aboutsummaryrefslogtreecommitdiff
path: root/src/windows/identity/plugins
diff options
context:
space:
mode:
authorJeffrey Altman <jaltman@secure-endpoints.com>2005-11-02 01:14:30 +0000
committerJeffrey Altman <jaltman@secure-endpoints.com>2005-11-02 01:14:30 +0000
commit5c27b523150384dd8655e739d68f01be2e4ff5d4 (patch)
tree649928f66dba979d1a84a9317b83a678e8321889 /src/windows/identity/plugins
parent5aa72f089113f917694a20144dca42049951c4da (diff)
downloadkrb5-5c27b523150384dd8655e739d68f01be2e4ff5d4.zip
krb5-5c27b523150384dd8655e739d68f01be2e4ff5d4.tar.gz
krb5-5c27b523150384dd8655e739d68f01be2e4ff5d4.tar.bz2
Initial Commit Network Identity Manager for Windows
Initial commit of Network Identity Manager for KFW 3.0 Beta 1 ticket: new tags: pullup component: windows git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@17476 dc483132-0cff-0310-8789-dd5450dbe970
Diffstat (limited to 'src/windows/identity/plugins')
-rw-r--r--src/windows/identity/plugins/common/Makefile42
-rw-r--r--src/windows/identity/plugins/common/dynimport.c420
-rw-r--r--src/windows/identity/plugins/common/dynimport.h338
-rw-r--r--src/windows/identity/plugins/common/krb5common.c156
-rw-r--r--src/windows/identity/plugins/common/krb5common.h43
-rw-r--r--src/windows/identity/plugins/krb4/Makefile78
-rw-r--r--src/windows/identity/plugins/krb4/datarep.h37
-rw-r--r--src/windows/identity/plugins/krb4/errorfuncs.c264
-rw-r--r--src/windows/identity/plugins/krb4/errorfuncs.h80
-rw-r--r--src/windows/identity/plugins/krb4/krb4configdlg.c88
-rw-r--r--src/windows/identity/plugins/krb4/krb4funcs.c505
-rw-r--r--src/windows/identity/plugins/krb4/krb4funcs.h190
-rw-r--r--src/windows/identity/plugins/krb4/krb4plugin.c164
-rw-r--r--src/windows/identity/plugins/krb4/krbconfig.csv23
-rw-r--r--src/windows/identity/plugins/krb4/krbcred.h114
-rw-r--r--src/windows/identity/plugins/krb4/lang/en_us/langres.rc141
-rw-r--r--src/windows/identity/plugins/krb4/langres.h78
-rw-r--r--src/windows/identity/plugins/krb4/main.c191
-rw-r--r--src/windows/identity/plugins/krb5/Makefile91
-rw-r--r--src/windows/identity/plugins/krb5/datarep.c269
-rw-r--r--src/windows/identity/plugins/krb5/datarep.h37
-rw-r--r--src/windows/identity/plugins/krb5/errorfuncs.c260
-rw-r--r--src/windows/identity/plugins/krb5/errorfuncs.h75
-rw-r--r--src/windows/identity/plugins/krb5/krb5configdlg.c421
-rw-r--r--src/windows/identity/plugins/krb5/krb5funcs.c1889
-rw-r--r--src/windows/identity/plugins/krb5/krb5funcs.h121
-rw-r--r--src/windows/identity/plugins/krb5/krb5identpro.c1108
-rw-r--r--src/windows/identity/plugins/krb5/krb5newcreds.c2167
-rw-r--r--src/windows/identity/plugins/krb5/krb5plugin.c230
-rw-r--r--src/windows/identity/plugins/krb5/krb5props.c117
-rw-r--r--src/windows/identity/plugins/krb5/krb5util.c1362
-rw-r--r--src/windows/identity/plugins/krb5/krbconfig.csv34
-rw-r--r--src/windows/identity/plugins/krb5/krbcred.h182
-rw-r--r--src/windows/identity/plugins/krb5/lang/en_us/langres.rc406
-rw-r--r--src/windows/identity/plugins/krb5/lang/krb5_msgs.mc151
-rw-r--r--src/windows/identity/plugins/krb5/langres.h127
-rw-r--r--src/windows/identity/plugins/krb5/main.c387
37 files changed, 12386 insertions, 0 deletions
diff --git a/src/windows/identity/plugins/common/Makefile b/src/windows/identity/plugins/common/Makefile
new file mode 100644
index 0000000..cbadbc6
--- /dev/null
+++ b/src/windows/identity/plugins/common/Makefile
@@ -0,0 +1,42 @@
+#
+# Copyright (c) 2004 Massachusetts Institute of Technology
+#
+# Permission is hereby granted, free of charge, to any person
+# obtaining a copy of this software and associated documentation files
+# (the "Software"), to deal in the Software without restriction,
+# including without limitation the rights to use, copy, modify, merge,
+# publish, distribute, sublicense, and/or sell copies of the Software,
+# and to permit persons to whom the Software is furnished to do so,
+# subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+
+
+MODULE=plugins\common
+!include <../../config/Makefile.w32>
+
+INCFILES= \
+ $(INCDIR)\krb5common.h \
+ $(INCDIR)\dynimport.h
+
+OBJFILES= \
+ $(LIBDIR)\krb5common.obj \
+ $(LIBDIR)\dynimport.obj
+
+all: mkdirs $(INCFILES) $(OBJFILES)
+
+clean::
+ $(RM) $(INCFILES)
+
+{}.c{$(LIBDIR)}.obj:
+ $(C2OBJ)
diff --git a/src/windows/identity/plugins/common/dynimport.c b/src/windows/identity/plugins/common/dynimport.c
new file mode 100644
index 0000000..cd33813
--- /dev/null
+++ b/src/windows/identity/plugins/common/dynimport.c
@@ -0,0 +1,420 @@
+/*
+* Copyright (c) 2004 Massachusetts Institute of Technology
+*
+* Permission is hereby granted, free of charge, to any person
+* obtaining a copy of this software and associated documentation
+* files (the "Software"), to deal in the Software without
+* restriction, including without limitation the rights to use, copy,
+* modify, merge, publish, distribute, sublicense, and/or sell copies
+* of the Software, and to permit persons to whom the Software is
+* furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be
+* included in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+* SOFTWARE.
+*/
+
+/* $Id$ */
+
+#include<windows.h>
+#include<khdefs.h>
+#include<kherror.h>
+#include<dynimport.h>
+
+HINSTANCE hKrb4 = 0;
+HINSTANCE hKrb5 = 0;
+HINSTANCE hKrb524 = 0;
+HINSTANCE hSecur32 = 0;
+HINSTANCE hComErr = 0;
+HINSTANCE hService = 0;
+HINSTANCE hProfile = 0;
+HINSTANCE hPsapi = 0;
+HINSTANCE hToolHelp32 = 0;
+HINSTANCE hCCAPI = 0;
+
+DWORD AfsAvailable = 0;
+
+// CCAPI
+DECL_FUNC_PTR(cc_initialize);
+DECL_FUNC_PTR(cc_shutdown);
+DECL_FUNC_PTR(cc_get_NC_info);
+DECL_FUNC_PTR(cc_free_NC_info);
+
+// krb4 functions
+DECL_FUNC_PTR(get_krb_err_txt_entry);
+DECL_FUNC_PTR(k_isinst);
+DECL_FUNC_PTR(k_isname);
+DECL_FUNC_PTR(k_isrealm);
+DECL_FUNC_PTR(kadm_change_your_password);
+DECL_FUNC_PTR(kname_parse);
+DECL_FUNC_PTR(krb_get_cred);
+DECL_FUNC_PTR(krb_get_krbhst);
+DECL_FUNC_PTR(krb_get_lrealm);
+DECL_FUNC_PTR(krb_get_pw_in_tkt);
+DECL_FUNC_PTR(krb_get_tf_realm);
+DECL_FUNC_PTR(krb_mk_req);
+DECL_FUNC_PTR(krb_realmofhost);
+DECL_FUNC_PTR(tf_init);
+DECL_FUNC_PTR(tf_close);
+DECL_FUNC_PTR(tf_get_cred);
+DECL_FUNC_PTR(tf_get_pname);
+DECL_FUNC_PTR(tf_get_pinst);
+DECL_FUNC_PTR(LocalHostAddr);
+DECL_FUNC_PTR(tkt_string);
+DECL_FUNC_PTR(krb_set_tkt_string);
+DECL_FUNC_PTR(initialize_krb_error_func);
+DECL_FUNC_PTR(initialize_kadm_error_table);
+DECL_FUNC_PTR(dest_tkt);
+DECL_FUNC_PTR(krb_in_tkt);
+DECL_FUNC_PTR(krb_save_credentials);
+DECL_FUNC_PTR(krb_get_krbconf2);
+DECL_FUNC_PTR(krb_get_krbrealm2);
+DECL_FUNC_PTR(krb_life_to_time);
+
+// krb5 functions
+DECL_FUNC_PTR(krb5_change_password);
+DECL_FUNC_PTR(krb5_get_init_creds_opt_init);
+DECL_FUNC_PTR(krb5_get_init_creds_opt_set_tkt_life);
+DECL_FUNC_PTR(krb5_get_init_creds_opt_set_renew_life);
+DECL_FUNC_PTR(krb5_get_init_creds_opt_set_forwardable);
+DECL_FUNC_PTR(krb5_get_init_creds_opt_set_proxiable);
+DECL_FUNC_PTR(krb5_get_init_creds_opt_set_address_list);
+DECL_FUNC_PTR(krb5_get_init_creds_password);
+DECL_FUNC_PTR(krb5_get_prompt_types);
+DECL_FUNC_PTR(krb5_build_principal_ext);
+DECL_FUNC_PTR(krb5_cc_get_name);
+DECL_FUNC_PTR(krb5_cc_resolve);
+DECL_FUNC_PTR(krb5_cc_default);
+DECL_FUNC_PTR(krb5_cc_default_name);
+DECL_FUNC_PTR(krb5_cc_set_default_name);
+DECL_FUNC_PTR(krb5_cc_initialize);
+DECL_FUNC_PTR(krb5_cc_destroy);
+DECL_FUNC_PTR(krb5_cc_close);
+DECL_FUNC_PTR(krb5_cc_store_cred);
+DECL_FUNC_PTR(krb5_cc_copy_creds);
+DECL_FUNC_PTR(krb5_cc_retrieve_cred);
+DECL_FUNC_PTR(krb5_cc_get_principal);
+DECL_FUNC_PTR(krb5_cc_start_seq_get);
+DECL_FUNC_PTR(krb5_cc_next_cred);
+DECL_FUNC_PTR(krb5_cc_end_seq_get);
+DECL_FUNC_PTR(krb5_cc_remove_cred);
+DECL_FUNC_PTR(krb5_cc_set_flags);
+// DECL_FUNC_PTR(krb5_cc_get_type);
+DECL_FUNC_PTR(krb5_free_context);
+DECL_FUNC_PTR(krb5_free_cred_contents);
+DECL_FUNC_PTR(krb5_free_principal);
+DECL_FUNC_PTR(krb5_get_in_tkt_with_password);
+DECL_FUNC_PTR(krb5_init_context);
+DECL_FUNC_PTR(krb5_parse_name);
+DECL_FUNC_PTR(krb5_timeofday);
+DECL_FUNC_PTR(krb5_timestamp_to_sfstring);
+DECL_FUNC_PTR(krb5_unparse_name);
+DECL_FUNC_PTR(krb5_get_credentials);
+DECL_FUNC_PTR(krb5_mk_req);
+DECL_FUNC_PTR(krb5_sname_to_principal);
+DECL_FUNC_PTR(krb5_get_credentials_renew);
+DECL_FUNC_PTR(krb5_free_data);
+DECL_FUNC_PTR(krb5_free_data_contents);
+// DECL_FUNC_PTR(krb5_get_realm_domain);
+DECL_FUNC_PTR(krb5_free_unparsed_name);
+DECL_FUNC_PTR(krb5_os_localaddr);
+DECL_FUNC_PTR(krb5_copy_keyblock_contents);
+DECL_FUNC_PTR(krb5_copy_data);
+DECL_FUNC_PTR(krb5_free_creds);
+DECL_FUNC_PTR(krb5_build_principal);
+DECL_FUNC_PTR(krb5_get_renewed_creds);
+DECL_FUNC_PTR(krb5_get_default_config_files);
+DECL_FUNC_PTR(krb5_free_config_files);
+DECL_FUNC_PTR(krb5_get_default_realm);
+DECL_FUNC_PTR(krb5_free_ticket);
+DECL_FUNC_PTR(krb5_decode_ticket);
+DECL_FUNC_PTR(krb5_get_host_realm);
+DECL_FUNC_PTR(krb5_free_host_realm);
+DECL_FUNC_PTR(krb5_c_random_make_octets);
+DECL_FUNC_PTR(krb5_free_addresses);
+DECL_FUNC_PTR(krb5_free_default_realm);
+
+// Krb524 functions
+DECL_FUNC_PTR(krb524_init_ets);
+DECL_FUNC_PTR(krb524_convert_creds_kdc);
+
+// ComErr functions
+DECL_FUNC_PTR(com_err);
+DECL_FUNC_PTR(error_message);
+
+// Profile functions
+DECL_FUNC_PTR(profile_init);
+DECL_FUNC_PTR(profile_release);
+DECL_FUNC_PTR(profile_get_subsection_names);
+DECL_FUNC_PTR(profile_free_list);
+DECL_FUNC_PTR(profile_get_string);
+DECL_FUNC_PTR(profile_release_string);
+
+// Service functions
+DECL_FUNC_PTR(OpenSCManagerA);
+DECL_FUNC_PTR(OpenServiceA);
+DECL_FUNC_PTR(QueryServiceStatus);
+DECL_FUNC_PTR(CloseServiceHandle);
+DECL_FUNC_PTR(LsaNtStatusToWinError);
+
+// LSA Functions
+DECL_FUNC_PTR(LsaConnectUntrusted);
+DECL_FUNC_PTR(LsaLookupAuthenticationPackage);
+DECL_FUNC_PTR(LsaCallAuthenticationPackage);
+DECL_FUNC_PTR(LsaFreeReturnBuffer);
+DECL_FUNC_PTR(LsaGetLogonSessionData);
+
+// CCAPI
+FUNC_INFO ccapi_fi[] = {
+ MAKE_FUNC_INFO(cc_initialize),
+ MAKE_FUNC_INFO(cc_shutdown),
+ MAKE_FUNC_INFO(cc_get_NC_info),
+ MAKE_FUNC_INFO(cc_free_NC_info),
+ END_FUNC_INFO
+};
+
+FUNC_INFO k4_fi[] = {
+ MAKE_FUNC_INFO(get_krb_err_txt_entry),
+ MAKE_FUNC_INFO(k_isinst),
+ MAKE_FUNC_INFO(k_isname),
+ MAKE_FUNC_INFO(k_isrealm),
+ MAKE_FUNC_INFO(kadm_change_your_password),
+ MAKE_FUNC_INFO(kname_parse),
+ MAKE_FUNC_INFO(krb_get_cred),
+ MAKE_FUNC_INFO(krb_get_krbhst),
+ MAKE_FUNC_INFO(krb_get_lrealm),
+ MAKE_FUNC_INFO(krb_get_pw_in_tkt),
+ MAKE_FUNC_INFO(krb_get_tf_realm),
+ MAKE_FUNC_INFO(krb_mk_req),
+ MAKE_FUNC_INFO(krb_realmofhost),
+ MAKE_FUNC_INFO(tf_init),
+ MAKE_FUNC_INFO(tf_close),
+ MAKE_FUNC_INFO(tf_get_cred),
+ MAKE_FUNC_INFO(tf_get_pname),
+ MAKE_FUNC_INFO(tf_get_pinst),
+ MAKE_FUNC_INFO(LocalHostAddr),
+ MAKE_FUNC_INFO(tkt_string),
+ MAKE_FUNC_INFO(krb_set_tkt_string),
+ MAKE_FUNC_INFO(initialize_krb_error_func),
+ MAKE_FUNC_INFO(initialize_kadm_error_table),
+ MAKE_FUNC_INFO(dest_tkt),
+ /* MAKE_FUNC_INFO(lsh_LoadKrb4LeashErrorTables), */// XXX
+ MAKE_FUNC_INFO(krb_in_tkt),
+ MAKE_FUNC_INFO(krb_save_credentials),
+ MAKE_FUNC_INFO(krb_get_krbconf2),
+ MAKE_FUNC_INFO(krb_get_krbrealm2),
+ MAKE_FUNC_INFO(krb_life_to_time),
+ END_FUNC_INFO
+};
+
+FUNC_INFO k5_fi[] = {
+ MAKE_FUNC_INFO(krb5_change_password),
+ MAKE_FUNC_INFO(krb5_get_init_creds_opt_init),
+ MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_tkt_life),
+ MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_renew_life),
+ MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_forwardable),
+ MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_proxiable),
+ MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_address_list),
+ MAKE_FUNC_INFO(krb5_get_init_creds_password),
+ MAKE_FUNC_INFO(krb5_get_prompt_types),
+ MAKE_FUNC_INFO(krb5_build_principal_ext),
+ MAKE_FUNC_INFO(krb5_cc_get_name),
+ MAKE_FUNC_INFO(krb5_cc_resolve),
+ MAKE_FUNC_INFO(krb5_cc_default),
+ MAKE_FUNC_INFO(krb5_cc_default_name),
+ MAKE_FUNC_INFO(krb5_cc_set_default_name),
+ MAKE_FUNC_INFO(krb5_cc_initialize),
+ MAKE_FUNC_INFO(krb5_cc_destroy),
+ MAKE_FUNC_INFO(krb5_cc_close),
+ MAKE_FUNC_INFO(krb5_cc_copy_creds),
+ MAKE_FUNC_INFO(krb5_cc_store_cred),
+ MAKE_FUNC_INFO(krb5_cc_retrieve_cred),
+ MAKE_FUNC_INFO(krb5_cc_get_principal),
+ MAKE_FUNC_INFO(krb5_cc_start_seq_get),
+ MAKE_FUNC_INFO(krb5_cc_next_cred),
+ MAKE_FUNC_INFO(krb5_cc_end_seq_get),
+ MAKE_FUNC_INFO(krb5_cc_remove_cred),
+ MAKE_FUNC_INFO(krb5_cc_set_flags),
+ // MAKE_FUNC_INFO(krb5_cc_get_type),
+ MAKE_FUNC_INFO(krb5_free_context),
+ MAKE_FUNC_INFO(krb5_free_cred_contents),
+ MAKE_FUNC_INFO(krb5_free_principal),
+ MAKE_FUNC_INFO(krb5_get_in_tkt_with_password),
+ MAKE_FUNC_INFO(krb5_init_context),
+ MAKE_FUNC_INFO(krb5_parse_name),
+ MAKE_FUNC_INFO(krb5_timeofday),
+ MAKE_FUNC_INFO(krb5_timestamp_to_sfstring),
+ MAKE_FUNC_INFO(krb5_unparse_name),
+ MAKE_FUNC_INFO(krb5_get_credentials),
+ MAKE_FUNC_INFO(krb5_mk_req),
+ MAKE_FUNC_INFO(krb5_sname_to_principal),
+ MAKE_FUNC_INFO(krb5_get_credentials_renew),
+ MAKE_FUNC_INFO(krb5_free_data),
+ MAKE_FUNC_INFO(krb5_free_data_contents),
+ // MAKE_FUNC_INFO(krb5_get_realm_domain),
+ MAKE_FUNC_INFO(krb5_free_unparsed_name),
+ MAKE_FUNC_INFO(krb5_os_localaddr),
+ MAKE_FUNC_INFO(krb5_copy_keyblock_contents),
+ MAKE_FUNC_INFO(krb5_copy_data),
+ MAKE_FUNC_INFO(krb5_free_creds),
+ MAKE_FUNC_INFO(krb5_build_principal),
+ MAKE_FUNC_INFO(krb5_get_renewed_creds),
+ MAKE_FUNC_INFO(krb5_free_addresses),
+ MAKE_FUNC_INFO(krb5_get_default_config_files),
+ MAKE_FUNC_INFO(krb5_free_config_files),
+ MAKE_FUNC_INFO(krb5_get_default_realm),
+ MAKE_FUNC_INFO(krb5_free_ticket),
+ MAKE_FUNC_INFO(krb5_decode_ticket),
+ MAKE_FUNC_INFO(krb5_get_host_realm),
+ MAKE_FUNC_INFO(krb5_free_host_realm),
+ MAKE_FUNC_INFO(krb5_c_random_make_octets),
+ MAKE_FUNC_INFO(krb5_free_default_realm),
+ END_FUNC_INFO
+};
+
+FUNC_INFO k524_fi[] = {
+ MAKE_FUNC_INFO(krb524_init_ets),
+ MAKE_FUNC_INFO(krb524_convert_creds_kdc),
+ END_FUNC_INFO
+};
+
+FUNC_INFO profile_fi[] = {
+ MAKE_FUNC_INFO(profile_init),
+ MAKE_FUNC_INFO(profile_release),
+ MAKE_FUNC_INFO(profile_get_subsection_names),
+ MAKE_FUNC_INFO(profile_free_list),
+ MAKE_FUNC_INFO(profile_get_string),
+ MAKE_FUNC_INFO(profile_release_string),
+ END_FUNC_INFO
+};
+
+FUNC_INFO ce_fi[] = {
+ MAKE_FUNC_INFO(com_err),
+ MAKE_FUNC_INFO(error_message),
+ END_FUNC_INFO
+};
+
+FUNC_INFO service_fi[] = {
+ MAKE_FUNC_INFO(OpenSCManagerA),
+ MAKE_FUNC_INFO(OpenServiceA),
+ MAKE_FUNC_INFO(QueryServiceStatus),
+ MAKE_FUNC_INFO(CloseServiceHandle),
+ MAKE_FUNC_INFO(LsaNtStatusToWinError),
+ END_FUNC_INFO
+};
+
+FUNC_INFO lsa_fi[] = {
+ MAKE_FUNC_INFO(LsaConnectUntrusted),
+ MAKE_FUNC_INFO(LsaLookupAuthenticationPackage),
+ MAKE_FUNC_INFO(LsaCallAuthenticationPackage),
+ MAKE_FUNC_INFO(LsaFreeReturnBuffer),
+ MAKE_FUNC_INFO(LsaGetLogonSessionData),
+ END_FUNC_INFO
+};
+
+// psapi functions
+DECL_FUNC_PTR(GetModuleFileNameExA);
+DECL_FUNC_PTR(EnumProcessModules);
+
+FUNC_INFO psapi_fi[] = {
+ MAKE_FUNC_INFO(GetModuleFileNameExA),
+ MAKE_FUNC_INFO(EnumProcessModules),
+ END_FUNC_INFO
+};
+
+// toolhelp functions
+DECL_FUNC_PTR(CreateToolhelp32Snapshot);
+DECL_FUNC_PTR(Module32First);
+DECL_FUNC_PTR(Module32Next);
+
+FUNC_INFO toolhelp_fi[] = {
+ MAKE_FUNC_INFO(CreateToolhelp32Snapshot),
+ MAKE_FUNC_INFO(Module32First),
+ MAKE_FUNC_INFO(Module32Next),
+ END_FUNC_INFO
+};
+
+khm_int32 init_imports(void) {
+ OSVERSIONINFO osvi;
+
+ LoadFuncs(KRB4_DLL, k4_fi, &hKrb4, 0, 1, 0, 0);
+ LoadFuncs(KRB5_DLL, k5_fi, &hKrb5, 0, 1, 0, 0);
+ LoadFuncs(COMERR_DLL, ce_fi, &hComErr, 0, 0, 1, 0);
+ LoadFuncs(SERVICE_DLL, service_fi, &hService, 0, 1, 0, 0);
+ LoadFuncs(SECUR32_DLL, lsa_fi, &hSecur32, 0, 1, 1, 1);
+ LoadFuncs(KRB524_DLL, k524_fi, &hKrb524, 0, 1, 1, 1);
+ LoadFuncs(PROFILE_DLL, profile_fi, &hProfile, 0, 1, 0, 0);
+ LoadFuncs(CCAPI_DLL, ccapi_fi, &hCCAPI, 0, 1, 0, 0);
+
+ memset(&osvi, 0, sizeof(OSVERSIONINFO));
+ osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
+ GetVersionEx(&osvi);
+
+ // XXX: We should really use feature testing, first
+ // checking for CreateToolhelp32Snapshot. If that's
+ // not around, we try the psapi stuff.
+ //
+ // Only load LSA functions if on NT/2000/XP
+ if(osvi.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)
+ {
+ // Windows 9x
+ LoadFuncs(TOOLHELPDLL, toolhelp_fi, &hToolHelp32, 0, 1, 0, 0);
+ hPsapi = 0;
+ }
+ else if(osvi.dwPlatformId == VER_PLATFORM_WIN32_NT)
+ {
+ // Windows NT
+ LoadFuncs(PSAPIDLL, psapi_fi, &hPsapi, 0, 1, 0, 0);
+ hToolHelp32 = 0;
+ }
+
+ AfsAvailable = TRUE; //afscompat_init();
+
+ return KHM_ERROR_SUCCESS;
+}
+
+khm_int32 exit_imports(void) {
+ //afscompat_close();
+
+ if (hKrb4)
+ FreeLibrary(hKrb4);
+ if (hKrb5)
+ FreeLibrary(hKrb5);
+ if (hProfile)
+ FreeLibrary(hProfile);
+ if (hComErr)
+ FreeLibrary(hComErr);
+ if (hService)
+ FreeLibrary(hService);
+ if (hSecur32)
+ FreeLibrary(hSecur32);
+ if (hKrb524)
+ FreeLibrary(hKrb524);
+ if (hPsapi)
+ FreeLibrary(hPsapi);
+ if (hToolHelp32)
+ FreeLibrary(hToolHelp32);
+
+ return KHM_ERROR_SUCCESS;
+}
+
+int (*Lcom_err)(LPSTR,long,LPSTR,...);
+LPSTR (*Lerror_message)(long);
+LPSTR (*Lerror_table_name)(long);
+
+void Leash_load_com_err_callback(FARPROC ce,
+ FARPROC em,
+ FARPROC etn)
+{
+ (FARPROC)Lcom_err=ce;
+ (FARPROC)Lerror_message=em;
+ (FARPROC)Lerror_table_name=etn;
+}
diff --git a/src/windows/identity/plugins/common/dynimport.h b/src/windows/identity/plugins/common/dynimport.h
new file mode 100644
index 0000000..b3ba225
--- /dev/null
+++ b/src/windows/identity/plugins/common/dynimport.h
@@ -0,0 +1,338 @@
+/*
+ * Copyright (c) 2004 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#ifndef __KHIMAIRA_DYNIMPORT_H
+#define __KHIMAIRA_DYNIMPORT_H
+
+/* Dynamic imports */
+#include<khdefs.h>
+#include<tlhelp32.h>
+#include<ntsecapi.h>
+
+extern HINSTANCE hKrb4;
+extern HINSTANCE hKrb5;
+extern HINSTANCE hProfile;
+
+///////////////////////////////////////////////////////////////////////////////
+
+#define CCAPI_DLL "krbcc32.dll"
+#define KRBCC32_DLL "krbcc32.dll"
+#define SERVICE_DLL "advapi32.dll"
+#define SECUR32_DLL "secur32.dll"
+#define PROFILE_DLL "xpprof32.dll"
+
+//////////////////////////////////////////////////////////////////////////////
+
+#include <loadfuncs-com_err.h>
+#include <loadfuncs-krb5.h>
+#include <loadfuncs-profile.h>
+#include <loadfuncs-krb.h>
+#include <loadfuncs-krb524.h>
+#include <loadfuncs-lsa.h>
+
+//// CCAPI
+/* In order to avoid including the private CCAPI headers */
+typedef int cc_int32;
+
+#define CC_API_VER_1 1
+#define CC_API_VER_2 2
+
+#define CCACHE_API cc_int32
+
+/*
+** The Official Error Codes
+*/
+#define CC_NOERROR 0
+#define CC_BADNAME 1
+#define CC_NOTFOUND 2
+#define CC_END 3
+#define CC_IO 4
+#define CC_WRITE 5
+#define CC_NOMEM 6
+#define CC_FORMAT 7
+#define CC_LOCKED 8
+#define CC_BAD_API_VERSION 9
+#define CC_NO_EXIST 10
+#define CC_NOT_SUPP 11
+#define CC_BAD_PARM 12
+#define CC_ERR_CACHE_ATTACH 13
+#define CC_ERR_CACHE_RELEASE 14
+#define CC_ERR_CACHE_FULL 15
+#define CC_ERR_CRED_VERSION 16
+
+enum {
+ CC_CRED_VUNKNOWN = 0, // For validation
+ CC_CRED_V4 = 1,
+ CC_CRED_V5 = 2,
+ CC_CRED_VMAX = 3 // For validation
+};
+
+typedef struct opaque_dll_control_block_type* apiCB;
+typedef struct _infoNC {
+ char* name;
+ char* principal;
+ cc_int32 vers;
+} infoNC;
+
+TYPEDEF_FUNC(
+CCACHE_API,
+CALLCONV_C,
+cc_initialize,
+ (
+ apiCB** cc_ctx, // < DLL's primary control structure.
+ // returned here, passed everywhere else
+ cc_int32 api_version, // > ver supported by caller (use CC_API_VER_1)
+ cc_int32* api_supported, // < if ~NULL, max ver supported by DLL
+ const char** vendor // < if ~NULL, vendor name in read only C string
+ )
+);
+
+TYPEDEF_FUNC(
+CCACHE_API,
+CALLCONV_C,
+cc_shutdown,
+ (
+ apiCB** cc_ctx // <> DLL's primary control structure. NULL after
+ )
+);
+
+TYPEDEF_FUNC(
+CCACHE_API,
+CALLCONV_C,
+cc_get_NC_info,
+ (
+ apiCB* cc_ctx, // > DLL's primary control structure
+ struct _infoNC*** ppNCi // < (NULL before call) null terminated,
+ // list of a structs (free via cc_free_infoNC())
+ )
+);
+
+TYPEDEF_FUNC(
+CCACHE_API,
+CALLCONV_C,
+cc_free_NC_info,
+ (
+ apiCB* cc_ctx,
+ struct _infoNC*** ppNCi // < free list of structs returned by
+ // cc_get_cache_names(). set to NULL on return
+ )
+);
+//// \CCAPI
+
+extern DWORD AfsAvailable;
+
+// service definitions
+typedef SC_HANDLE (WINAPI *FP_OpenSCManagerA)(char *, char *, DWORD);
+typedef SC_HANDLE (WINAPI *FP_OpenServiceA)(SC_HANDLE, char *, DWORD);
+typedef BOOL (WINAPI *FP_QueryServiceStatus)(SC_HANDLE, LPSERVICE_STATUS);
+typedef BOOL (WINAPI *FP_CloseServiceHandle)(SC_HANDLE);
+
+//////////////////////////////////////////////////////////////////////////////
+
+// CCAPI
+extern DECL_FUNC_PTR(cc_initialize);
+extern DECL_FUNC_PTR(cc_shutdown);
+extern DECL_FUNC_PTR(cc_get_NC_info);
+extern DECL_FUNC_PTR(cc_free_NC_info);
+
+// krb4 functions
+extern DECL_FUNC_PTR(get_krb_err_txt_entry);
+extern DECL_FUNC_PTR(k_isinst);
+extern DECL_FUNC_PTR(k_isname);
+extern DECL_FUNC_PTR(k_isrealm);
+extern DECL_FUNC_PTR(kadm_change_your_password);
+extern DECL_FUNC_PTR(kname_parse);
+extern DECL_FUNC_PTR(krb_get_cred);
+extern DECL_FUNC_PTR(krb_get_krbhst);
+extern DECL_FUNC_PTR(krb_get_lrealm);
+extern DECL_FUNC_PTR(krb_get_pw_in_tkt);
+extern DECL_FUNC_PTR(krb_get_tf_realm);
+extern DECL_FUNC_PTR(krb_mk_req);
+extern DECL_FUNC_PTR(krb_realmofhost);
+extern DECL_FUNC_PTR(tf_init);
+extern DECL_FUNC_PTR(tf_close);
+extern DECL_FUNC_PTR(tf_get_cred);
+extern DECL_FUNC_PTR(tf_get_pname);
+extern DECL_FUNC_PTR(tf_get_pinst);
+extern DECL_FUNC_PTR(LocalHostAddr);
+extern DECL_FUNC_PTR(tkt_string);
+extern DECL_FUNC_PTR(krb_set_tkt_string);
+extern DECL_FUNC_PTR(initialize_krb_error_func);
+extern DECL_FUNC_PTR(initialize_kadm_error_table);
+extern DECL_FUNC_PTR(dest_tkt);
+extern DECL_FUNC_PTR(lsh_LoadKrb4LeashErrorTables); // XXX
+extern DECL_FUNC_PTR(krb_in_tkt);
+extern DECL_FUNC_PTR(krb_save_credentials);
+extern DECL_FUNC_PTR(krb_get_krbconf2);
+extern DECL_FUNC_PTR(krb_get_krbrealm2);
+extern DECL_FUNC_PTR(krb_life_to_time);
+
+// krb5 functions
+extern DECL_FUNC_PTR(krb5_change_password);
+extern DECL_FUNC_PTR(krb5_get_init_creds_opt_init);
+extern DECL_FUNC_PTR(krb5_get_init_creds_opt_set_tkt_life);
+extern DECL_FUNC_PTR(krb5_get_init_creds_opt_set_renew_life);
+extern DECL_FUNC_PTR(krb5_get_init_creds_opt_set_forwardable);
+extern DECL_FUNC_PTR(krb5_get_init_creds_opt_set_proxiable);
+extern DECL_FUNC_PTR(krb5_get_init_creds_opt_set_renew_life);
+extern DECL_FUNC_PTR(krb5_get_init_creds_opt_set_address_list);
+extern DECL_FUNC_PTR(krb5_get_init_creds_password);
+extern DECL_FUNC_PTR(krb5_get_prompt_types);
+extern DECL_FUNC_PTR(krb5_build_principal_ext);
+extern DECL_FUNC_PTR(krb5_cc_get_name);
+extern DECL_FUNC_PTR(krb5_cc_resolve);
+extern DECL_FUNC_PTR(krb5_cc_default);
+extern DECL_FUNC_PTR(krb5_cc_default_name);
+extern DECL_FUNC_PTR(krb5_cc_set_default_name);
+extern DECL_FUNC_PTR(krb5_cc_initialize);
+extern DECL_FUNC_PTR(krb5_cc_destroy);
+extern DECL_FUNC_PTR(krb5_cc_close);
+extern DECL_FUNC_PTR(krb5_cc_copy_creds);
+extern DECL_FUNC_PTR(krb5_cc_store_cred);
+extern DECL_FUNC_PTR(krb5_cc_retrieve_cred);
+extern DECL_FUNC_PTR(krb5_cc_get_principal);
+extern DECL_FUNC_PTR(krb5_cc_start_seq_get);
+extern DECL_FUNC_PTR(krb5_cc_next_cred);
+extern DECL_FUNC_PTR(krb5_cc_end_seq_get);
+extern DECL_FUNC_PTR(krb5_cc_remove_cred);
+extern DECL_FUNC_PTR(krb5_cc_set_flags);
+// extern DECL_FUNC_PTR(krb5_cc_get_type);
+extern DECL_FUNC_PTR(krb5_free_context);
+extern DECL_FUNC_PTR(krb5_free_cred_contents);
+extern DECL_FUNC_PTR(krb5_free_principal);
+extern DECL_FUNC_PTR(krb5_get_in_tkt_with_password);
+extern DECL_FUNC_PTR(krb5_init_context);
+extern DECL_FUNC_PTR(krb5_parse_name);
+extern DECL_FUNC_PTR(krb5_timeofday);
+extern DECL_FUNC_PTR(krb5_timestamp_to_sfstring);
+extern DECL_FUNC_PTR(krb5_unparse_name);
+extern DECL_FUNC_PTR(krb5_get_credentials);
+extern DECL_FUNC_PTR(krb5_mk_req);
+extern DECL_FUNC_PTR(krb5_sname_to_principal);
+extern DECL_FUNC_PTR(krb5_get_credentials_renew);
+extern DECL_FUNC_PTR(krb5_free_data);
+extern DECL_FUNC_PTR(krb5_free_data_contents);
+// extern DECL_FUNC_PTR(krb5_get_realm_domain);
+extern DECL_FUNC_PTR(krb5_free_unparsed_name);
+extern DECL_FUNC_PTR(krb5_os_localaddr);
+extern DECL_FUNC_PTR(krb5_copy_keyblock_contents);
+extern DECL_FUNC_PTR(krb5_copy_data);
+extern DECL_FUNC_PTR(krb5_free_creds);
+extern DECL_FUNC_PTR(krb5_build_principal);
+extern DECL_FUNC_PTR(krb5_get_renewed_creds);
+extern DECL_FUNC_PTR(krb5_free_addresses);
+extern DECL_FUNC_PTR(krb5_get_default_config_files);
+extern DECL_FUNC_PTR(krb5_free_config_files);
+extern DECL_FUNC_PTR(krb5_get_default_realm);
+extern DECL_FUNC_PTR(krb5_free_ticket);
+extern DECL_FUNC_PTR(krb5_decode_ticket);
+extern DECL_FUNC_PTR(krb5_get_host_realm);
+extern DECL_FUNC_PTR(krb5_free_host_realm);
+extern DECL_FUNC_PTR(krb5_c_random_make_octets);
+extern DECL_FUNC_PTR(krb5_free_default_realm);
+
+// Krb524 functions
+extern DECL_FUNC_PTR(krb524_init_ets);
+extern DECL_FUNC_PTR(krb524_convert_creds_kdc);
+
+// ComErr functions
+extern DECL_FUNC_PTR(com_err);
+extern DECL_FUNC_PTR(error_message);
+
+// Profile functions
+extern DECL_FUNC_PTR(profile_init);
+extern DECL_FUNC_PTR(profile_release);
+extern DECL_FUNC_PTR(profile_get_subsection_names);
+extern DECL_FUNC_PTR(profile_free_list);
+extern DECL_FUNC_PTR(profile_get_string);
+extern DECL_FUNC_PTR(profile_release_string);
+
+// Service functions
+extern DECL_FUNC_PTR(OpenSCManagerA);
+extern DECL_FUNC_PTR(OpenServiceA);
+extern DECL_FUNC_PTR(QueryServiceStatus);
+extern DECL_FUNC_PTR(CloseServiceHandle);
+extern DECL_FUNC_PTR(LsaNtStatusToWinError);
+
+// LSA Functions
+extern DECL_FUNC_PTR(LsaConnectUntrusted);
+extern DECL_FUNC_PTR(LsaLookupAuthenticationPackage);
+extern DECL_FUNC_PTR(LsaCallAuthenticationPackage);
+extern DECL_FUNC_PTR(LsaFreeReturnBuffer);
+extern DECL_FUNC_PTR(LsaGetLogonSessionData);
+
+// toolhelp functions
+TYPEDEF_FUNC(
+ HANDLE,
+ WINAPI,
+ CreateToolhelp32Snapshot,
+ (DWORD, DWORD)
+ );
+TYPEDEF_FUNC(
+ BOOL,
+ WINAPI,
+ Module32First,
+ (HANDLE, LPMODULEENTRY32)
+ );
+TYPEDEF_FUNC(
+ BOOL,
+ WINAPI,
+ Module32Next,
+ (HANDLE, LPMODULEENTRY32)
+ );
+
+// psapi functions
+TYPEDEF_FUNC(
+ DWORD,
+ WINAPI,
+ GetModuleFileNameExA,
+ (HANDLE, HMODULE, LPSTR, DWORD)
+ );
+
+TYPEDEF_FUNC(
+ BOOL,
+ WINAPI,
+ EnumProcessModules,
+ (HANDLE, HMODULE*, DWORD, LPDWORD)
+ );
+
+#define pGetModuleFileNameEx pGetModuleFileNameExA
+#define TOOLHELPDLL "kernel32.dll"
+#define PSAPIDLL "psapi.dll"
+
+// psapi functions
+extern DECL_FUNC_PTR(GetModuleFileNameExA);
+extern DECL_FUNC_PTR(EnumProcessModules);
+
+// toolhelp functions
+extern DECL_FUNC_PTR(CreateToolhelp32Snapshot);
+extern DECL_FUNC_PTR(Module32First);
+extern DECL_FUNC_PTR(Module32Next);
+
+khm_int32 init_imports(void);
+khm_int32 exit_imports(void);
+
+#endif
diff --git a/src/windows/identity/plugins/common/krb5common.c b/src/windows/identity/plugins/common/krb5common.c
new file mode 100644
index 0000000..5501a12
--- /dev/null
+++ b/src/windows/identity/plugins/common/krb5common.c
@@ -0,0 +1,156 @@
+/*
+ * Copyright (c) 2004 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#include<windows.h>
+#include<kcreddb.h>
+#include<kherror.h>
+#include<dynimport.h>
+
+/**************************************/
+/* khm_krb5_error(): */
+/**************************************/
+int
+khm_krb5_error(krb5_error_code rc, LPCSTR FailedFunctionName,
+ int FreeContextFlag, krb5_context * ctx,
+ krb5_ccache * cache)
+{
+#ifdef NO_KRB5
+ return 0;
+#else
+
+#ifdef SHOW_MESSAGE_IN_AN_ANNOYING_WAY
+ char message[256];
+ const char *errText;
+ int krb5Error = ((int)(rc & 255));
+
+ errText = perror_message(rc);
+ _snprintf(message, sizeof(message),
+ "%s\n(Kerberos error %ld)\n\n%s failed",
+ errText,
+ krb5Error,
+ FailedFunctionName);
+
+ MessageBoxA(NULL, message, "Kerberos Five", MB_OK | MB_ICONERROR |
+ MB_TASKMODAL |
+ MB_SETFOREGROUND);
+#endif
+
+ if (FreeContextFlag == 1)
+ {
+ if (*ctx != NULL)
+ {
+ if (*cache != NULL) {
+ pkrb5_cc_close(*ctx, *cache);
+ *cache = NULL;
+ }
+
+ pkrb5_free_context(*ctx);
+ *ctx = NULL;
+ }
+ }
+
+ return rc;
+
+#endif //!NO_KRB5
+}
+
+int
+khm_krb5_initialize(khm_handle ident,
+ krb5_context *ctx,
+ krb5_ccache *cache)
+{
+#ifdef NO_KRB5
+ return(0);
+#else
+
+ LPCSTR functionName;
+ int freeContextFlag;
+ krb5_error_code rc;
+ krb5_flags flags = 0;
+
+ if (pkrb5_init_context == NULL)
+ return 1;
+
+ if (*ctx == 0 && (rc = (*pkrb5_init_context)(ctx)))
+ {
+ functionName = "krb5_init_context()";
+ freeContextFlag = 0;
+ goto on_error;
+ }
+
+ if(*cache == 0) {
+ wchar_t wccname[256];
+ khm_size cbwccname;
+
+ if(ident != NULL) {
+ cbwccname = sizeof(wccname);
+ do {
+ char ccname[256];
+
+ if(KHM_FAILED(kcdb_identity_get_attrib(ident, L"Krb5CCName", NULL, wccname, &cbwccname)))
+ break;
+
+ if(UnicodeStrToAnsi(ccname, sizeof(ccname), wccname) == 0)
+ break;
+
+ if((*pkrb5_cc_resolve)(*ctx, ccname, cache)) {
+ functionName = "krb5_cc_resolve()";
+ freeContextFlag = 1;
+ goto on_error;
+ }
+ } while(FALSE);
+ }
+
+ if (*cache == 0 && (rc = (*pkrb5_cc_default)(*ctx, cache)))
+ {
+ functionName = "krb5_cc_default()";
+ freeContextFlag = 1;
+ goto on_error;
+ }
+ }
+
+#ifdef KRB5_TC_NOTICKET
+ flags = KRB5_TC_NOTICKET;
+#endif
+
+ if ((rc = (*pkrb5_cc_set_flags)(*ctx, *cache, flags)))
+ {
+ if (rc != KRB5_FCC_NOFILE && rc != KRB5_CC_NOTFOUND)
+ khm_krb5_error(rc, "krb5_cc_set_flags()", 0, ctx,
+ cache);
+ else if ((rc == KRB5_FCC_NOFILE || rc == KRB5_CC_NOTFOUND) && *ctx != NULL)
+ {
+ if (*cache != NULL)
+ (*pkrb5_cc_close)(*ctx, *cache);
+ }
+ return rc;
+ }
+ return 0;
+
+on_error:
+ return khm_krb5_error(rc, functionName, freeContextFlag, ctx, cache);
+#endif //!NO_KRB5
+}
diff --git a/src/windows/identity/plugins/common/krb5common.h b/src/windows/identity/plugins/common/krb5common.h
new file mode 100644
index 0000000..7d99821
--- /dev/null
+++ b/src/windows/identity/plugins/common/krb5common.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2004 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+/* Adapted from multiple Leash header files */
+
+#ifndef __KHIMAIRA_KRB5COMMON_H
+#define __KHIMAIRA_KRB5COMMON_H
+
+#include<krb5.h>
+
+#ifndef NO_KRB5
+int khm_krb5_error(krb5_error_code rc, LPCSTR FailedFunctionName,
+ int FreeContextFlag, krb5_context *ctx,
+ krb5_ccache *cache);
+
+
+int khm_krb5_initialize(khm_handle ident, krb5_context *, krb5_ccache *);
+#endif /* NO_KRB5 */
+
+#endif \ No newline at end of file
diff --git a/src/windows/identity/plugins/krb4/Makefile b/src/windows/identity/plugins/krb4/Makefile
new file mode 100644
index 0000000..d6b7491
--- /dev/null
+++ b/src/windows/identity/plugins/krb4/Makefile
@@ -0,0 +1,78 @@
+#
+# Copyright (c) 2004 Massachusetts Institute of Technology
+#
+# Permission is hereby granted, free of charge, to any person
+# obtaining a copy of this software and associated documentation files
+# (the "Software"), to deal in the Software without restriction,
+# including without limitation the rights to use, copy, modify, merge,
+# publish, distribute, sublicense, and/or sell copies of the Software,
+# and to permit persons to whom the Software is furnished to do so,
+# subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+
+
+MODULE=plugins\krb4
+!include <../../config/Makefile.w32>
+
+DLLFILE=$(BINDIR)\krb4cred.dll
+
+LIBFILE=$(LIBDIR)\krb4cred.lib
+
+OBJFILES= \
+ $(LIBDIR)\dynimport.obj \
+ $(LIBDIR)\krb5common.obj \
+ $(OBJ)\main.obj \
+ $(OBJ)\krb4plugin.obj \
+ $(OBJ)\krb4funcs.obj \
+ $(OBJ)\errorfuncs.obj \
+ $(OBJ)\krb4config.obj \
+ $(OBJ)\krb4configdlg.obj
+
+LIBFILES= \
+ $(LIBDIR)\nidmgr32.lib \
+ $(KFWLIBDIR)\loadfuncs.lib
+
+SDKLIBFILES=
+
+$(OBJ)\krb4config.c: krbconfig.csv $(CONFDIR)\csvschema.cfg
+ $(CCSV) $** $@
+
+$(DLLFILE): $(OBJFILES)
+ $(DLLGUILINK) $(LIBFILES) $(SDKLIBFILES)
+
+all: mkdirs $(DLLFILE) lang
+
+lang::
+
+# Repeat this block as necessary redefining LANG for additional
+# languages.
+
+# Begin language block
+LANG=en_us
+
+LANGDLL=$(BINDIR)\krb4cred_$(LANG).dll
+
+lang:: $(LANGDLL)
+
+$(LANGDLL): $(OBJ)\langres_$(LANG).res
+ $(DLLRESLINK)
+
+$(OBJ)\langres_$(LANG).res: lang\$(LANG)\langres.rc
+ $(RC2RES)
+# End language block
+
+clean::
+!if defined(INCFILES)
+ $(RM) $(INCFILES)
+!endif
diff --git a/src/windows/identity/plugins/krb4/datarep.h b/src/windows/identity/plugins/krb4/datarep.h
new file mode 100644
index 0000000..9c7048e
--- /dev/null
+++ b/src/windows/identity/plugins/krb4/datarep.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2004 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#ifndef __KHIMAIRA_KRB_DATAREP_H
+#define __KHIMAIRA_KRB_DATAREP_H
+
+
+khm_int32 KHMAPI enctype_toString(const void * data, khm_int32 cbdata, wchar_t *destbuf, khm_int32 *pcbdestbuf, khm_int32 flags);
+khm_int32 KHMAPI addr_list_toString(const void *, khm_int32, wchar_t *, khm_int32 *, khm_int32);
+khm_int32 KHMAPI krb5flags_toString(const void *, khm_int32, wchar_t *, khm_int32 *, khm_int32);
+khm_int32 KHMAPI renew_for_cb(khm_handle cred, khm_int32 id, void * buffer, khm_int32 * pcbsize);
+
+
+#endif \ No newline at end of file
diff --git a/src/windows/identity/plugins/krb4/errorfuncs.c b/src/windows/identity/plugins/krb4/errorfuncs.c
new file mode 100644
index 0000000..9feaad2
--- /dev/null
+++ b/src/windows/identity/plugins/krb4/errorfuncs.c
@@ -0,0 +1,264 @@
+/*
+ * Copyright (c) 2004 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#include<krbcred.h>
+#include<kherror.h>
+
+extern void (__cdecl *pinitialize_krb_error_func)();
+extern void (__cdecl *pinitialize_kadm_error_table)();
+
+
+khm_int32 init_error_funcs()
+{
+
+#if 0
+ /*TODO: Do something about this */
+ if (plsh_LoadKrb4LeashErrorTables)
+ plsh_LoadKrb4LeashErrorTables(hLeashInst, 0);
+#endif
+ return KHM_ERROR_SUCCESS;
+}
+
+khm_int32 exit_error_funcs()
+{
+ return KHM_ERROR_SUCCESS;
+}
+
+// Global Variables.
+static long lsh_errno;
+static char *err_context; /* error context */
+extern int (*Lcom_err)(LPSTR,long,LPSTR,...);
+extern LPSTR (*Lerror_message)(long);
+extern LPSTR (*Lerror_table_name)(long);
+
+#ifdef WIN16
+#define UNDERSCORE "_"
+#else
+#define UNDERSCORE
+#endif
+
+HWND GetRootParent (HWND Child)
+{
+ HWND Last;
+ while (Child)
+ {
+ Last = Child;
+ Child = GetParent (Child);
+ }
+ return Last;
+}
+
+
+LPSTR err_describe(LPSTR buf, long code)
+{
+ LPSTR cp, com_err_msg;
+ int offset;
+ long table_num;
+ char *etype;
+
+ offset = (int) (code & 255);
+ table_num = code - offset;
+ com_err_msg = Lerror_message(code);
+
+ switch(table_num)
+ {
+ case krb_err_base:
+ case kadm_err_base:
+ break;
+ default:
+ strcpy(buf, com_err_msg);
+ return buf;
+ }
+
+ cp = buf;
+ if (table_num == krb_err_base)
+ switch(offset)
+ {
+ case KDC_NAME_EXP: /* 001 Principal expired */
+ case KDC_SERVICE_EXP: /* 002 Service expired */
+ case KDC_AUTH_EXP: /* 003 Auth expired */
+ case KDC_PKT_VER: /* 004 Protocol version unknown */
+ case KDC_P_MKEY_VER: /* 005 Wrong master key version */
+ case KDC_S_MKEY_VER: /* 006 Wrong master key version */
+ case KDC_BYTE_ORDER: /* 007 Byte order unknown */
+ case KDC_PR_N_UNIQUE: /* 009 Principal not unique */
+ case KDC_NULL_KEY: /* 010 Principal has null key */
+ case KDC_GEN_ERR: /* 011 Generic error from KDC */
+ case INTK_W_NOTALL : /* 061 Not ALL tickets returned */
+ case INTK_PROT : /* 063 Protocol Error */
+ case INTK_ERR : /* 070 Other error */
+ com_err_msg = "Something weird happened... try again, and if Leash"
+ " continues to fail, contact Network Services as listed in the "
+ "About box.";
+ break;
+ case KDC_PR_UNKNOWN: /* 008 Principal unknown */
+ com_err_msg = "You have entered an unknown username/instance/realm"
+ " combination.";
+ break;
+ case GC_TKFIL : /* 021 Can't read ticket file */
+ case GC_NOTKT : /* 022 Can't find ticket or TGT */
+ com_err_msg = "Something is wrong with the memory where your "
+ "tickets are stored. Try exiting Windows and restarting your "
+ "computer.";
+ break;
+ case MK_AP_TGTEXP : /* 026 TGT Expired */
+ /* no extra error msg */
+ break;
+ case RD_AP_TIME : /* 037 delta_t too big */
+ com_err_msg = "Your computer's clock is out of sync with the "
+ "Kerberos server. Please see the help file about correcting "
+ "your clock.";
+ break;
+
+ case RD_AP_UNDEC : /* 031 Can't decode authenticator */
+ case RD_AP_EXP : /* 032 Ticket expired */
+ case RD_AP_NYV : /* 033 Ticket not yet valid */
+ case RD_AP_REPEAT : /* 034 Repeated request */
+ case RD_AP_NOT_US : /* 035 The ticket isn't for us */
+ case RD_AP_INCON : /* 036 Request is inconsistent */
+ case RD_AP_BADD : /* 038 Incorrect net address */
+ case RD_AP_VERSION : /* 039 protocol version mismatch */
+ case RD_AP_MSG_TYPE : /* 040 invalid msg type */
+ case RD_AP_MODIFIED : /* 041 message stream modified */
+ case RD_AP_ORDER : /* 042 message out of order */
+ case RD_AP_UNAUTHOR : /* 043 unauthorized request */
+ /* no extra error msg */
+ break;
+ case GT_PW_NULL: /* 51 Current PW is null */
+ case GT_PW_BADPW: /* 52 Incorrect current password */
+ case GT_PW_PROT: /* 53 Protocol Error */
+ case GT_PW_KDCERR: /* 54 Error returned by KDC */
+ case GT_PW_NULLTKT: /* 55 Null tkt returned by KDC */
+ /* no error msg yet */
+ break;
+
+ /* Values returned by send_to_kdc */
+ case SKDC_RETRY : /* 56 Retry count exceeded */
+ case SKDC_CANT : /* 57 Can't send request */
+ com_err_msg = "Cannot contact the kerberos server for the selected realm.";
+ break;
+ /* no error message on purpose: */
+ case INTK_BADPW : /* 062 Incorrect password */
+ break;
+ default:
+ /* no extra error msg */
+ break;
+ }
+ else
+ switch(code)
+ {
+ case KADM_INSECURE_PW:
+ /* if( kadm_info != NULL ){
+ * wsprintf(buf, "%s\n%s", com_err_msg, kadm_info);
+ * } else {
+ * wsprintf(buf, "%s\nPlease see the help file for information "
+ * "about secure passwords.", com_err_msg);
+ * }
+ * com_err_msg = buf;
+ */
+
+ /* The above code would be preferred since it allows site specific
+ * information to be delivered from the Kerberos server. However the
+ * message box is too small for VGA screens.
+ * It does work well if we only have to support 1024x768
+ */
+
+ com_err_msg = "You have entered an insecure or weak password.";
+
+ default:
+ /* no extra error msg */
+ break;
+ }
+ if(com_err_msg != buf)
+ strcpy(buf, com_err_msg);
+ cp = buf + strlen(buf);
+ *cp++ = '\n';
+ switch(table_num) {
+ case krb_err_base:
+ etype = "Kerberos";
+ break;
+ case kadm_err_base:
+ etype = "Kerberos supplemental";
+ break;
+ default:
+ etype = Lerror_table_name(table_num);
+ break;
+ }
+ wsprintfA((LPSTR) cp, (LPSTR) "(%s error %d"
+#ifdef DEBUG_COM_ERR
+ " (absolute error %ld)"
+#endif
+ ")", etype, offset
+ //")\nPress F1 for help on this error.", etype, offset
+#ifdef DEBUG_COM_ERR
+ , code
+#endif
+ );
+
+ return (LPSTR)buf;
+}
+
+int lsh_com_err_proc (LPSTR whoami, long code,
+ LPSTR fmt, va_list args)
+{
+ int retval;
+ HWND hOldFocus;
+ char buf[1024], *cp; /* changed to 512 by jms 8/23/93 */
+ WORD mbformat = MB_OK | MB_ICONEXCLAMATION;
+
+ cp = buf;
+ memset(buf, '\0', sizeof(buf));
+ cp[0] = '\0';
+
+ if (code)
+ {
+ err_describe(buf, code);
+ while (*cp)
+ cp++;
+ }
+
+ if (fmt)
+ {
+ if (fmt[0] == '%' && fmt[1] == 'b')
+ {
+ fmt += 2;
+ mbformat = va_arg(args, WORD);
+ /* if the first arg is a %b, we use it for the message
+ box MB_??? flags. */
+ }
+ if (code)
+ {
+ *cp++ = '\n';
+ *cp++ = '\n';
+ }
+ wvsprintfA((LPSTR)cp, fmt, args);
+ }
+ hOldFocus = GetFocus();
+ retval = MessageBoxA(/*GetRootParent(hOldFocus)*/NULL, buf, whoami,
+ mbformat | MB_ICONHAND | MB_TASKMODAL);
+ SetFocus(hOldFocus);
+ return retval;
+}
diff --git a/src/windows/identity/plugins/krb4/errorfuncs.h b/src/windows/identity/plugins/krb4/errorfuncs.h
new file mode 100644
index 0000000..be8f4e7
--- /dev/null
+++ b/src/windows/identity/plugins/krb4/errorfuncs.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2004 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#ifndef __KHIMAIRA_ERR_H
+#define __KHIMAIRA_ERR_H
+
+/* All error handling and reporting related functions for the krb4/5
+ and AFS plugins */
+
+#include <errno.h>
+#include <com_err.h>
+/*
+ * This is a hack needed because the real com_err.h does
+ * not define err_func. We need it in the case where
+ * we pull in the real com_err instead of the krb4
+ * impostor.
+ */
+#ifndef _DCNS_MIT_COM_ERR_H
+typedef LPSTR (*err_func)(int, long);
+#endif
+
+#include <krberr.h>
+extern void Leash_initialize_krb_error_func(err_func func,struct et_list **);
+#undef init_krb_err_func
+#define init_krb_err_func(erf) Leash_initialize_krb_error_func(erf,&_et_list)
+
+#include <kadm_err.h>
+
+extern void Leash_initialize_kadm_error_table(struct et_list **);
+#undef init_kadm_err_tbl
+#define init_kadm_err_tbl() Leash_initialize_kadm_error_table(&_et_list)
+#define kadm_err_base ERROR_TABLE_BASE_kadm
+
+#define krb_err_func Leash_krb_err_func
+
+#include <stdarg.h>
+int lsh_com_err_proc (LPSTR whoami, long code,
+ LPSTR fmt, va_list args);
+void FAR Leash_load_com_err_callback(FARPROC,FARPROC,FARPROC);
+
+#ifndef KRBERR
+#define KRBERR(code) (code + krb_err_base)
+#endif
+
+int lsh_com_err_proc (LPSTR whoami, long code, LPSTR fmt, va_list args);
+int DoNiftyErrorReport(long errnum, LPSTR what);
+
+LPSTR err_describe(LPSTR buf, long code);
+
+
+/* */
+khm_int32 init_error_funcs();
+
+khm_int32 exit_error_funcs();
+
+
+#endif
diff --git a/src/windows/identity/plugins/krb4/krb4configdlg.c b/src/windows/identity/plugins/krb4/krb4configdlg.c
new file mode 100644
index 0000000..9ad3406
--- /dev/null
+++ b/src/windows/identity/plugins/krb4/krb4configdlg.c
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2004 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#include<krbcred.h>
+#include<kherror.h>
+#include<khuidefs.h>
+#include<strsafe.h>
+
+INT_PTR CALLBACK
+krb4_confg_proc(HWND hwnd,
+ UINT uMsg,
+ WPARAM wParam,
+ LPARAM lParam) {
+
+ switch(uMsg) {
+ case WM_INITDIALOG:
+ {
+ wchar_t wbuf[MAX_PATH];
+ CHAR krb_path[MAX_PATH];
+ CHAR krbrealm_path[MAX_PATH];
+ CHAR ticketName[MAX_PATH];
+ char * pticketName;
+ unsigned int krb_path_sz = sizeof(krb_path);
+ unsigned int krbrealm_path_sz = sizeof(krbrealm_path);
+
+ // Set KRB.CON
+ memset(krb_path, '\0', sizeof(krb_path));
+ if (!pkrb_get_krbconf2(krb_path, &krb_path_sz)) {
+ // Error has happened
+ } else { // normal find
+ AnsiStrToUnicode(wbuf, sizeof(wbuf), krb_path);
+ SetDlgItemText(hwnd, IDC_CFG_CFGPATH, wbuf);
+ }
+
+ // Set KRBREALM.CON
+ memset(krbrealm_path, '\0', sizeof(krbrealm_path));
+ if (!pkrb_get_krbrealm2(krbrealm_path, &krbrealm_path_sz)) {
+ // Error has happened
+ } else {
+ AnsiStrToUnicode(wbuf, sizeof(wbuf), krbrealm_path);
+ SetDlgItemText(hwnd, IDC_CFG_RLMPATH, wbuf);
+ }
+
+ // Set TICKET.KRB file Editbox
+ *ticketName = 0;
+ pkrb_set_tkt_string(0);
+
+ pticketName = ptkt_string();
+ if (pticketName)
+ StringCbCopyA(ticketName, sizeof(ticketName), pticketName);
+
+ if (!*ticketName) {
+ // error
+ } else {
+ AnsiStrToUnicode(wbuf, sizeof(wbuf), ticketName);
+ SetDlgItemText(hwnd, IDC_CFG_CACHE, wbuf);
+ }
+ }
+ break;
+
+ case WM_DESTROY:
+ break;
+ }
+ return FALSE;
+}
diff --git a/src/windows/identity/plugins/krb4/krb4funcs.c b/src/windows/identity/plugins/krb4/krb4funcs.c
new file mode 100644
index 0000000..8fda720
--- /dev/null
+++ b/src/windows/identity/plugins/krb4/krb4funcs.c
@@ -0,0 +1,505 @@
+/*
+* Copyright (c) 2004 Massachusetts Institute of Technology
+*
+* Permission is hereby granted, free of charge, to any person
+* obtaining a copy of this software and associated documentation
+* files (the "Software"), to deal in the Software without
+* restriction, including without limitation the rights to use, copy,
+* modify, merge, publish, distribute, sublicense, and/or sell copies
+* of the Software, and to permit persons to whom the Software is
+* furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be
+* included in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+* SOFTWARE.
+*/
+
+/* $Id$ */
+
+/* Originally this was krb5routines.c in Leash sources. Subsequently
+modified and adapted for NetIDMgr */
+
+#include<krbcred.h>
+#include<kherror.h>
+
+#define SECURITY_WIN32
+#include <security.h>
+#include <ntsecapi.h>
+
+#include <string.h>
+#include <time.h>
+#include <assert.h>
+#include <strsafe.h>
+
+
+
+int com_addr(void)
+{
+ long ipAddr;
+ char loc_addr[ADDR_SZ];
+ CREDENTIALS cred;
+ char service[40];
+ char instance[40];
+ // char addr[40];
+ char realm[40];
+ struct in_addr LocAddr;
+ int k_errno;
+
+ if (pkrb_get_cred == NULL)
+ return(KSUCCESS);
+
+ k_errno = (*pkrb_get_cred)(service,instance,realm,&cred);
+ if (k_errno)
+ return KRBERR(k_errno);
+
+ while(1) {
+ ipAddr = (*pLocalHostAddr)();
+ LocAddr.s_addr = ipAddr;
+ StringCbCopyA(loc_addr, sizeof(loc_addr), inet_ntoa(LocAddr));
+ if ( strcmp(cred.address,loc_addr) != 0) {
+ /* TODO: do something about this */
+ //Leash_kdestroy ();
+ break;
+ }
+ break;
+ } // while()
+ return 0;
+}
+
+
+long
+khm_krb4_list_tickets(void)
+{
+ char pname[ANAME_SZ];
+ char pinst[INST_SZ];
+ char prealm[REALM_SZ];
+ wchar_t wbuf[256];
+ int k_errno;
+ CREDENTIALS c;
+ int newtickets = 0;
+ int open = 0;
+ khm_handle ident = NULL;
+ khm_handle cred = NULL;
+ time_t tt;
+ FILETIME ft;
+
+ // Since krb_get_tf_realm will return a ticket_file error,
+ // we will call tf_init and tf_close first to filter out
+ // things like no ticket file. Otherwise, the error that
+ // the user would see would be
+ // klist: can't find realm of ticket file: No ticket file (tf_util)
+ // instead of klist: No ticket file (tf_util)
+ if (ptf_init == NULL)
+ return(KSUCCESS);
+
+ com_addr();
+
+ // Open ticket file
+ if ((k_errno = (*ptf_init)((*ptkt_string)(), R_TKT_FIL)))
+ {
+ goto cleanup;
+ }
+ // Close ticket file
+ (void) (*ptf_close)();
+
+ // We must find the realm of the ticket file here before calling
+ // tf_init because since the realm of the ticket file is not
+ // really stored in the principal section of the file, the
+ // routine we use must itself call tf_init and tf_close.
+
+ if ((k_errno = (*pkrb_get_tf_realm)((*ptkt_string)(), prealm)) != KSUCCESS)
+ {
+ goto cleanup;
+ }
+
+ // Open ticket file
+ if (k_errno = (*ptf_init)((*ptkt_string)(), R_TKT_FIL))
+ {
+ goto cleanup;
+ }
+
+ open = 1;
+
+ // Get principal name and instance
+ if ((k_errno = (*ptf_get_pname)(pname)) || (k_errno = (*ptf_get_pinst)(pinst)))
+ {
+ goto cleanup;
+ }
+
+ // You may think that this is the obvious place to get the
+ // realm of the ticket file, but it can't be done here as the
+ // routine to do this must open the ticket file. This is why
+ // it was done before tf_init.
+ StringCbPrintf(wbuf, sizeof(wbuf), L"%S%S%S%S%S", (LPSTR)pname,
+ (LPSTR)(pinst[0] ? "." : ""), (LPSTR)pinst,
+ (LPSTR)(prealm[0] ? "@" : ""), (LPSTR)prealm);
+
+ if(KHM_FAILED(kcdb_identity_create(wbuf, KCDB_IDENT_FLAG_CREATE, &ident)))
+ {
+ goto cleanup;
+ }
+
+ kcdb_credset_flush(krb4_credset);
+
+ // Get KRB4 tickets
+ while ((k_errno = (*ptf_get_cred)(&c)) == KSUCCESS)
+ {
+ StringCbPrintf(wbuf, sizeof(wbuf), L"%S%S%S%S%S",
+ c.service,
+ (c.instance[0] ? "." : ""),
+ c.instance,
+ (c.realm[0] ? "@" : ""),
+ c.realm);
+
+ if(KHM_FAILED(kcdb_cred_create(wbuf, ident, credtype_id_krb4, &cred)))
+ continue;
+
+ tt = c.issue_date + c.lifetime * 5L * 60L;
+ TimetToFileTime(tt, &ft);
+ kcdb_cred_set_attr(cred, KCDB_ATTR_EXPIRE, &ft, sizeof(ft));
+
+ tt = c.issue_date;
+ TimetToFileTime(tt, &ft);
+ kcdb_cred_set_attr(cred, KCDB_ATTR_ISSUE, &ft, sizeof(ft));
+
+ tt = c.lifetime * 5L * 60L;
+ TimetToFileTimeInterval(tt, &ft);
+ kcdb_cred_set_attr(cred, KCDB_ATTR_LIFETIME, &ft, sizeof(ft));
+
+ kcdb_credset_add_cred(krb4_credset, cred, -1);
+
+ } // while
+
+ kcdb_credset_collect(NULL, krb4_credset, ident, credtype_id_krb4, NULL);
+
+cleanup:
+ if (ptf_close == NULL)
+ return(KSUCCESS);
+
+ if (open)
+ (*ptf_close)(); //close ticket file
+
+ if (k_errno == EOF)
+ k_errno = 0;
+
+ // XXX the if statement directly below was inserted to eliminate
+ // an error NO_TKT_FIL on Leash startup. The error occurs from an
+ // error number thrown from krb_get_tf_realm. We believe this
+ // change does not eliminate other errors, but it may.
+
+ if (k_errno == NO_TKT_FIL)
+ k_errno = 0;
+
+ if(ident)
+ kcdb_identity_release(ident);
+
+#if 0
+ /*TODO: Handle errors here */
+ if (k_errno)
+ {
+ CHAR message[256];
+ CHAR errBuf[256];
+ LPCSTR errText;
+
+ if (!Lerror_message)
+ return -1;
+
+ errText = err_describe(errBuf, KRBERR(k_errno));
+
+ sprintf(message, "%s\n\n%s failed", errText, functionName);
+ MessageBox(NULL, message, "Kerberos Four",
+ MB_OK | MB_ICONERROR | MB_TASKMODAL | MB_SETFOREGROUND);
+ }
+#endif
+ return k_errno;
+}
+
+#define KRB_FILE "KRB.CON"
+#define KRBREALM_FILE "KRBREALM.CON"
+#define KRB5_FILE "KRB5.INI"
+
+BOOL
+khm_get_profile_file(LPSTR confname, UINT szConfname)
+{
+ char **configFile = NULL;
+ if (pkrb5_get_default_config_files(&configFile))
+ {
+ GetWindowsDirectoryA(confname,szConfname);
+ confname[szConfname-1] = '\0';
+ strncat(confname, "\\",sizeof(confname)-strlen(confname));
+ confname[szConfname-1] = '\0';
+ strncat(confname, KRB5_FILE,sizeof(confname)-strlen(confname));
+ confname[szConfname-1] = '\0';
+ return FALSE;
+ }
+
+ *confname = 0;
+
+ if (configFile)
+ {
+ strncpy(confname, *configFile, szConfname);
+ pkrb5_free_config_files(configFile);
+ }
+
+ if (!*confname)
+ {
+ GetWindowsDirectoryA(confname,szConfname);
+ confname[szConfname-1] = '\0';
+ strncat(confname, "\\",sizeof(confname)-strlen(confname));
+ confname[szConfname-1] = '\0';
+ strncat(confname, KRB5_FILE,sizeof(confname)-strlen(confname));
+ confname[szConfname-1] = '\0';
+ }
+
+ return FALSE;
+}
+
+BOOL
+khm_get_krb4_con_file(LPSTR confname, UINT szConfname)
+{
+ if (hKrb5 && !hKrb4)
+ { // hold krb.con where krb5.ini is located
+ CHAR krbConFile[MAX_PATH]="";
+ LPSTR pFind;
+
+ //strcpy(krbConFile, CLeashApp::m_krbv5_profile->first_file->filename);
+ if (khm_get_profile_file(krbConFile, sizeof(krbConFile)))
+ {
+ GetWindowsDirectoryA(krbConFile,sizeof(krbConFile));
+ krbConFile[MAX_PATH-1] = '\0';
+ strncat(krbConFile, "\\",sizeof(krbConFile)-strlen(krbConFile));
+ krbConFile[MAX_PATH-1] = '\0';
+ strncat(krbConFile, KRB5_FILE,sizeof(krbConFile)-strlen(krbConFile));
+ krbConFile[MAX_PATH-1] = '\0';
+ }
+
+ pFind = strrchr(krbConFile, '\\');
+ if (pFind)
+ {
+ *pFind = 0;
+ strncat(krbConFile, "\\",sizeof(krbConFile)-strlen(krbConFile));
+ krbConFile[MAX_PATH-1] = '\0';
+ strncat(krbConFile, KRB_FILE,sizeof(krbConFile)-strlen(krbConFile));
+ krbConFile[MAX_PATH-1] = '\0';
+ }
+ else
+ krbConFile[0] = 0;
+
+ strncpy(confname, krbConFile, szConfname);
+ confname[szConfname-1] = '\0';
+ }
+ else if (hKrb4)
+ {
+ unsigned int size = szConfname;
+ memset(confname, '\0', szConfname);
+ if (!pkrb_get_krbconf2(confname, &size))
+ { // Error has happened
+ GetWindowsDirectoryA(confname,szConfname);
+ confname[szConfname-1] = '\0';
+ strncat(confname, "\\",szConfname-strlen(confname));
+ confname[szConfname-1] = '\0';
+ strncat(confname,KRB_FILE,szConfname-strlen(confname));
+ confname[szConfname-1] = '\0';
+ }
+ }
+ return FALSE;
+}
+
+int
+readstring(FILE * file, char * buf, int len)
+{
+ int c,i;
+ memset(buf, '\0', sizeof(buf));
+ for (i=0, c=fgetc(file); c != EOF ; c=fgetc(file), i++)
+ {
+ if (i < sizeof(buf)) {
+ if (c == '\n') {
+ buf[i] = '\0';
+ return i;
+ } else {
+ buf[i] = c;
+ }
+ } else {
+ if (c == '\n') {
+ buf[len-1] = '\0';
+ return(i);
+ }
+ }
+ }
+ if (c == EOF) {
+ if (i > 0 && i < len) {
+ buf[i] = '\0';
+ return(i);
+ } else {
+ buf[len-1] = '\0';
+ return(-1);
+ }
+ }
+ return(-1);
+}
+
+/*! \internal
+ \brief Return a list of configured realms
+
+ The string that is returned is a set of null terminated unicode strings,
+ each of which denotes one realm. The set is terminated by a zero length
+ null terminated string.
+
+ The caller should free the returned string using free()
+
+ \return The string with the list of realms or NULL if the operation fails.
+*/
+wchar_t * khm_krb5_get_realm_list(void)
+{
+ wchar_t * rlist = NULL;
+
+ if (pprofile_get_subsection_names && pprofile_free_list) {
+ const char* rootSection[] = {"realms", NULL};
+ const char** rootsec = rootSection;
+ char **sections = NULL, **cpp = NULL, *value = NULL;
+
+ char krb5_conf[MAX_PATH+1];
+
+ if (!khm_get_profile_file(krb5_conf,sizeof(krb5_conf))) {
+ profile_t profile;
+ long retval;
+ const char *filenames[2];
+ wchar_t * d;
+ size_t cbsize;
+ size_t t;
+
+ filenames[0] = krb5_conf;
+ filenames[1] = NULL;
+ retval = pprofile_init(filenames, &profile);
+ if (!retval) {
+ retval = pprofile_get_subsection_names(profile, rootsec, &sections);
+
+ if (!retval)
+ {
+ /* first figure out how much space to allocate */
+ cbsize = 0;
+ for (cpp = sections; *cpp; cpp++)
+ {
+ cbsize += sizeof(wchar_t) * (strlen(*cpp) + 1);
+ }
+ cbsize += sizeof(wchar_t); /* double null terminated */
+
+ rlist = malloc(cbsize);
+ d = rlist;
+ for (cpp = sections; *cpp; cpp++)
+ {
+ AnsiStrToUnicode(d, cbsize, *cpp);
+ t = wcslen(d) + 1;
+ d += t;
+ cbsize -= sizeof(wchar_t) * t;
+ }
+ *d = L'\0';
+ }
+
+ pprofile_free_list(sections);
+
+#if 0
+ retval = pprofile_get_string(profile, "libdefaults","noaddresses", 0, "true", &value);
+ if ( value ) {
+ disable_noaddresses = config_boolean_to_int(value);
+ pprofile_release_string(value);
+ }
+#endif
+ pprofile_release(profile);
+ }
+ }
+ } else {
+ FILE * file;
+ char krb_conf[MAX_PATH+1];
+ char * p;
+ size_t cbsize, t;
+ wchar_t * d;
+
+ if (!khm_get_krb4_con_file(krb_conf,sizeof(krb_conf)) &&
+ (file = fopen(krb_conf, "rt")))
+ {
+ char lineBuf[256];
+
+ /*TODO: compute the actual required buffer size instead of hardcoding */
+ cbsize = 16384; // arbitrary
+ rlist = malloc(cbsize);
+ d = rlist;
+
+ // Skip the default realm
+ readstring(file,lineBuf,sizeof(lineBuf));
+
+ // Read the defined realms
+ while (TRUE)
+ {
+ if (readstring(file,lineBuf,sizeof(lineBuf)) < 0)
+ break;
+
+ if (*(lineBuf + strlen(lineBuf) - 1) == '\r')
+ *(lineBuf + strlen(lineBuf) - 1) = 0;
+
+ for (p=lineBuf; *p ; p++)
+ {
+ if (isspace(*p)) {
+ *p = 0;
+ break;
+ }
+ }
+
+ if ( strncmp(".KERBEROS.OPTION.",lineBuf,17) ) {
+ t = strlen(lineBuf) + 1;
+ if(cbsize > (1 + t*sizeof(wchar_t))) {
+ AnsiStrToUnicode(d, cbsize, lineBuf);
+ d += t;
+ cbsize -= t * sizeof(wchar_t);
+ } else
+ break;
+ }
+ }
+
+ *d = L'\0';
+
+ fclose(file);
+ }
+ }
+
+ return rlist;
+}
+
+/*! \internal
+ \brief Get the default realm
+
+ A string will be returned that specifies the default realm. The caller
+ should free the string using free().
+
+ Returns NULL if the operation fails.
+*/
+wchar_t * khm_krb5_get_default_realm(void)
+{
+ wchar_t * realm;
+ size_t cch;
+ krb5_context ctx=0;
+ char * def = 0;
+
+ pkrb5_init_context(&ctx);
+ pkrb5_get_default_realm(ctx,&def);
+
+ if (def) {
+ cch = strlen(def) + 1;
+ realm = malloc(sizeof(wchar_t) * cch);
+ AnsiStrToUnicode(realm, sizeof(wchar_t) * cch, def);
+ pkrb5_free_default_realm(ctx, def);
+ } else
+ realm = NULL;
+
+ pkrb5_free_context(ctx);
+
+ return realm;
+}
diff --git a/src/windows/identity/plugins/krb4/krb4funcs.h b/src/windows/identity/plugins/krb4/krb4funcs.h
new file mode 100644
index 0000000..ea97358
--- /dev/null
+++ b/src/windows/identity/plugins/krb4/krb4funcs.h
@@ -0,0 +1,190 @@
+/*
+ * Copyright (c) 2004 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+/* Adapted from multiple Leash header files */
+
+#ifndef __KHIMAIRA_KRB5FUNCS_H
+#define __KHIMAIRA_KRB5FUNCS_H
+
+#include<stdlib.h>
+#include<krb5.h>
+
+#include <windows.h>
+#define SECURITY_WIN32
+#include <security.h>
+#include <ntsecapi.h>
+
+#include <krb5common.h>
+
+#define LEASH_DEBUG_CLASS_GENERIC 0
+#define LEASH_DEBUG_CLASS_KRB4 1
+#define LEASH_DEBUG_CLASS_KRB4_APP 2
+
+#define LEASH_PRIORITY_LOW 0
+#define LEASH_PRIORITY_HIGH 1
+
+#define KRB5_DEFAULT_LIFE 60*60*10 /* 10 hours */
+
+// Function Prototypes.
+BOOL khm_krb5_ms2mit(BOOL);
+
+int
+khm_krb5_kinit(krb5_context alt_ctx,
+ char * principal_name,
+ char * password,
+ krb5_deltat lifetime,
+ DWORD forwardable,
+ DWORD proxiable,
+ krb5_deltat renew_life,
+ DWORD addressless,
+ DWORD publicIP,
+ krb5_prompter_fct prompter,
+ void * p_data
+ );
+
+long
+Leash_int_kinit_ex(
+ krb5_context ctx,
+ HWND hParent,
+ char * principal,
+ char * password,
+ int lifetime,
+ int forwardable,
+ int proxiable,
+ int renew_life,
+ int addressless,
+ unsigned long publicIP,
+ int displayErrors
+ );
+
+long
+Leash_int_checkpwd(
+ char * principal,
+ char * password,
+ int displayErrors
+ );
+
+long
+Leash_int_changepwd(
+ char * principal,
+ char * password,
+ char * newpassword,
+ char** result_string,
+ int displayErrors
+ );
+
+int
+Leash_krb5_kdestroy(
+ void
+ );
+
+int
+Leash_krb5_kinit(
+ krb5_context,
+ HWND hParent,
+ char * principal_name,
+ char * password,
+ krb5_deltat lifetime,
+ DWORD forwardable,
+ DWORD proxiable,
+ krb5_deltat renew_life,
+ DWORD addressless,
+ DWORD publicIP
+ );
+
+long
+khm_convert524(
+ krb5_context ctx
+ );
+
+int
+Leash_afs_unlog(
+ void
+ );
+
+int
+Leash_afs_klog(
+ char *,
+ char *,
+ char *,
+ int
+ );
+
+int
+LeashKRB5_renew(void);
+
+LONG
+write_registry_setting(
+ char* setting,
+ DWORD type,
+ void* buffer,
+ size_t size
+ );
+
+LONG
+read_registry_setting_user(
+ char* setting,
+ void* buffer,
+ size_t size
+ );
+
+LONG
+read_registry_setting(
+ char* setting,
+ void* buffer,
+ size_t size
+ );
+
+BOOL
+get_STRING_from_registry(
+ HKEY hBaseKey,
+ char * key,
+ char * value,
+ char * outbuf,
+ DWORD outlen
+ );
+
+BOOL
+get_DWORD_from_registry(
+ HKEY hBaseKey,
+ char * key,
+ char * value,
+ DWORD * result
+ );
+
+int
+config_boolean_to_int(
+ const char *s
+ );
+
+
+wchar_t * khm_krb5_get_default_realm(void);
+wchar_t * khm_krb5_get_realm_list(void);
+long khm_krb5_list_tickets(krb5_context *krbv5Context);
+long khm_krb4_list_tickets(void);
+
+
+#endif
diff --git a/src/windows/identity/plugins/krb4/krb4plugin.c b/src/windows/identity/plugins/krb4/krb4plugin.c
new file mode 100644
index 0000000..106feba
--- /dev/null
+++ b/src/windows/identity/plugins/krb4/krb4plugin.c
@@ -0,0 +1,164 @@
+/*
+ * Copyright (c) 2004 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#include<krbcred.h>
+#include<kherror.h>
+#include<khmsgtypes.h>
+#include<khuidefs.h>
+#include<commctrl.h>
+#include<strsafe.h>
+#include<krb5.h>
+
+khm_int32 credtype_id_krb4 = KCDB_CREDTYPE_INVALID;
+khm_boolean krb4_initialized = FALSE;
+khm_handle krb4_credset = NULL;
+
+/* Kerberos IV stuff */
+khm_int32 KHMAPI
+krb4_msg_system(khm_int32 msg_type, khm_int32 msg_subtype,
+ khm_ui_4 uparam, void * vparam)
+{
+ khm_int32 rv = KHM_ERROR_SUCCESS;
+
+ switch(msg_subtype) {
+ case KMSG_SYSTEM_INIT:
+ {
+ kcdb_credtype ct;
+ wchar_t buf[KCDB_MAXCCH_SHORT_DESC];
+ size_t cbsize;
+ khui_config_node_reg reg;
+ wchar_t wshort_desc[KHUI_MAXCCH_SHORT_DESC];
+ wchar_t wlong_desc[KHUI_MAXCCH_LONG_DESC];
+
+ /* perform critical registrations and initialization
+ stuff */
+ ZeroMemory(&ct, sizeof(ct));
+ ct.id = KCDB_CREDTYPE_AUTO;
+ ct.name = KRB4_CREDTYPE_NAME;
+
+ if(LoadString(hResModule, IDS_KRB4_SHORT_DESC,
+ buf, ARRAYLENGTH(buf)))
+ {
+ StringCbLength(buf, KCDB_MAXCB_SHORT_DESC, &cbsize);
+ cbsize += sizeof(wchar_t);
+ ct.short_desc = malloc(cbsize);
+ StringCbCopy(ct.short_desc, cbsize, buf);
+ }
+
+ /* even though ideally we should be setting limits
+ based KCDB_MAXCB_LONG_DESC, our long description
+ actually fits nicely in KCDB_MAXCB_SHORT_DESC */
+ if(LoadString(hResModule, IDS_KRB4_LONG_DESC,
+ buf, ARRAYLENGTH(buf)))
+ {
+ StringCbLength(buf, KCDB_MAXCB_SHORT_DESC, &cbsize);
+ cbsize += sizeof(wchar_t);
+ ct.long_desc = malloc(cbsize);
+ StringCbCopy(ct.long_desc, cbsize, buf);
+ }
+
+ ct.icon = NULL; /* TODO: set a proper icon */
+ kmq_create_subscription(krb4_cb, &ct.sub);
+
+ rv = kcdb_credtype_register(&ct, &credtype_id_krb4);
+
+ if(KHM_SUCCEEDED(rv))
+ rv = kcdb_credset_create(&krb4_credset);
+
+ if(ct.short_desc)
+ free(ct.short_desc);
+
+ if(ct.long_desc)
+ free(ct.long_desc);
+
+ ZeroMemory(&reg, sizeof(reg));
+
+ reg.name = KRB4_CONFIG_NODE_NAME;
+ reg.short_desc = wshort_desc;
+ reg.long_desc = wlong_desc;
+ reg.h_module = hResModule;
+ reg.dlg_template = MAKEINTRESOURCE(IDD_CFG_KRB4);
+ reg.dlg_proc = krb4_confg_proc;
+ reg.flags = 0;
+
+ LoadString(hResModule, IDS_CFG_KRB4_LONG,
+ wlong_desc, ARRAYLENGTH(wlong_desc));
+ LoadString(hResModule, IDS_CFG_KRB4_SHORT,
+ wshort_desc, ARRAYLENGTH(wshort_desc));
+
+ khui_cfg_register(NULL, &reg);
+
+ if(KHM_SUCCEEDED(rv)) {
+ krb4_initialized = TRUE;
+
+ khm_krb4_list_tickets();
+ }
+ }
+ break;
+
+ case KMSG_SYSTEM_EXIT:
+ if(credtype_id_krb4 >= 0)
+ {
+ /* basically just unregister the credential type */
+ kcdb_credtype_unregister(credtype_id_krb4);
+
+ kcdb_credset_delete(krb4_credset);
+ }
+ break;
+ }
+
+ return rv;
+}
+
+khm_int32 KHMAPI
+krb4_msg_cred(khm_int32 msg_type, khm_int32 msg_subtype,
+ khm_ui_4 uparam, void * vparam)
+{
+ khm_int32 rv = KHM_ERROR_SUCCESS;
+
+ switch(msg_subtype) {
+ case KMSG_CRED_REFRESH:
+ {
+ khm_krb4_list_tickets();
+ }
+ break;
+ }
+
+ return rv;
+}
+
+khm_int32 KHMAPI
+krb4_cb(khm_int32 msg_type, khm_int32 msg_subtype,
+ khm_ui_4 uparam, void * vparam)
+{
+ switch(msg_type) {
+ case KMSG_SYSTEM:
+ return krb4_msg_system(msg_type, msg_subtype, uparam, vparam);
+ case KMSG_CRED:
+ return krb4_msg_cred(msg_type, msg_subtype, uparam, vparam);
+ }
+ return KHM_ERROR_SUCCESS;
+}
diff --git a/src/windows/identity/plugins/krb4/krbconfig.csv b/src/windows/identity/plugins/krb4/krbconfig.csv
new file mode 100644
index 0000000..bed0d1c
--- /dev/null
+++ b/src/windows/identity/plugins/krb4/krbconfig.csv
@@ -0,0 +1,23 @@
+Name,Type,Value,Description
+Krb4Cred,KC_SPACE,0,"Kerberos IV Credentials Provider"
+ Module,KC_STRING,"MITKrb4",
+ Description,KC_STRING,"Kerberos IV Credentials Provider",
+ Dependencies,KC_STRING,Krb5Cred,
+ Type,KC_INT32,1,
+ Flags,KC_INT32,0,
+ Parameters,KC_SPACE,0,Parameters for KrbCred
+ CreateMissingConfig,KC_INT32,0,Create missing configuration files
+ MsLsaImport,KC_INT32,2,Automatically import MSLSA credentials
+ AutoRenewTickets,KC_INT32,1,Automatically renew expiring tickets
+ DefaultLifetime,KC_INT32,36000,Default ticket lifetime
+ MaxLifetime,KC_INT32,86400,Maximum lifetime
+ MinLifetime,KC_INT32,60,Minimum lifetime
+ Forwardable,KC_INT32,1,Obtain forwardable tickets (boolean)
+ Proxiable,KC_INT32,0,Obtain proxiable tickets (boolean)
+ Addressless,KC_INT32,1,Obtain addressless tickets (boolean)
+ Renewable,KC_INT32,1,Obtain renewable tickets (boolean)
+ DefaultRenewLifetime,KC_INT32,604800,Default renewable lifetime
+ MaxRenewLifetime,KC_INT32,2592000,Maximum renewable lifetime
+ MinRenewLifetime,KC_INT32,60,Maximum renewable lifetime
+ Parameters,KC_ENDSPACE,0,
+Krb4Cred,KC_ENDSPACE,0,
diff --git a/src/windows/identity/plugins/krb4/krbcred.h b/src/windows/identity/plugins/krb4/krbcred.h
new file mode 100644
index 0000000..e56d114
--- /dev/null
+++ b/src/windows/identity/plugins/krb4/krbcred.h
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2004 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#ifndef __KHIMAIRA_KRBAFSCRED_H
+#define __KHIMAIRA_KRBAFSCRED_H
+
+#include<windows.h>
+
+#include<khdefs.h>
+#include<kcreddb.h>
+#include<kmm.h>
+#include<kconfig.h>
+
+
+#include<krb4funcs.h>
+#include<krb5common.h>
+#include<errorfuncs.h>
+#include<dynimport.h>
+
+#include<langres.h>
+#include<datarep.h>
+
+#define TYPENAME_ENCTYPE L"EncType"
+#define TYPENAME_ADDR_LIST L"AddrList"
+#define TYPENAME_KRB5_FLAGS L"Krb5Flags"
+
+#define ATTRNAME_KEY_ENCTYPE L"KeyEncType"
+#define ATTRNAME_TKT_ENCTYPE L"TktEncType"
+#define ATTRNAME_ADDR_LIST L"AddrList"
+#define ATTRNAME_KRB5_FLAGS L"Krb5Flags"
+#define ATTRNAME_RENEW_TILL L"RenewTill"
+#define ATTRNAME_RENEW_FOR L"RenewFor"
+
+void init_krb();
+void exit_krb();
+KHMEXP khm_int32 KHMAPI init_module(kmm_module h_module);
+KHMEXP khm_int32 KHMAPI exit_module(kmm_module h_module);
+
+/* globals */
+extern kmm_module h_khModule;
+extern HMODULE hResModule;
+extern HINSTANCE hInstance;
+
+extern khm_int32 type_id_enctype;
+extern khm_int32 type_id_addr_list;
+extern khm_int32 type_id_krb5_flags;
+
+extern khm_int32 attr_id_key_enctype;
+extern khm_int32 attr_id_tkt_enctype;
+extern khm_int32 attr_id_addr_list;
+extern khm_int32 attr_id_krb5_flags;
+extern khm_int32 attr_id_renew_till;
+extern khm_int32 attr_id_renew_for;
+
+/* Configuration spaces */
+#define CSNAME_KRB4CRED L"Krb4Cred"
+#define CSNAME_PARAMS L"Parameters"
+
+/* plugin constants */
+#define KRB4_PLUGIN_NAME L"Krb4Cred"
+
+#define KRB4_PLUGIN_DEPS L"Krb5Cred\0"
+
+#define KRB4_CREDTYPE_NAME L"Krb4Cred"
+
+#define KRB4_CONFIG_NODE_NAME L"Krb4Config"
+
+extern khm_handle csp_plugins;
+extern khm_handle csp_krbcred;
+extern khm_handle csp_params;
+
+extern kconf_schema schema_krbconfig[];
+
+/* other globals */
+extern khm_int32 credtype_id_krb4;
+
+extern khm_boolean krb4_initialized;
+
+extern khm_handle krb4_credset;
+
+/* plugin callbacks */
+khm_int32 KHMAPI
+krb4_cb(khm_int32 msg_type, khm_int32 msg_subtype,
+ khm_ui_4 uparam, void * vparam);
+
+INT_PTR CALLBACK
+krb4_confg_proc(HWND hwnd,
+ UINT uMsg,
+ WPARAM wParam,
+ LPARAM lParam);
+#endif
diff --git a/src/windows/identity/plugins/krb4/lang/en_us/langres.rc b/src/windows/identity/plugins/krb4/lang/en_us/langres.rc
new file mode 100644
index 0000000..a5d62a2
--- /dev/null
+++ b/src/windows/identity/plugins/krb4/lang/en_us/langres.rc
@@ -0,0 +1,141 @@
+// Microsoft Visual C++ generated resource script.
+//
+#include "..\..\langres.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "afxres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// English (U.S.) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+#ifdef _WIN32
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+#pragma code_page(1252)
+#endif //_WIN32
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE
+BEGIN
+ "..\\..\\langres.h\0"
+END
+
+2 TEXTINCLUDE
+BEGIN
+ "#include ""afxres.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+IDD_NC_KRB4 DIALOGEX 0, 0, 300, 166
+STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD | WS_SYSMENU
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg", 400, 0, 0x1
+BEGIN
+ LTEXT "kRB4",IDC_STATIC,38,43,71,24
+END
+
+IDD_CFG_KRB4 DIALOGEX 0, 0, 255, 182
+STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_SYSMENU
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg", 400, 0, 0x1
+BEGIN
+ LTEXT "Ticket cache location",IDC_CFG_LBL_CACHE,7,10,67,8
+ EDITTEXT IDC_CFG_CACHE,83,7,165,14,ES_AUTOHSCROLL
+ LTEXT "Config file path",IDC_CFG_LBL_CFGFILE,7,30,50,8
+ EDITTEXT IDC_CFG_CFGPATH,83,27,113,14,ES_AUTOHSCROLL
+ PUSHBUTTON "Browse...",IDC_CFG_CFGBROW,200,27,48,14
+ LTEXT "Realm file path",IDC_CFG_LBL_RLMPATH,7,50,48,8
+ EDITTEXT IDC_CFG_RLMPATH,83,47,113,14,ES_AUTOHSCROLL
+ PUSHBUTTON "Browse...",IDC_CFG_RLMBROW,200,47,48,14
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// DESIGNINFO
+//
+
+#ifdef APSTUDIO_INVOKED
+GUIDELINES DESIGNINFO
+BEGIN
+ IDD_NC_KRB4, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 293
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 159
+ END
+
+ IDD_CFG_KRB4, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 248
+ VERTGUIDE, 83
+ VERTGUIDE, 196
+ VERTGUIDE, 200
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 175
+ END
+END
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// String Table
+//
+
+STRINGTABLE
+BEGIN
+ IDS_PLUGIN_DESC "Kerberos 4 Credentials Provider"
+END
+
+STRINGTABLE
+BEGIN
+ IDS_KRB4_SHORT_DESC "Kerberos 4 tickets"
+ IDS_KRB4_LONG_DESC "Kerberos 4 tickets"
+ IDS_CFG_KRB4_LONG "Kerberos 4 Configuration"
+ IDS_CFG_KRB4_SHORT "Kerberos 4"
+END
+
+#endif // English (U.S.) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/src/windows/identity/plugins/krb4/langres.h b/src/windows/identity/plugins/krb4/langres.h
new file mode 100644
index 0000000..2096ade
--- /dev/null
+++ b/src/windows/identity/plugins/krb4/langres.h
@@ -0,0 +1,78 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by D:\work\khimaira\src\plugins\krb4\lang\en_us\langres.rc
+//
+#define IDS_UNK_ADDR_FMT 101
+#define IDS_KRB5_CREDTEXT_0 102
+#define IDD_NC_KRB4 103
+#define IDS_PLUGIN_DESC 103
+#define IDS_KEY_ENCTYPE_SHORT_DESC 104
+#define IDD_CFG_KRB4 104
+#define IDS_TKT_ENCTYPE_SHORT_DESC 105
+#define IDS_KEY_ENCTYPE_LONG_DESC 106
+#define IDS_TKT_ENCTYPE_LONG_DESC 107
+#define IDS_ADDR_LIST_SHORT_DESC 108
+#define IDS_ADDR_LIST_LONG_DESC 109
+#define IDS_ETYPE_NULL 110
+#define IDS_ETYPE_DES_CBC_CRC 111
+#define IDS_ETYPE_DES_CBC_MD4 112
+#define IDS_ETYPE_DES_CBC_MD5 113
+#define IDS_ETYPE_DES_CBC_RAW 114
+#define IDS_ETYPE_DES3_CBC_SHA 115
+#define IDS_ETYPE_DES3_CBC_RAW 116
+#define IDS_ETYPE_DES_HMAC_SHA1 117
+#define IDS_ETYPE_DES3_CBC_SHA1 118
+#define IDS_ETYPE_AES128_CTS_HMAC_SHA1_96 119
+#define IDS_ETYPE_AES256_CTS_HMAC_SHA1_96 120
+#define IDS_ETYPE_ARCFOUR_HMAC 121
+#define IDS_ETYPE_ARCFOUR_HMAC_EXP 122
+#define IDS_ETYPE_UNKNOWN 123
+#define IDS_ETYPE_LOCAL_DES3_HMAC_SHA1 124
+#define IDS_ETYPE_LOCAL_RC4_MD4 125
+#define IDS_KRB5_SHORT_DESC 126
+#define IDS_KRB5_LONG_DESC 127
+#define IDS_KRB4_SHORT_DESC 128
+#define IDS_KRB4_LONG_DESC 129
+#define IDS_KRB5_FLAGS_SHORT_DESC 130
+#define IDS_RENEW_TILL_SHORT_DESC 131
+#define IDS_RENEW_TILL_LONG_DESC 132
+#define IDS_RENEW_FOR_SHORT_DESC 133
+#define IDS_RENEW_FOR_LONG_DESC 134
+#define IDS_CFG_KRB4_LONG 135
+#define IDS_CFG_KRB4_SHORT 136
+#define IDC_NCK5_RENEWABLE 1002
+#define IDC_NCK5_FORWARDABLE 1004
+#define IDC_NCK5_REALM 1005
+#define IDC_NCK5_ADD_REALMS 1006
+#define IDC_NCK5_LIFETIME_EDIT 1008
+#define IDC_NCK5_RENEW_EDIT 1009
+#define IDC_PPK5_CRENEW 1014
+#define IDC_PPK5_CFORWARD 1015
+#define IDC_PPK5_CPROXY 1016
+#define IDC_PPK5_NAME 1017
+#define IDC_PPK5_ISSUE 1018
+#define IDC_PPK5_VALID 1019
+#define IDC_PPK5_RENEW 1020
+#define IDC_CHECK2 1022
+#define IDC_CHECK4 1024
+#define IDC_PPK5_LIFETIME 1024
+#define IDC_CHECK5 1025
+#define IDC_CFG_LBL_CACHE 1025
+#define IDC_CFG_LBL_CFGFILE 1026
+#define IDC_CFG_LBL_RLMPATH 1027
+#define IDC_CFG_CACHE 1028
+#define IDC_CFG_CFGPATH 1029
+#define IDC_CFG_RLMPATH 1030
+#define IDC_CFG_CFGBROW 1031
+#define IDC_CFG_RLMBROW 1032
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 105
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1033
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/src/windows/identity/plugins/krb4/main.c b/src/windows/identity/plugins/krb4/main.c
new file mode 100644
index 0000000..60ceb7f
--- /dev/null
+++ b/src/windows/identity/plugins/krb4/main.c
@@ -0,0 +1,191 @@
+/*
+ * Copyright (c) 2004 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#include<krbcred.h>
+#include<kherror.h>
+
+kmm_module h_khModule; /* KMM's handle to this module */
+HINSTANCE hInstance;
+HMODULE hResModule; /* HMODULE to the resource library */
+
+khm_int32 type_id_enctype = -1;
+khm_int32 type_id_addr_list = -1;
+khm_int32 type_id_krb5_flags = -1;
+
+khm_int32 attr_id_key_enctype = -1;
+khm_int32 attr_id_tkt_enctype = -1;
+khm_int32 attr_id_addr_list = -1;
+khm_int32 attr_id_krb5_flags = -1;
+khm_int32 attr_id_renew_till = -1;
+khm_int32 attr_id_renew_for = -1;
+
+khm_handle csp_plugins = NULL;
+khm_handle csp_krbcred = NULL;
+khm_handle csp_params = NULL;
+
+kmm_module_locale locales[] = {
+ LOCALE_DEF(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US), L"krb4cred_en_us.dll", KMM_MLOC_FLAG_DEFAULT)
+};
+
+int n_locales = ARRAYLENGTH(locales);
+
+/* These two probably should not do anything */
+void init_krb() {
+}
+
+void exit_krb() {
+}
+
+/* called by the NetIDMgr module manager */
+KHMEXP khm_int32 KHMAPI init_module(kmm_module h_module) {
+ khm_int32 rv = KHM_ERROR_SUCCESS;
+ kmm_plugin_reg pi;
+ wchar_t buf[256];
+
+ h_khModule = h_module;
+
+ rv = kmm_set_locale_info(h_module, locales, n_locales);
+ if(KHM_SUCCEEDED(rv)) {
+ hResModule = kmm_get_resource_hmodule(h_module);
+ } else
+ goto _exit;
+
+ ZeroMemory(&pi, sizeof(pi));
+ pi.name = KRB4_PLUGIN_NAME;
+ pi.type = KHM_PITYPE_CRED;
+ pi.icon = NULL; /*TODO: Assign icon */
+ pi.flags = 0;
+ pi.msg_proc = krb4_cb;
+ pi.dependencies = KRB4_PLUGIN_DEPS;
+ pi.description = buf;
+ LoadString(hResModule, IDS_PLUGIN_DESC,
+ buf, ARRAYLENGTH(buf));
+ kmm_provide_plugin(h_module, &pi);
+
+ if(KHM_FAILED(rv = init_imports()))
+ goto _exit;
+
+ if(KHM_FAILED(rv = init_error_funcs()))
+ goto _exit;
+
+ /* Lookup common data types */
+ if(KHM_FAILED(kcdb_type_get_id(TYPENAME_ENCTYPE, &type_id_enctype))) {
+ goto _exit;
+ }
+
+ if(KHM_FAILED(kcdb_type_get_id(TYPENAME_ADDR_LIST, &type_id_addr_list))) {
+ goto _exit;
+ }
+
+ if(KHM_FAILED(kcdb_type_get_id(TYPENAME_KRB5_FLAGS, &type_id_krb5_flags))) {
+ goto _exit;
+ }
+
+ /* Lookup common attributes */
+ if(KHM_FAILED(kcdb_attrib_get_id(ATTRNAME_KEY_ENCTYPE, &attr_id_key_enctype))) {
+ goto _exit;
+ }
+
+ if(KHM_FAILED(kcdb_attrib_get_id(ATTRNAME_TKT_ENCTYPE, &attr_id_tkt_enctype))) {
+ goto _exit;
+ }
+
+ if(KHM_FAILED(kcdb_attrib_get_id(ATTRNAME_ADDR_LIST, &attr_id_addr_list))) {
+ goto _exit;
+ }
+
+ if(KHM_FAILED(kcdb_attrib_get_id(ATTRNAME_KRB5_FLAGS, &attr_id_krb5_flags))) {
+ goto _exit;
+ }
+
+ if(KHM_FAILED(kcdb_attrib_get_id(ATTRNAME_RENEW_TILL, &attr_id_renew_till))) {
+ goto _exit;
+ }
+
+ if(KHM_FAILED(kcdb_attrib_get_id(ATTRNAME_RENEW_FOR, &attr_id_renew_for))) {
+ goto _exit;
+ }
+
+ rv = kmm_get_plugins_config(0, &csp_plugins);
+ if(KHM_FAILED(rv)) goto _exit;
+
+ rv = khc_load_schema(csp_plugins, schema_krbconfig);
+ if(KHM_FAILED(rv)) goto _exit;
+
+ rv = khc_open_space(csp_plugins, CSNAME_KRB4CRED, 0, &csp_krbcred);
+ if(KHM_FAILED(rv)) goto _exit;
+
+ rv = khc_open_space(csp_krbcred, CSNAME_PARAMS, 0, &csp_params);
+ if(KHM_FAILED(rv)) goto _exit;
+
+_exit:
+ return rv;
+}
+
+/* called by the NetIDMgr module manager */
+KHMEXP khm_int32 KHMAPI exit_module(kmm_module h_module) {
+ exit_imports();
+ exit_error_funcs();
+
+ if(csp_params) {
+ khc_close_space(csp_params);
+ csp_params = NULL;
+ }
+ if(csp_krbcred) {
+ khc_close_space(csp_krbcred);
+ csp_krbcred = NULL;
+ }
+ if(csp_plugins) {
+ khc_unload_schema(csp_plugins, schema_krbconfig);
+ khc_close_space(csp_plugins);
+ csp_plugins = NULL;
+ }
+
+ return KHM_ERROR_SUCCESS; /* the return code is ignored */
+}
+
+BOOL WINAPI DllMain(
+ HINSTANCE hinstDLL,
+ DWORD fdwReason,
+ LPVOID lpvReserved
+)
+{
+ switch(fdwReason) {
+ case DLL_PROCESS_ATTACH:
+ hInstance = hinstDLL;
+ init_krb();
+ break;
+ case DLL_PROCESS_DETACH:
+ exit_krb();
+ break;
+ case DLL_THREAD_ATTACH:
+ break;
+ case DLL_THREAD_DETACH:
+ break;
+ }
+
+ return TRUE;
+}
diff --git a/src/windows/identity/plugins/krb5/Makefile b/src/windows/identity/plugins/krb5/Makefile
new file mode 100644
index 0000000..9bf9ef0
--- /dev/null
+++ b/src/windows/identity/plugins/krb5/Makefile
@@ -0,0 +1,91 @@
+#
+# Copyright (c) 2004 Massachusetts Institute of Technology
+#
+# Permission is hereby granted, free of charge, to any person
+# obtaining a copy of this software and associated documentation files
+# (the "Software"), to deal in the Software without restriction,
+# including without limitation the rights to use, copy, modify, merge,
+# publish, distribute, sublicense, and/or sell copies of the Software,
+# and to permit persons to whom the Software is furnished to do so,
+# subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+
+
+MODULE=plugins\krb5
+!include <../../config/Makefile.w32>
+
+DLLFILE=$(BINDIR)\krb5cred.dll
+
+LIBFILE=$(LIBDIR)\krb5cred.lib
+
+OBJFILES= \
+ $(LIBDIR)\dynimport.obj \
+ $(LIBDIR)\krb5common.obj \
+ $(OBJ)\main.obj \
+ $(OBJ)\datarep.obj \
+ $(OBJ)\errorfuncs.obj \
+ $(OBJ)\krb5plugin.obj \
+ $(OBJ)\krb5props.obj \
+ $(OBJ)\krb5newcreds.obj \
+ $(OBJ)\krb5funcs.obj \
+ $(OBJ)\krb5config.obj \
+ $(OBJ)\krb5identpro.obj \
+ $(OBJ)\krb5configdlg.obj
+
+LIBFILES= \
+ $(LIBDIR)\nidmgr32.lib \
+ $(KFWLIBDIR)\loadfuncs.lib
+
+SDKLIBFILES= \
+ netapi32.lib
+
+MSGRESFILE=$(OBJ)\krb5_msgs.res
+
+$(OBJ)\krb5config.c: krbconfig.csv $(CONFDIR)\csvschema.cfg
+ $(CCSV) $** $@
+
+$(DLLFILE): $(MSGRESFILE) $(OBJFILES)
+ $(DLLGUILINK) $(LIBFILES) $(SDKLIBFILES)
+
+$(MSGRESFILE): $(OBJ)\krb5_msgs.rc
+
+$(OBJ)\krb5_msgs.rc: lang\krb5_msgs.mc
+ $(MC2RC)
+
+all: mkdirs $(DLLFILE) lang
+
+lang::
+
+# Repeat this block as necessary redefining LANG for additional
+# languages.
+
+# Begin language block
+LANG=en_us
+
+LANGDLL=$(BINDIR)\krb5cred_$(LANG).dll
+
+lang:: $(LANGDLL)
+
+$(LANGDLL): $(OBJ)\langres_$(LANG).res
+ $(DLLRESLINK)
+
+$(OBJ)\langres_$(LANG).res: lang\$(LANG)\langres.rc
+ $(RC2RES)
+
+# End language block
+
+clean::
+!if defined(INCFILES)
+ $(RM) $(INCFILES)
+!endif
diff --git a/src/windows/identity/plugins/krb5/datarep.c b/src/windows/identity/plugins/krb5/datarep.c
new file mode 100644
index 0000000..f8cc4cc
--- /dev/null
+++ b/src/windows/identity/plugins/krb5/datarep.c
@@ -0,0 +1,269 @@
+/*
+ * Copyright (c) 2004 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+/* Data representation and related functions */
+
+#include<krbcred.h>
+#include<krb5.h>
+#include<kherror.h>
+#include<strsafe.h>
+
+khm_int32 KHMAPI enctype_toString(const void * data, khm_size cbdata, wchar_t *destbuf, khm_size *pcbdestbuf, khm_int32 flags)
+{
+ int resid = 0;
+ int etype;
+ wchar_t buf[256];
+ size_t cblength;
+
+ if(cbdata != sizeof(khm_int32))
+ return KHM_ERROR_INVALID_PARM;
+
+ etype = *((khm_int32 *) data);
+
+ switch(etype) {
+ case ENCTYPE_NULL:
+ resid = IDS_ETYPE_NULL;
+ break;
+
+ case ENCTYPE_DES_CBC_CRC:
+ resid = IDS_ETYPE_DES_CBC_CRC;
+ break;
+
+ case ENCTYPE_DES_CBC_MD4:
+ resid = IDS_ETYPE_DES_CBC_MD4;
+ break;
+
+ case ENCTYPE_DES_CBC_MD5:
+ resid = IDS_ETYPE_DES_CBC_MD5;
+ break;
+
+ case ENCTYPE_DES_CBC_RAW:
+ resid = IDS_ETYPE_DES_CBC_RAW;
+ break;
+
+ case ENCTYPE_DES3_CBC_SHA:
+ resid = IDS_ETYPE_DES3_CBC_SHA;
+ break;
+
+ case ENCTYPE_DES3_CBC_RAW:
+ resid = IDS_ETYPE_DES3_CBC_RAW;
+ break;
+
+ case ENCTYPE_DES_HMAC_SHA1:
+ resid = IDS_ETYPE_DES_HMAC_SHA1;
+ break;
+
+ case ENCTYPE_DES3_CBC_SHA1:
+ resid = IDS_ETYPE_DES3_CBC_SHA1;
+ break;
+
+ case ENCTYPE_AES128_CTS_HMAC_SHA1_96:
+ resid = IDS_ETYPE_AES128_CTS_HMAC_SHA1_96;
+ break;
+
+ case ENCTYPE_AES256_CTS_HMAC_SHA1_96:
+ resid = IDS_ETYPE_AES256_CTS_HMAC_SHA1_96;
+ break;
+
+ case ENCTYPE_ARCFOUR_HMAC:
+ resid = IDS_ETYPE_ARCFOUR_HMAC;
+ break;
+
+ case ENCTYPE_ARCFOUR_HMAC_EXP:
+ resid = IDS_ETYPE_ARCFOUR_HMAC_EXP;
+ break;
+
+ case ENCTYPE_UNKNOWN:
+ resid = IDS_ETYPE_UNKNOWN;
+ break;
+
+#if 0
+ case ENCTYPE_LOCAL_DES3_HMAC_SHA1:
+ resid = IDS_ETYPE_LOCAL_DES3_HMAC_SHA1;
+ break;
+
+ case ENCTYPE_LOCAL_RC4_MD4:
+ resid = IDS_ETYPE_LOCAL_RC4_MD4;
+ break;
+#endif
+ }
+
+ if(resid != 0) {
+ LoadString(hResModule, (UINT) resid, buf, ARRAYLENGTH(buf));
+ } else {
+ StringCbPrintf(buf, sizeof(buf), L"#%d", etype);
+ }
+
+ StringCbLength(buf, ARRAYLENGTH(buf), &cblength);
+ cblength += sizeof(wchar_t);
+
+ if(!destbuf || *pcbdestbuf < cblength) {
+ *pcbdestbuf = cblength;
+ return KHM_ERROR_TOO_LONG;
+ } else {
+ StringCbCopy(destbuf, *pcbdestbuf, buf);
+ *pcbdestbuf = cblength;
+ return KHM_ERROR_SUCCESS;
+ }
+}
+
+khm_int32 KHMAPI addr_list_toString(const void *d, khm_size cb_d, wchar_t *buf, khm_size *pcb_buf, khm_int32 flags)
+{
+ /*TODO: implement this */
+ return KHM_ERROR_NOT_IMPLEMENTED;
+}
+
+khm_int32 KHMAPI krb5flags_toString(const void *d,
+ khm_size cb_d,
+ wchar_t *buf,
+ khm_size *pcb_buf,
+ khm_int32 f)
+{
+ wchar_t sbuf[32];
+ int i = 0;
+ khm_size cb;
+ khm_int32 flags;
+
+ flags = *((khm_int32 *) d);
+
+ if (flags & TKT_FLG_FORWARDABLE)
+ sbuf[i++] = L'F';
+
+ if (flags & TKT_FLG_FORWARDED)
+ sbuf[i++] = L'f';
+
+ if (flags & TKT_FLG_PROXIABLE)
+ sbuf[i++] = L'P';
+
+ if (flags & TKT_FLG_PROXY)
+ sbuf[i++] = L'p';
+
+ if (flags & TKT_FLG_MAY_POSTDATE)
+ sbuf[i++] = L'D';
+
+ if (flags & TKT_FLG_POSTDATED)
+ sbuf[i++] = L'd';
+
+ if (flags & TKT_FLG_INVALID)
+ sbuf[i++] = L'i';
+
+ if (flags & TKT_FLG_RENEWABLE)
+ sbuf[i++] = L'R';
+
+ if (flags & TKT_FLG_INITIAL)
+ sbuf[i++] = L'I';
+
+ if (flags & TKT_FLG_HW_AUTH)
+ sbuf[i++] = L'H';
+
+ if (flags & TKT_FLG_PRE_AUTH)
+ sbuf[i++] = L'A';
+
+ sbuf[i++] = L'\0';
+
+ cb = i * sizeof(wchar_t);
+
+ if (!buf || *pcb_buf < cb) {
+ *pcb_buf = cb;
+ return KHM_ERROR_TOO_LONG;
+ } else {
+ StringCbCopy(buf, *pcb_buf, sbuf);
+ *pcb_buf = cb;
+ return KHM_ERROR_SUCCESS;
+ }
+}
+
+khm_int32 serialize_krb5_addresses(krb5_address ** a, void ** buf, size_t * pcbbuf)
+{
+ /*TODO: implement this */
+ return KHM_ERROR_NOT_IMPLEMENTED;
+}
+
+#if 0
+
+wchar_t *
+one_addr(krb5_address *a)
+{
+ static wchar_t retstr[256];
+ struct hostent *h;
+ int no_resolve = 1;
+
+ retstr[0] = L'\0';
+
+ if ((a->addrtype == ADDRTYPE_INET && a->length == 4)
+#ifdef AF_INET6
+ || (a->addrtype == ADDRTYPE_INET6 && a->length == 16)
+#endif
+ )
+ {
+ int af = AF_INET;
+#ifdef AF_INET6
+ if (a->addrtype == ADDRTYPE_INET6)
+ af = AF_INET6;
+#endif
+ if (!no_resolve) {
+#ifdef HAVE_GETIPNODEBYADDR
+ int err;
+ h = getipnodebyaddr(a->contents, a->length, af, &err);
+ if (h) {
+ StringCbPrintf(retstr, sizeof(retstr), L"%S", h->h_name);
+ freehostent(h);
+ }
+#else
+ h = gethostbyaddr(a->contents, a->length, af);
+ if (h) {
+ StringCbPrintf(retstr, sizeof(retstr), L"%S", h->h_name);
+ }
+#endif
+ if (h)
+ return(retstr);
+ }
+ if (no_resolve || !h) {
+#ifdef HAVE_INET_NTOP
+ char buf[46];
+ const char *name = inet_ntop(a->addrtype, a->contents, buf, sizeof(buf));
+ if (name) {
+ StringCbPrintf(retstr, sizeof(retstr), L"%S", name);
+ return;
+ }
+#else
+ if (a->addrtype == ADDRTYPE_INET) {
+ StringCbPrintf(retstr, sizeof(retstr),
+ L"%d.%d.%d.%d", a->contents[0], a->contents[1],
+ a->contents[2], a->contents[3]);
+ return(retstr);
+ }
+#endif
+ }
+ }
+ {
+ wchar_t tmpfmt[128];
+ LoadString(hResModule, IDS_UNK_ADDR_FMT, tmpfmt, sizeof(tmpfmt)/sizeof(wchar_t));
+ StringCbPrintf(retstr, sizeof(retstr), tmpfmt, a->addrtype);
+ }
+ return(retstr);
+}
+#endif
diff --git a/src/windows/identity/plugins/krb5/datarep.h b/src/windows/identity/plugins/krb5/datarep.h
new file mode 100644
index 0000000..e5388f0
--- /dev/null
+++ b/src/windows/identity/plugins/krb5/datarep.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2004 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#ifndef __KHIMAIRA_KRB_DATAREP_H
+#define __KHIMAIRA_KRB_DATAREP_H
+
+
+khm_int32 KHMAPI enctype_toString(const void * data, khm_size cbdata, wchar_t *destbuf, khm_size *pcbdestbuf, khm_int32 flags);
+khm_int32 KHMAPI addr_list_toString(const void *, khm_size, wchar_t *, khm_size *, khm_int32);
+khm_int32 KHMAPI krb5flags_toString(const void *, khm_size, wchar_t *, khm_size *, khm_int32);
+khm_int32 KHMAPI renew_for_cb(khm_handle cred, khm_int32 id, void * buffer, khm_size * pcbsize);
+
+
+#endif \ No newline at end of file
diff --git a/src/windows/identity/plugins/krb5/errorfuncs.c b/src/windows/identity/plugins/krb5/errorfuncs.c
new file mode 100644
index 0000000..ab64889
--- /dev/null
+++ b/src/windows/identity/plugins/krb5/errorfuncs.c
@@ -0,0 +1,260 @@
+/*
+ * Copyright (c) 2004 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#include<krbcred.h>
+#include<kherror.h>
+
+extern void (__cdecl *pinitialize_krb_error_func)();
+extern void (__cdecl *pinitialize_kadm_error_table)();
+
+
+khm_int32 init_error_funcs()
+{
+ return KHM_ERROR_SUCCESS;
+}
+
+khm_int32 exit_error_funcs()
+{
+ return KHM_ERROR_SUCCESS;
+}
+
+#ifdef DEPRECATED_REMOVABLE
+HWND GetRootParent (HWND Child)
+{
+ HWND Last;
+ while (Child)
+ {
+ Last = Child;
+ Child = GetParent (Child);
+ }
+ return Last;
+}
+#endif
+
+void khm_err_describe(long code, wchar_t * buf, khm_size cbbuf,
+ DWORD * suggestion,
+ kherr_suggestion * suggest_code)
+{
+ const char * com_err_msg;
+ int offset;
+ long table_num;
+ DWORD msg_id = 0;
+ DWORD sugg_id = 0;
+ kherr_suggestion sugg_code = KHERR_SUGGEST_NONE;
+
+ if (suggestion == NULL || buf == NULL || cbbuf == 0 || suggest_code == 0)
+ return;
+
+ *buf = L'\0';
+
+ offset = (int) (code & 255);
+ table_num = code - offset;
+ com_err_msg = perror_message(code);
+
+ *suggestion = 0;
+ *suggest_code = KHERR_SUGGEST_NONE;
+
+ switch(table_num)
+ {
+ case krb_err_base:
+ case kadm_err_base:
+ break;
+ default:
+ *suggest_code = KHERR_SUGGEST_RETRY;
+ AnsiStrToUnicode(buf, cbbuf, com_err_msg);
+ return;
+ }
+
+ if (table_num == krb_err_base)
+ switch(offset)
+ {
+ case KDC_NAME_EXP: /* 001 Principal expired */
+ case KDC_SERVICE_EXP: /* 002 Service expired */
+ case KDC_AUTH_EXP: /* 003 Auth expired */
+ case KDC_PKT_VER: /* 004 Protocol version unknown */
+ case KDC_P_MKEY_VER: /* 005 Wrong master key version */
+ case KDC_S_MKEY_VER: /* 006 Wrong master key version */
+ case KDC_BYTE_ORDER: /* 007 Byte order unknown */
+ case KDC_PR_N_UNIQUE: /* 009 Principal not unique */
+ case KDC_NULL_KEY: /* 010 Principal has null key */
+ case KDC_GEN_ERR: /* 011 Generic error from KDC */
+ case INTK_W_NOTALL : /* 061 Not ALL tickets returned */
+ case INTK_PROT : /* 063 Protocol Error */
+ case INTK_ERR : /* 070 Other error */
+ msg_id = MSG_ERR_UNKNOWN;
+ sugg_code = KHERR_SUGGEST_RETRY;
+ break;
+
+ case KDC_PR_UNKNOWN: /* 008 Principal unknown */
+ msg_id = MSG_ERR_PR_UNKNOWN;
+ sugg_code = KHERR_SUGGEST_RETRY;
+ break;
+ case GC_TKFIL : /* 021 Can't read ticket file */
+ case GC_NOTKT : /* 022 Can't find ticket or TGT */
+ msg_id = MSG_ERR_TKFIL;
+ sugg_id = MSG_ERR_S_TKFIL;
+ sugg_code = KHERR_SUGGEST_RETRY;
+ break;
+ case MK_AP_TGTEXP : /* 026 TGT Expired */
+ /* no extra error msg */
+ break;
+
+ case RD_AP_TIME : /* 037 delta_t too big */
+ msg_id = MSG_ERR_CLOCKSKEW;
+ sugg_id = MSG_ERR_S_CLOCKSKEW;
+ sugg_code = KHERR_SUGGEST_RETRY;
+ break;
+
+ case RD_AP_UNDEC : /* 031 Can't decode
+ authenticator */
+ case RD_AP_EXP : /* 032 Ticket expired */
+ case RD_AP_NYV : /* 033 Ticket not yet valid */
+ case RD_AP_REPEAT : /* 034 Repeated request */
+ case RD_AP_NOT_US : /* 035 The ticket isn't for us */
+ case RD_AP_INCON : /* 036 Request is inconsistent */
+ case RD_AP_BADD : /* 038 Incorrect net address */
+ case RD_AP_VERSION : /* 039 protocol version mismatch */
+ case RD_AP_MSG_TYPE : /* 040 invalid msg type */
+ case RD_AP_MODIFIED : /* 041 message stream modified */
+ case RD_AP_ORDER : /* 042 message out of order */
+ case RD_AP_UNAUTHOR : /* 043 unauthorized request */
+ /* no extra error msg */
+ sugg_code = KHERR_SUGGEST_RETRY;
+ break;
+
+ case GT_PW_NULL: /* 51 Current PW is null */
+ case GT_PW_BADPW: /* 52 Incorrect current password */
+ case GT_PW_PROT: /* 53 Protocol Error */
+ case GT_PW_KDCERR: /* 54 Error returned by KDC */
+ case GT_PW_NULLTKT: /* 55 Null tkt returned by KDC */
+ /* no error msg yet */
+ sugg_code = KHERR_SUGGEST_RETRY;
+ break;
+
+ /* Values returned by send_to_kdc */
+ case SKDC_RETRY : /* 56 Retry count exceeded */
+ case SKDC_CANT : /* 57 Can't send request */
+ msg_id = MSG_ERR_KDC_CONTACT;
+ break;
+ /* no error message on purpose: */
+ case INTK_BADPW : /* 062 Incorrect password */
+ sugg_code = KHERR_SUGGEST_RETRY;
+ break;
+ default:
+ /* no extra error msg */
+ break;
+ }
+ else
+ switch(code)
+ {
+ case KADM_INSECURE_PW:
+ /* if( kadm_info != NULL ){
+ * wsprintf(buf, "%s\n%s", com_err_msg, kadm_info);
+ * } else {
+ * wsprintf(buf, "%s\nPlease see the help file for information "
+ * "about secure passwords.", com_err_msg);
+ * }
+ * com_err_msg = buf;
+ */
+
+ /* The above code would be preferred since it allows site
+ * specific information to be delivered from the Kerberos
+ * server. However the message box is too small for VGA
+ * screens. It does work well if we only have to support
+ * 1024x768
+ */
+
+ msg_id = MSG_ERR_INSECURE_PW;
+ sugg_code = KHERR_SUGGEST_RETRY;
+ break;
+
+ default:
+ /* no extra error msg */
+ break;
+ }
+
+ if (msg_id != 0) {
+ FormatMessage(FORMAT_MESSAGE_FROM_HMODULE |
+ FORMAT_MESSAGE_IGNORE_INSERTS,
+ KHERR_HMODULE,
+ msg_id,
+ 0,
+ buf,
+ (int) (cbbuf / sizeof(buf[0])),
+ NULL);
+ }
+
+ if (sugg_id != 0) {
+ *suggestion = sugg_id;
+ }
+
+ if (sugg_code != KHERR_SUGGEST_NONE)
+ *suggest_code = sugg_code;
+}
+
+#ifdef DEPRECATED_REMOVABLE
+int lsh_com_err_proc (LPSTR whoami, long code,
+ LPSTR fmt, va_list args)
+{
+ int retval;
+ HWND hOldFocus;
+ char buf[1024], *cp;
+ WORD mbformat = MB_OK | MB_ICONEXCLAMATION;
+
+ cp = buf;
+ memset(buf, '\0', sizeof(buf));
+ cp[0] = '\0';
+
+ if (code)
+ {
+ err_describe(buf, code);
+ while (*cp)
+ cp++;
+ }
+
+ if (fmt)
+ {
+ if (fmt[0] == '%' && fmt[1] == 'b')
+ {
+ fmt += 2;
+ mbformat = va_arg(args, WORD);
+ /* if the first arg is a %b, we use it for the message
+ box MB_??? flags. */
+ }
+ if (code)
+ {
+ *cp++ = '\n';
+ *cp++ = '\n';
+ }
+ wvsprintfA((LPSTR)cp, fmt, args);
+ }
+ hOldFocus = GetFocus();
+ retval = MessageBoxA(/*GetRootParent(hOldFocus)*/NULL, buf, whoami,
+ mbformat | MB_ICONHAND | MB_TASKMODAL);
+ SetFocus(hOldFocus);
+ return retval;
+}
+#endif
diff --git a/src/windows/identity/plugins/krb5/errorfuncs.h b/src/windows/identity/plugins/krb5/errorfuncs.h
new file mode 100644
index 0000000..46d68f9
--- /dev/null
+++ b/src/windows/identity/plugins/krb5/errorfuncs.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2004 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#ifndef __KHIMAIRA_ERR_H
+#define __KHIMAIRA_ERR_H
+
+/* All error handling and reporting related functions for the krb4/5
+ and AFS plugins */
+
+#include <errno.h>
+#include <com_err.h>
+/*
+ * This is a hack needed because the real com_err.h does
+ * not define err_func. We need it in the case where
+ * we pull in the real com_err instead of the krb4
+ * impostor.
+ */
+#ifndef _DCNS_MIT_COM_ERR_H
+typedef LPSTR (*err_func)(int, long);
+#endif
+
+#include <krberr.h>
+#include <kadm_err.h>
+
+#define kadm_err_base ERROR_TABLE_BASE_kadm
+
+#include <stdarg.h>
+
+#ifndef KRBERR
+#define KRBERR(code) (code + krb_err_base)
+#endif
+
+/*! \internal
+ \brief Describe an error
+
+ \param[in] code Error code returned by Kerberos
+ \param[out] buf Receives the error string
+ \param[in] cbbuf Size of buffer pointed to by \a buf
+ \param[out] suggestion Message ID of suggestion
+ \param[out] suggest_code Suggestion ID
+*/
+void khm_err_describe(long code, wchar_t * buf, khm_size cbbuf,
+ DWORD * suggestion,
+ kherr_suggestion * suggest_code);
+
+/* */
+khm_int32 init_error_funcs();
+
+khm_int32 exit_error_funcs();
+
+
+#endif
diff --git a/src/windows/identity/plugins/krb5/krb5configdlg.c b/src/windows/identity/plugins/krb5/krb5configdlg.c
new file mode 100644
index 0000000..c3b00e1
--- /dev/null
+++ b/src/windows/identity/plugins/krb5/krb5configdlg.c
@@ -0,0 +1,421 @@
+/*
+ * Copyright (c) 2004 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#include<krbcred.h>
+#include<krb5.h>
+#include<assert.h>
+#include<lm.h>
+
+INT_PTR CALLBACK
+k5_config_dlgproc(HWND hwnd,
+ UINT uMsg,
+ WPARAM wParam,
+ LPARAM lParam) {
+ switch(uMsg) {
+ case WM_INITDIALOG:
+ {
+ HWND hw;
+ wchar_t * realms;
+ wchar_t * defrealm;
+ wchar_t * t;
+ char conffile[MAX_PATH];
+ wchar_t wconffile[MAX_PATH];
+ wchar_t importopts[256];
+ WKSTA_INFO_100 * winfo100;
+
+ hw = GetDlgItem(hwnd, IDC_CFG_DEFREALM);
+#ifdef DEBUG
+ assert(hw);
+#endif
+ realms = khm_krb5_get_realm_list();
+ defrealm = khm_krb5_get_default_realm();
+#ifdef DEBUG
+ assert(realms);
+ assert(defrealm);
+#endif
+
+ SendMessage(hw, CB_RESETCONTENT, 0, 0);
+
+ for(t = realms; t && *t; t = multi_string_next(t)) {
+ SendMessage(hw, CB_ADDSTRING, 0, (LPARAM) t);
+ }
+
+ SendMessage(hw, CB_SELECTSTRING, -1, (LPARAM) defrealm);
+
+ free(defrealm);
+ free(realms);
+
+ khm_get_profile_file(conffile, sizeof(conffile));
+
+ AnsiStrToUnicode(wconffile, sizeof(wconffile), conffile);
+
+ SetDlgItemText(hwnd, IDC_CFG_CFGFILE, wconffile);
+
+ /* hostname/domain */
+ if (NetWkstaGetInfo(NULL, 100, (LPBYTE *) &winfo100) == NERR_Success) {
+ SetDlgItemText(hwnd, IDC_CFG_HOSTNAME, winfo100->wki100_computername);
+ SetDlgItemText(hwnd, IDC_CFG_DOMAIN, winfo100->wki100_langroup);
+ NetApiBufferFree(winfo100);
+ }
+
+ /* and the import ticket options */
+ LoadString(hResModule, IDS_K5CFG_IMPORT_OPTIONS,
+ importopts, ARRAYLENGTH(importopts));
+
+ hw = GetDlgItem(hwnd, IDC_CFG_IMPORT);
+#ifdef DEBUG
+ assert(hw);
+#endif
+ SendMessage(hw, CB_RESETCONTENT, 0, 0);
+
+ for (t=importopts;
+ t && *t && *t != L' ' &&
+ t < importopts + ARRAYLENGTH(importopts);
+ t = multi_string_next(t)) {
+
+ SendMessage(hw, CB_ADDSTRING, 0, (LPARAM) t);
+ }
+
+ SendMessage(hw, CB_SETCURSEL, 0, 0);
+
+ }
+ break;
+
+ case WM_DESTROY:
+ break;
+ }
+ return FALSE;
+}
+
+INT_PTR CALLBACK
+k5_realms_dlgproc(HWND hwndDlg,
+ UINT uMsg,
+ WPARAM wParam,
+ LPARAM lParam) {
+ switch(uMsg) {
+ case WM_INITDIALOG:
+ break;
+
+ case WM_DESTROY:
+ break;
+ }
+ return FALSE;
+}
+
+typedef struct tag_k5_ids_dlg_data {
+ khui_tracker tc_life;
+ khui_tracker tc_renew;
+ khui_tracker tc_life_min;
+ khui_tracker tc_life_max;
+ khui_tracker tc_renew_min;
+ khui_tracker tc_renew_max;
+
+ time_t life;
+ time_t renew_life;
+ time_t life_min;
+ time_t life_max;
+ time_t renew_min;
+ time_t renew_max;
+} k5_ids_dlg_data;
+
+static void
+k5_ids_read_params(k5_ids_dlg_data * d) {
+ khm_int32 t;
+ khm_int32 rv;
+
+#ifdef DEBUG
+ assert(csp_params);
+#endif
+
+ rv = khc_read_int32(csp_params, L"DefaultLifetime", &t);
+ assert(KHM_SUCCEEDED(rv));
+ d->life = t;
+
+ rv = khc_read_int32(csp_params, L"DefaultRenewLifetime", &t);
+ assert(KHM_SUCCEEDED(rv));
+ d->renew_life = t;
+
+ rv = khc_read_int32(csp_params, L"MaxLifetime", &t);
+ assert(KHM_SUCCEEDED(rv));
+ d->life_max = t;
+
+ rv = khc_read_int32(csp_params, L"MinLifetime", &t);
+ assert(KHM_SUCCEEDED(rv));
+ d->life_min = t;
+
+ rv = khc_read_int32(csp_params, L"MaxRenewLifetime", &t);
+ assert(KHM_SUCCEEDED(rv));
+ d->renew_max = t;
+
+ rv = khc_read_int32(csp_params, L"MinRenewLifetime", &t);
+ assert(KHM_SUCCEEDED(rv));
+ d->renew_min = t;
+
+ khui_tracker_initialize(&d->tc_life);
+ d->tc_life.current = d->life;
+ d->tc_life.min = 0;
+ d->tc_life.max = 3600 * 24 * 7;
+
+ khui_tracker_initialize(&d->tc_renew);
+ d->tc_renew.current = d->renew_life;
+ d->tc_renew.min = 0;
+ d->tc_renew.max = 3600 * 24 * 30;
+
+ khui_tracker_initialize(&d->tc_life_min);
+ d->tc_life_min.current = d->life_min;
+ d->tc_life_min.min = d->tc_life.min;
+ d->tc_life_min.max = d->tc_life.max;
+
+ khui_tracker_initialize(&d->tc_life_max);
+ d->tc_life_max.current = d->life_max;
+ d->tc_life_max.min = d->tc_life.min;
+ d->tc_life_max.max = d->tc_life.max;
+
+ khui_tracker_initialize(&d->tc_renew_min);
+ d->tc_renew_min.current = d->renew_min;
+ d->tc_renew_min.min = d->tc_renew.min;
+ d->tc_renew_min.max = d->tc_renew.max;
+
+ khui_tracker_initialize(&d->tc_renew_max);
+ d->tc_renew_max.current = d->renew_max;
+ d->tc_renew_max.min = d->tc_renew.min;
+ d->tc_renew_max.max = d->tc_renew.max;
+}
+
+INT_PTR CALLBACK
+k5_ids_tab_dlgproc(HWND hwnd,
+ UINT uMsg,
+ WPARAM wParam,
+ LPARAM lParam) {
+ k5_ids_dlg_data * d;
+
+ switch(uMsg) {
+ case WM_INITDIALOG:
+ d = malloc(sizeof(*d));
+#ifdef DEBUG
+ assert(d);
+#endif
+ ZeroMemory(d, sizeof(*d));
+#pragma warning(push)
+#pragma warning(disable: 4244)
+ SetWindowLongPtr(hwnd, DWLP_USER, (LONG_PTR) d);
+#pragma warning(pop)
+
+ k5_ids_read_params(d);
+
+ khui_tracker_install(GetDlgItem(hwnd, IDC_CFG_DEFLIFE),
+ &d->tc_life);
+ khui_tracker_install(GetDlgItem(hwnd, IDC_CFG_DEFRLIFE),
+ &d->tc_renew);
+ khui_tracker_install(GetDlgItem(hwnd, IDC_CFG_LRNG_MIN),
+ &d->tc_life_min);
+ khui_tracker_install(GetDlgItem(hwnd, IDC_CFG_LRNG_MAX),
+ &d->tc_life_max);
+ khui_tracker_install(GetDlgItem(hwnd, IDC_CFG_RLRNG_MIN),
+ &d->tc_renew_min);
+ khui_tracker_install(GetDlgItem(hwnd, IDC_CFG_RLRNG_MAX),
+ &d->tc_renew_max);
+ khui_tracker_refresh(&d->tc_life);
+ khui_tracker_refresh(&d->tc_life_min);
+ khui_tracker_refresh(&d->tc_life_max);
+ khui_tracker_refresh(&d->tc_renew);
+ khui_tracker_refresh(&d->tc_renew_min);
+ khui_tracker_refresh(&d->tc_renew_max);
+ break;
+
+ case WM_DESTROY:
+ d = (k5_ids_dlg_data *) (LONG_PTR)
+ GetWindowLongPtr(hwnd, DWLP_USER);
+
+ khui_tracker_kill_controls(&d->tc_life);
+ khui_tracker_kill_controls(&d->tc_renew);
+ khui_tracker_kill_controls(&d->tc_life_min);
+ khui_tracker_kill_controls(&d->tc_life_max);
+ khui_tracker_kill_controls(&d->tc_renew_min);
+ khui_tracker_kill_controls(&d->tc_renew_max);
+ break;
+ }
+ return FALSE;
+}
+
+INT_PTR CALLBACK
+k5_id_tab_dlgproc(HWND hwndDlg,
+ UINT uMsg,
+ WPARAM wParam,
+ LPARAM lParam) {
+ switch(uMsg) {
+ case WM_INITDIALOG:
+ break;
+
+ case WM_DESTROY:
+ break;
+ }
+ return FALSE;
+}
+
+
+void
+k5_register_config_panels(void) {
+ khui_config_node node;
+ khui_config_node_reg reg;
+ wchar_t wshort[KHUI_MAXCCH_SHORT_DESC];
+ wchar_t wlong[KHUI_MAXCCH_LONG_DESC];
+
+ ZeroMemory(&reg, sizeof(reg));
+
+ LoadString(hResModule, IDS_K5CFG_SHORT_DESC,
+ wshort, ARRAYLENGTH(wshort));
+ LoadString(hResModule, IDS_K5CFG_LONG_DESC,
+ wlong, ARRAYLENGTH(wlong));
+
+ reg.name = L"Kerberos5";
+ reg.short_desc = wshort;
+ reg.long_desc = wlong;
+ reg.h_module = hResModule;
+ reg.dlg_template = MAKEINTRESOURCE(IDD_CONFIG);
+ reg.dlg_proc = k5_config_dlgproc;
+ reg.flags = 0;
+
+ khui_cfg_register(NULL, &reg);
+
+ if (KHM_FAILED(khui_cfg_open(NULL, L"Kerberos5", &node))) {
+ node = NULL;
+#ifdef DEBUG
+ assert(FALSE);
+#endif
+ }
+
+ ZeroMemory(&reg, sizeof(reg));
+
+ LoadString(hResModule, IDS_K5RLM_SHORT_DESC,
+ wshort, ARRAYLENGTH(wshort));
+ LoadString(hResModule, IDS_K5RLM_LONG_DESC,
+ wlong, ARRAYLENGTH(wlong));
+
+ reg.name = L"KerberosRealms";
+ reg.short_desc = wshort;
+ reg.long_desc = wlong;
+ reg.h_module = hResModule;
+ reg.dlg_template = MAKEINTRESOURCE(IDD_CFG_REALMS);
+ reg.dlg_proc = k5_realms_dlgproc;
+ reg.flags = 0;
+
+ khui_cfg_register(node, &reg);
+
+ khui_cfg_release(node);
+
+ if (KHM_FAILED(khui_cfg_open(NULL, L"KhmIdentities", &node))) {
+ node = NULL;
+#ifdef DEBUG
+ assert(FALSE);
+#endif
+ }
+
+ ZeroMemory(&reg, sizeof(reg));
+
+ LoadString(hResModule, IDS_K5CFG_IDS_SHORT_DESC,
+ wshort, ARRAYLENGTH(wshort));
+ LoadString(hResModule, IDS_K5CFG_IDS_LONG_DESC,
+ wlong, ARRAYLENGTH(wlong));
+
+ reg.name = L"KerberosIdentities";
+ reg.short_desc = wshort;
+ reg.long_desc = wlong;
+ reg.h_module = hResModule;
+ reg.dlg_template = MAKEINTRESOURCE(IDD_CFG_IDS_TAB);
+ reg.dlg_proc = k5_ids_tab_dlgproc;
+ reg.flags = KHUI_CNFLAG_SUBPANEL;
+
+ khui_cfg_register(node, &reg);
+
+ ZeroMemory(&reg, sizeof(reg));
+
+ LoadString(hResModule, IDS_K5CFG_ID_SHORT_DESC,
+ wshort, ARRAYLENGTH(wshort));
+ LoadString(hResModule, IDS_K5CFG_ID_LONG_DESC,
+ wlong, ARRAYLENGTH(wlong));
+
+ reg.name = L"KerberosIdentitiesPlural";
+ reg.short_desc = wshort;
+ reg.long_desc = wlong;
+ reg.h_module = hResModule;
+ reg.dlg_template = MAKEINTRESOURCE(IDD_CFG_ID_TAB);
+ reg.dlg_proc = k5_id_tab_dlgproc;
+ reg.flags = KHUI_CNFLAG_SUBPANEL | KHUI_CNFLAG_PLURAL;
+
+ khui_cfg_register(node, &reg);
+
+ khui_cfg_release(node);
+}
+
+void
+k5_unregister_config_panels(void) {
+ khui_config_node node_main;
+ khui_config_node node_realms;
+ khui_config_node node_ids;
+ khui_config_node node_tab;
+
+ if (KHM_FAILED(khui_cfg_open(NULL, L"Kerberos5", &node_main))) {
+ node_main = NULL;
+#ifdef DEBUG
+ assert(FALSE);
+#endif
+ }
+
+ if (KHM_SUCCEEDED(khui_cfg_open(node_main, L"KerberosRealms",
+ &node_realms))) {
+ khui_cfg_remove(node_realms);
+ khui_cfg_release(node_realms);
+ }
+#ifdef DEBUG
+ else
+ assert(FALSE);
+#endif
+
+ if (node_main) {
+ khui_cfg_remove(node_main);
+ khui_cfg_release(node_main);
+ }
+
+ if (KHM_FAILED(khui_cfg_open(NULL, L"KhmIdentities", &node_ids))) {
+ node_ids = NULL;
+#ifdef DEBUG
+ assert(FALSE);
+#endif
+ }
+
+ if (KHM_SUCCEEDED(khui_cfg_open(node_ids, L"KerberosIdentities", &node_tab))) {
+ khui_cfg_remove(node_tab);
+ khui_cfg_release(node_tab);
+ }
+ if (KHM_SUCCEEDED(khui_cfg_open(node_ids, L"KerberosIdentitiesPlural", &node_tab))) {
+ khui_cfg_remove(node_tab);
+ khui_cfg_release(node_tab);
+ }
+
+ if (node_ids)
+ khui_cfg_release(node_ids);
+}
diff --git a/src/windows/identity/plugins/krb5/krb5funcs.c b/src/windows/identity/plugins/krb5/krb5funcs.c
new file mode 100644
index 0000000..d3c97ff
--- /dev/null
+++ b/src/windows/identity/plugins/krb5/krb5funcs.c
@@ -0,0 +1,1889 @@
+/*
+* Copyright (c) 2004 Massachusetts Institute of Technology
+*
+* Permission is hereby granted, free of charge, to any person
+* obtaining a copy of this software and associated documentation
+* files (the "Software"), to deal in the Software without
+* restriction, including without limitation the rights to use, copy,
+* modify, merge, publish, distribute, sublicense, and/or sell copies
+* of the Software, and to permit persons to whom the Software is
+* furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be
+* included in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+* SOFTWARE.
+*/
+
+/* $Id$ */
+
+/* Originally this was krb5routines.c in Leash sources. Subsequently
+modified and adapted for NetIDMgr */
+
+#include<krbcred.h>
+#include<kherror.h>
+
+#define SECURITY_WIN32
+#include <security.h>
+#include <ntsecapi.h>
+
+#include <string.h>
+#include <time.h>
+#include <assert.h>
+#include <strsafe.h>
+
+long
+khm_convert524(krb5_context alt_ctx)
+{
+ krb5_context ctx = 0;
+ krb5_error_code code = 0;
+ int icode = 0;
+ krb5_principal me = 0;
+ krb5_principal server = 0;
+ krb5_creds *v5creds = 0;
+ krb5_creds increds;
+ krb5_ccache cc = 0;
+ CREDENTIALS * v4creds = NULL;
+ static int init_ets = 1;
+
+ if (!pkrb5_init_context ||
+ !pkrb_in_tkt ||
+ !pkrb524_init_ets ||
+ !pkrb524_convert_creds_kdc)
+ return 0;
+
+ v4creds = (CREDENTIALS *) malloc(sizeof(CREDENTIALS));
+ memset((char *) v4creds, 0, sizeof(CREDENTIALS));
+
+ memset((char *) &increds, 0, sizeof(increds));
+ /*
+ From this point on, we can goto cleanup because increds is
+ initialized.
+ */
+
+ if (alt_ctx)
+ {
+ ctx = alt_ctx;
+ }
+ else
+ {
+ code = pkrb5_init_context(&ctx);
+ if (code) goto cleanup;
+ }
+
+ code = pkrb5_cc_default(ctx, &cc);
+ if (code) goto cleanup;
+
+ if ( init_ets ) {
+ pkrb524_init_ets(ctx);
+ init_ets = 0;
+ }
+
+ if (code = pkrb5_cc_get_principal(ctx, cc, &me))
+ goto cleanup;
+
+ if ((code = pkrb5_build_principal(ctx,
+ &server,
+ krb5_princ_realm(ctx, me)->length,
+ krb5_princ_realm(ctx, me)->data,
+ "krbtgt",
+ krb5_princ_realm(ctx, me)->data,
+ NULL)))
+ {
+ goto cleanup;
+ }
+
+ increds.client = me;
+ increds.server = server;
+ increds.times.endtime = 0;
+ increds.keyblock.enctype = ENCTYPE_DES_CBC_CRC;
+ if ((code = pkrb5_get_credentials(ctx, 0,
+ cc,
+ &increds,
+ &v5creds)))
+ {
+ goto cleanup;
+ }
+
+ if ((icode = pkrb524_convert_creds_kdc(ctx,
+ v5creds,
+ v4creds)))
+ {
+ goto cleanup;
+ }
+
+ /* initialize ticket cache */
+ if ((icode = pkrb_in_tkt(v4creds->pname, v4creds->pinst, v4creds->realm)
+ != KSUCCESS))
+ {
+ goto cleanup;
+ }
+ /* stash ticket, session key, etc. for future use */
+ if ((icode = pkrb_save_credentials(v4creds->service,
+ v4creds->instance,
+ v4creds->realm,
+ v4creds->session,
+ v4creds->lifetime,
+ v4creds->kvno,
+ &(v4creds->ticket_st),
+ v4creds->issue_date)))
+ {
+ goto cleanup;
+ }
+
+cleanup:
+ memset(v4creds, 0, sizeof(v4creds));
+ free(v4creds);
+
+ if (v5creds) {
+ pkrb5_free_creds(ctx, v5creds);
+ }
+ if (increds.client == me)
+ me = 0;
+ if (increds.server == server)
+ server = 0;
+ pkrb5_free_cred_contents(ctx, &increds);
+ if (server) {
+ pkrb5_free_principal(ctx, server);
+ }
+ if (me) {
+ pkrb5_free_principal(ctx, me);
+ }
+ pkrb5_cc_close(ctx, cc);
+
+ if (ctx && (ctx != alt_ctx)) {
+ pkrb5_free_context(ctx);
+ }
+ return !(code || icode);
+}
+
+#ifdef DEPRECATED_REMOVABLE
+int com_addr(void)
+{
+ long ipAddr;
+ char loc_addr[ADDR_SZ];
+ CREDENTIALS cred;
+ char service[40];
+ char instance[40];
+ // char addr[40];
+ char realm[40];
+ struct in_addr LocAddr;
+ int k_errno;
+
+ if (pkrb_get_cred == NULL)
+ return(KSUCCESS);
+
+ k_errno = (*pkrb_get_cred)(service,instance,realm,&cred);
+ if (k_errno)
+ return KRBERR(k_errno);
+
+ while(1) {
+ ipAddr = (*pLocalHostAddr)();
+ LocAddr.s_addr = ipAddr;
+ StringCbCopyA(loc_addr, sizeof(loc_addr), inet_ntoa(LocAddr));
+ if ( strcmp(cred.address, loc_addr) != 0) {
+ /* TODO: do something about this */
+ //Leash_kdestroy ();
+ break;
+ }
+ break;
+ } // while()
+ return 0;
+}
+#endif
+
+#ifndef ENCTYPE_LOCAL_RC4_MD4
+#define ENCTYPE_LOCAL_RC4_MD4 0xFFFFFF80
+#endif
+
+static long get_tickets_from_cache(krb5_context ctx,
+ krb5_ccache cache)
+{
+ krb5_error_code code;
+ krb5_principal KRBv5Principal;
+ krb5_flags flags = 0;
+ krb5_cc_cursor KRBv5Cursor;
+ krb5_creds KRBv5Credentials;
+ krb5_ticket *tkt=NULL;
+ char *ClientName;
+ char *PrincipalName;
+ wchar_t wbuf[256]; /* temporary conversion buffer */
+ wchar_t *wcc_name = NULL; /* credential cache name */
+ char *sServerName;
+ khm_handle ident = NULL;
+ khm_handle cred = NULL;
+ time_t tt;
+ khm_int64 ft, eft;
+ khm_int32 ti;
+
+
+#ifdef KRB5_TC_NOTICKET
+ flags = KRB5_TC_NOTICKET;
+#else
+ flags = 0;
+#endif
+
+ {
+ char * cc_name;
+ size_t namelen;
+
+ cc_name = (*pkrb5_cc_get_name)(ctx, cache);
+ if(cc_name) {
+ namelen = strlen(cc_name);
+ namelen = (namelen + 1 + 4) * sizeof(wchar_t);
+ /* the +4 is for the possible addtion of API: during the
+ cannonicalization process */
+ wcc_name = malloc(namelen);
+ AnsiStrToUnicode(wcc_name, namelen, cc_name);
+ khm_krb5_canon_cc_name(wcc_name, namelen);
+ }
+ }
+
+ if ((code = (*pkrb5_cc_set_flags)(ctx, cache, flags)))
+ {
+ if (code != KRB5_FCC_NOFILE && code != KRB5_CC_NOTFOUND)
+ khm_krb5_error(code, "krb5_cc_set_flags()", 0, &ctx, &cache);
+
+ goto _exit;
+ }
+
+ if ((code = (*pkrb5_cc_get_principal)(ctx, cache, &KRBv5Principal)))
+ {
+ if (code != KRB5_FCC_NOFILE && code != KRB5_CC_NOTFOUND)
+ khm_krb5_error(code, "krb5_cc_get_principal()", 0, &ctx, &cache);
+
+ goto _exit;
+ }
+
+ PrincipalName = NULL;
+ ClientName = NULL;
+ sServerName = NULL;
+ if ((code = (*pkrb5_unparse_name)(ctx, KRBv5Principal,
+ (char **)&PrincipalName)))
+ {
+ if (PrincipalName != NULL)
+ (*pkrb5_free_unparsed_name)(ctx, PrincipalName);
+
+ (*pkrb5_free_principal)(ctx, KRBv5Principal);
+
+ goto _exit;
+ }
+
+ if (!strcspn(PrincipalName, "@" ))
+ {
+ if (PrincipalName != NULL)
+ (*pkrb5_free_unparsed_name)(ctx, PrincipalName);
+
+ (*pkrb5_free_principal)(ctx, KRBv5Principal);
+
+ goto _exit;
+ }
+
+ AnsiStrToUnicode(wbuf, sizeof(wbuf), PrincipalName);
+ if(KHM_FAILED(kcdb_identity_create(wbuf, KCDB_IDENT_FLAG_CREATE,
+ &ident))) {
+ /* something bad happened */
+ code = 1;
+ goto _exit;
+ }
+
+ (*pkrb5_free_principal)(ctx, KRBv5Principal);
+
+ if ((code = (*pkrb5_cc_start_seq_get)(ctx, cache, &KRBv5Cursor)))
+ {
+ goto _exit;
+ }
+
+ memset(&KRBv5Credentials, '\0', sizeof(KRBv5Credentials));
+
+ ClientName = NULL;
+ sServerName = NULL;
+ cred = NULL;
+
+ while (!(code = pkrb5_cc_next_cred(ctx, cache, &KRBv5Cursor,
+ &KRBv5Credentials)))
+ {
+ khm_handle tident = NULL;
+
+ if(ClientName != NULL)
+ (*pkrb5_free_unparsed_name)(ctx, ClientName);
+ if(sServerName != NULL)
+ (*pkrb5_free_unparsed_name)(ctx, sServerName);
+ if(cred)
+ kcdb_cred_release(cred);
+
+ ClientName = NULL;
+ sServerName = NULL;
+ cred = NULL;
+
+ if ((*pkrb5_unparse_name)(ctx, KRBv5Credentials.client, &ClientName))
+ {
+ (*pkrb5_free_cred_contents)(ctx, &KRBv5Credentials);
+ khm_krb5_error(code, "krb5_free_cred_contents()", 0, &ctx, &cache);
+ continue;
+ }
+
+ if ((*pkrb5_unparse_name)(ctx, KRBv5Credentials.server, &sServerName))
+ {
+ (*pkrb5_free_cred_contents)(ctx, &KRBv5Credentials);
+ khm_krb5_error(code, "krb5_free_cred_contents()", 0, &ctx, &cache);
+ continue;
+ }
+
+ /* if the ClientName differs from PrincipalName for some
+ reason, we need to create a new identity */
+ if(strcmp(ClientName, PrincipalName)) {
+ AnsiStrToUnicode(wbuf, sizeof(wbuf), ClientName);
+ if(KHM_FAILED(kcdb_identity_create(wbuf, KCDB_IDENT_FLAG_CREATE,
+ &tident))) {
+ (*pkrb5_free_cred_contents)(ctx, &KRBv5Credentials);
+ continue;
+ }
+ } else {
+ tident = ident;
+ }
+
+ AnsiStrToUnicode(wbuf, sizeof(wbuf), sServerName);
+ if(KHM_FAILED(kcdb_cred_create(wbuf, tident, credtype_id_krb5,
+ &cred))) {
+ (*pkrb5_free_cred_contents)(ctx, &KRBv5Credentials);
+ continue;
+ }
+
+ if (!KRBv5Credentials.times.starttime)
+ KRBv5Credentials.times.starttime = KRBv5Credentials.times.authtime;
+
+ tt = KRBv5Credentials.times.starttime;
+ TimetToFileTime(tt, (LPFILETIME) &ft);
+ kcdb_cred_set_attr(cred, KCDB_ATTR_ISSUE, &ft, sizeof(ft));
+
+ tt = KRBv5Credentials.times.endtime;
+ TimetToFileTime(tt, (LPFILETIME) &eft);
+ kcdb_cred_set_attr(cred, KCDB_ATTR_EXPIRE, &eft, sizeof(eft));
+
+ eft -= ft;
+ kcdb_cred_set_attr(cred, KCDB_ATTR_LIFETIME, &eft, sizeof(eft));
+
+ if (KRBv5Credentials.times.renew_till >= 0) {
+ tt = KRBv5Credentials.times.renew_till;
+ TimetToFileTime(tt, (LPFILETIME) &eft);
+ kcdb_cred_set_attr(cred, KCDB_ATTR_RENEW_EXPIRE, &eft,
+ sizeof(eft));
+
+ eft -= ft;
+ kcdb_cred_set_attr(cred, KCDB_ATTR_RENEW_LIFETIME, &eft,
+ sizeof(eft));
+ }
+
+ ti = KRBv5Credentials.ticket_flags;
+ kcdb_cred_set_attr(cred, attr_id_krb5_flags, &ti, sizeof(ti));
+
+ /* special flags understood by NetIDMgr */
+ {
+ khm_int32 oflags, nflags;
+
+ kcdb_cred_get_flags(cred, &oflags);
+ nflags = oflags;
+
+ if (ti & TKT_FLG_RENEWABLE)
+ nflags |= KCDB_CRED_FLAG_RENEWABLE;
+ if (ti & TKT_FLG_INITIAL)
+ nflags |= KCDB_CRED_FLAG_INITIAL;
+
+ if (oflags != nflags)
+ kcdb_cred_set_flags(cred, nflags, KCDB_CRED_FLAGMASK_ALL);
+ }
+
+ if ( !pkrb5_decode_ticket(&KRBv5Credentials.ticket, &tkt)) {
+ ti = tkt->enc_part.enctype;
+ kcdb_cred_set_attr(cred, attr_id_tkt_enctype, &ti, sizeof(ti));
+ pkrb5_free_ticket(ctx, tkt);
+ tkt = NULL;
+ }
+
+ ti = KRBv5Credentials.keyblock.enctype;
+ kcdb_cred_set_attr(cred, attr_id_key_enctype, &ti, sizeof(ti));
+
+ kcdb_cred_set_attr(cred, KCDB_ATTR_LOCATION, wcc_name, KCDB_CBSIZE_AUTO);
+
+ /*TODO: going here */
+#if 0
+ if ( KRBv5Credentials.addresses && KRBv5Credentials.addresses[0] ) {
+ int n = 0;
+ while ( KRBv5Credentials.addresses[n] )
+ n++;
+ list->addrList = calloc(1, n * sizeof(char *));
+ if (!list->addrList) {
+ MessageBox(NULL, "Memory Error", "Error", MB_OK);
+ return ENOMEM;
+ }
+ list->addrCount = n;
+ for ( n=0; n<list->addrCount; n++ ) {
+ wsprintf(Buffer, "Address: %s", one_addr(KRBv5Credentials.addresses[n]));
+ list->addrList[n] = (char*) calloc(1, strlen(Buffer)+1);
+ if (!list->addrList[n])
+ {
+ MessageBox(NULL, "Memory Error", "Error", MB_OK);
+ return ENOMEM;
+ }
+ strcpy(list->addrList[n], Buffer);
+ }
+ }
+#endif
+
+ if(KRBv5Credentials.ticket_flags & TKT_FLG_INITIAL) {
+ __int64 t_expire_old;
+ __int64 t_expire_new;
+ khm_size cb;
+
+ /* an initial ticket! If we find one, we generally set
+ the lifetime, and primary ccache based on this, but
+ only if this initial cred has a greater lifetime than
+ the current primary credential. */
+
+ tt = KRBv5Credentials.times.endtime;
+ TimetToFileTime(tt, (LPFILETIME) &t_expire_new);
+
+ cb = sizeof(t_expire_old);
+ if(KHM_FAILED(kcdb_identity_get_attr(tident,
+ KCDB_ATTR_EXPIRE,
+ NULL, &t_expire_old,
+ &cb))
+ || t_expire_new > t_expire_old)
+ {
+ kcdb_identity_set_attr(tident, attr_id_krb5_ccname,
+ wcc_name, KCDB_CBSIZE_AUTO);
+ kcdb_identity_set_attr(tident, KCDB_ATTR_EXPIRE,
+ &t_expire_new,
+ sizeof(t_expire_new));
+
+ if (KRBv5Credentials.times.renew_till >= 0) {
+ tt = KRBv5Credentials.times.renew_till;
+ TimetToFileTime(tt, (LPFILETIME) &ft);
+ kcdb_identity_set_attr(tident,
+ KCDB_ATTR_RENEW_EXPIRE,
+ &ft, sizeof(ft));
+ } else {
+ kcdb_identity_set_attr(tident,
+ KCDB_ATTR_RENEW_EXPIRE,
+ NULL, 0);
+ }
+
+ ti = KRBv5Credentials.ticket_flags;
+ kcdb_identity_set_attr(tident, attr_id_krb5_flags,
+ &ti, sizeof(ti));
+ }
+ }
+
+ kcdb_credset_add_cred(krb5_credset, cred, -1);
+
+ (*pkrb5_free_cred_contents)(ctx, &KRBv5Credentials);
+
+ if(tident != ident)
+ kcdb_identity_release(tident);
+ }
+
+ if (PrincipalName != NULL)
+ (*pkrb5_free_unparsed_name)(ctx, PrincipalName);
+
+ if (ClientName != NULL)
+ (*pkrb5_free_unparsed_name)(ctx, ClientName);
+
+ if (sServerName != NULL)
+ (*pkrb5_free_unparsed_name)(ctx, sServerName);
+
+ if (cred)
+ kcdb_cred_release(cred);
+
+ if ((code == KRB5_CC_END) || (code == KRB5_CC_NOTFOUND))
+ {
+ if ((code = pkrb5_cc_end_seq_get(ctx, cache, &KRBv5Cursor)))
+ {
+ goto _exit;
+ }
+
+ flags = KRB5_TC_OPENCLOSE;
+#ifdef KRB5_TC_NOTICKET
+ flags |= KRB5_TC_NOTICKET;
+#endif
+ if ((code = pkrb5_cc_set_flags(ctx, cache, flags)))
+ {
+ goto _exit;
+ }
+ }
+ else
+ {
+ goto _exit;
+ }
+
+_exit:
+ if(wcc_name)
+ free(wcc_name);
+
+ return code;
+}
+
+long
+khm_krb5_list_tickets(krb5_context *krbv5Context)
+{
+ krb5_context ctx;
+ krb5_ccache cache;
+ krb5_error_code code;
+ apiCB * cc_ctx = 0;
+ struct _infoNC ** pNCi = NULL;
+ int i;
+
+ ctx = NULL;
+ cache = NULL;
+
+ kcdb_credset_flush(krb5_credset);
+
+ code = pcc_initialize(&cc_ctx, CC_API_VER_2, NULL, NULL);
+ if (code)
+ goto _exit;
+
+ code = pcc_get_NC_info(cc_ctx, &pNCi);
+ if (code)
+ goto _exit;
+
+ if((*krbv5Context == 0) && (code = (*pkrb5_init_context)(krbv5Context))) {
+ goto _exit;
+ }
+
+ ctx = (*krbv5Context);
+
+ for(i=0; pNCi[i]; i++) {
+ if (pNCi[i]->vers != CC_CRED_V5)
+ continue;
+
+ code = (*pkrb5_cc_resolve)(ctx, pNCi[i]->name, &cache);
+
+ if (code)
+ continue;
+
+ code = get_tickets_from_cache(ctx, cache);
+
+ if(ctx != NULL && cache != NULL)
+ (*pkrb5_cc_close)(ctx, cache);
+
+ cache = 0;
+ }
+
+_exit:
+ if (pNCi)
+ (*pcc_free_NC_info)(cc_ctx, &pNCi);
+ if (cc_ctx)
+ (*pcc_shutdown)(&cc_ctx);
+
+ kcdb_credset_collect(NULL, krb5_credset, NULL, credtype_id_krb5, NULL);
+
+ return(code);
+
+}
+
+int
+khm_krb5_renew(khm_handle identity)
+{
+ krb5_error_code code = 0;
+ krb5_context ctx = 0;
+ krb5_ccache cc = 0;
+ krb5_principal me = 0;
+ krb5_principal server = 0;
+ krb5_creds my_creds;
+ krb5_data *realm = 0;
+
+ if ( !pkrb5_init_context )
+ goto cleanup;
+
+ memset(&my_creds, 0, sizeof(krb5_creds));
+
+ code = khm_krb5_initialize(identity, &ctx, &cc);
+ if (code)
+ goto cleanup;
+
+ code = pkrb5_cc_get_principal(ctx, cc, &me);
+ if (code)
+ goto cleanup;
+
+ realm = krb5_princ_realm(ctx, me);
+
+ code = pkrb5_build_principal_ext(ctx, &server,
+ realm->length,realm->data,
+ KRB5_TGS_NAME_SIZE, KRB5_TGS_NAME,
+ realm->length,realm->data,
+ 0);
+
+ if (code)
+ goto cleanup;
+
+ my_creds.client = me;
+ my_creds.server = server;
+
+#ifdef KRB5_TC_NOTICKET
+ pkrb5_cc_set_flags(ctx, cc, 0);
+#endif
+ code = pkrb5_get_renewed_creds(ctx, &my_creds, me, cc, NULL);
+#ifdef KRB5_TC_NOTICKET
+ pkrb5_cc_set_flags(ctx, cc, KRB5_TC_NOTICKET);
+#endif
+ if (code) {
+ if ( code != KRB5KDC_ERR_ETYPE_NOSUPP ||
+ code != KRB5_KDC_UNREACH)
+ khm_krb5_error(code, "krb5_get_renewed_creds()", 0, &ctx, &cc);
+ goto cleanup;
+ }
+
+ code = pkrb5_cc_initialize(ctx, cc, me);
+ if (code) goto cleanup;
+
+ code = pkrb5_cc_store_cred(ctx, cc, &my_creds);
+ if (code) goto cleanup;
+
+cleanup:
+ if (my_creds.client == me)
+ my_creds.client = 0;
+ if (my_creds.server == server)
+ my_creds.server = 0;
+
+ pkrb5_free_cred_contents(ctx, &my_creds);
+
+ if (me)
+ pkrb5_free_principal(ctx, me);
+ if (server)
+ pkrb5_free_principal(ctx, server);
+ if (cc)
+ pkrb5_cc_close(ctx, cc);
+ if (ctx)
+ pkrb5_free_context(ctx);
+ return(code);
+}
+
+int
+khm_krb5_kinit(krb5_context alt_ctx,
+ char * principal_name,
+ char * password,
+ char * ccache,
+ krb5_deltat lifetime,
+ DWORD forwardable,
+ DWORD proxiable,
+ krb5_deltat renew_life,
+ DWORD addressless,
+ DWORD publicIP,
+ krb5_prompter_fct prompter,
+ void * p_data)
+{
+ krb5_error_code code = 0;
+ krb5_context ctx = 0;
+ krb5_ccache cc = 0;
+ krb5_principal me = 0;
+ char* name = 0;
+ krb5_creds my_creds;
+ krb5_get_init_creds_opt options;
+ krb5_address ** addrs = NULL;
+ int i = 0, addr_count = 0;
+
+ if (!pkrb5_init_context)
+ return 0;
+
+ pkrb5_get_init_creds_opt_init(&options);
+ memset(&my_creds, 0, sizeof(my_creds));
+
+ if (alt_ctx)
+ {
+ ctx = alt_ctx;
+ }
+ else
+ {
+ code = pkrb5_init_context(&ctx);
+ if (code) goto cleanup;
+ }
+
+// code = pkrb5_cc_default(ctx, &cc);
+ if (ccache)
+ code = pkrb5_cc_resolve(ctx, ccache, &cc);
+ else
+ code = pkrb5_cc_resolve(ctx, principal_name, &cc);
+ if (code) goto cleanup;
+
+ code = pkrb5_parse_name(ctx, principal_name, &me);
+ if (code) goto cleanup;
+
+ code = pkrb5_unparse_name(ctx, me, &name);
+ if (code) goto cleanup;
+
+ if (lifetime == 0) {
+ khc_read_int32(csp_params, L"DefaultLifetime", &lifetime);
+ }
+
+ if (lifetime)
+ pkrb5_get_init_creds_opt_set_tkt_life(&options, lifetime);
+ pkrb5_get_init_creds_opt_set_forwardable(&options,
+ forwardable ? 1 : 0);
+ pkrb5_get_init_creds_opt_set_proxiable(&options,
+ proxiable ? 1 : 0);
+ pkrb5_get_init_creds_opt_set_renew_life(&options,
+ renew_life);
+ if (addressless)
+ pkrb5_get_init_creds_opt_set_address_list(&options,NULL);
+ else {
+ if (publicIP)
+ {
+ // we are going to add the public IP address specified by the user
+ // to the list provided by the operating system
+ krb5_address ** local_addrs=NULL;
+ DWORD netIPAddr;
+
+ pkrb5_os_localaddr(ctx, &local_addrs);
+ while ( local_addrs[i++] );
+ addr_count = i + 1;
+
+ addrs = (krb5_address **) malloc((addr_count+1) * sizeof(krb5_address *));
+ if ( !addrs ) {
+ pkrb5_free_addresses(ctx, local_addrs);
+ assert(0);
+ }
+ memset(addrs, 0, sizeof(krb5_address *) * (addr_count+1));
+ i = 0;
+ while ( local_addrs[i] ) {
+ addrs[i] = (krb5_address *)malloc(sizeof(krb5_address));
+ if (addrs[i] == NULL) {
+ pkrb5_free_addresses(ctx, local_addrs);
+ assert(0);
+ }
+
+ addrs[i]->magic = local_addrs[i]->magic;
+ addrs[i]->addrtype = local_addrs[i]->addrtype;
+ addrs[i]->length = local_addrs[i]->length;
+ addrs[i]->contents = (unsigned char *)malloc(addrs[i]->length);
+ if (!addrs[i]->contents) {
+ pkrb5_free_addresses(ctx, local_addrs);
+ assert(0);
+ }
+
+ memcpy(addrs[i]->contents,local_addrs[i]->contents,
+ local_addrs[i]->length); /* safe */
+ i++;
+ }
+ pkrb5_free_addresses(ctx, local_addrs);
+
+ addrs[i] = (krb5_address *)malloc(sizeof(krb5_address));
+ if (addrs[i] == NULL)
+ assert(0);
+
+ addrs[i]->magic = KV5M_ADDRESS;
+ addrs[i]->addrtype = AF_INET;
+ addrs[i]->length = 4;
+ addrs[i]->contents = (unsigned char *)malloc(addrs[i]->length);
+ if (!addrs[i]->contents)
+ assert(0);
+
+ netIPAddr = htonl(publicIP);
+ memcpy(addrs[i]->contents,&netIPAddr,4);
+
+ pkrb5_get_init_creds_opt_set_address_list(&options,addrs);
+
+ }
+ }
+
+ code = pkrb5_get_init_creds_password(ctx,
+ &my_creds,
+ me,
+ password, // password
+ prompter, // prompter
+ p_data, // prompter data
+ 0, // start time
+ 0, // service name
+ &options);
+ if (code) goto cleanup;
+
+ code = pkrb5_cc_initialize(ctx, cc, me);
+ if (code) goto cleanup;
+
+ code = pkrb5_cc_store_cred(ctx, cc, &my_creds);
+ if (code) goto cleanup;
+
+cleanup:
+ if ( addrs ) {
+ for ( i=0;i<addr_count;i++ ) {
+ if ( addrs[i] ) {
+ if ( addrs[i]->contents )
+ free(addrs[i]->contents);
+ free(addrs[i]);
+ }
+ }
+ }
+ if (my_creds.client == me)
+ my_creds.client = 0;
+ pkrb5_free_cred_contents(ctx, &my_creds);
+ if (name)
+ pkrb5_free_unparsed_name(ctx, name);
+ if (me)
+ pkrb5_free_principal(ctx, me);
+ if (cc)
+ pkrb5_cc_close(ctx, cc);
+ if (ctx && (ctx != alt_ctx))
+ pkrb5_free_context(ctx);
+ return(code);
+}
+
+long
+khm_krb5_copy_ccache_by_name(krb5_context in_ctx,
+ wchar_t * wscc_dest,
+ wchar_t * wscc_src) {
+ krb5_context ctx = NULL;
+ krb5_error_code code = 0;
+ khm_boolean free_ctx;
+ krb5_ccache cc_src = NULL;
+ krb5_ccache cc_dest = NULL;
+ krb5_principal princ_src = NULL;
+ char scc_dest[KRB5_MAXCCH_CCNAME];
+ char scc_src[KRB5_MAXCCH_CCNAME];
+ int t;
+
+ t = UnicodeStrToAnsi(scc_dest, sizeof(scc_dest), wscc_dest);
+ if (t == 0)
+ return KHM_ERROR_TOO_LONG;
+ t = UnicodeStrToAnsi(scc_src, sizeof(scc_src), wscc_src);
+ if (t == 0)
+ return KHM_ERROR_TOO_LONG;
+
+ if (in_ctx) {
+ ctx = in_ctx;
+ free_ctx = FALSE;
+ } else {
+ code = pkrb5_init_context(&ctx);
+ if (code) {
+ if (ctx)
+ pkrb5_free_context(ctx);
+ return code;
+ }
+ free_ctx = TRUE;
+ }
+
+ code = pkrb5_cc_resolve(ctx, scc_dest, &cc_dest);
+ if (code)
+ goto _cleanup;
+
+ code = pkrb5_cc_resolve(ctx, scc_src, &cc_src);
+ if (code)
+ goto _cleanup;
+
+ code = pkrb5_cc_get_principal(ctx, cc_src, &princ_src);
+ if (code)
+ goto _cleanup;
+
+ code = pkrb5_cc_initialize(ctx, cc_dest, princ_src);
+ if (code)
+ goto _cleanup;
+
+ code = pkrb5_cc_copy_creds(ctx, cc_src, cc_dest);
+
+ _cleanup:
+ if (princ_src)
+ pkrb5_free_principal(ctx, princ_src);
+
+ if (cc_dest)
+ pkrb5_cc_close(ctx, cc_dest);
+
+ if (cc_src)
+ pkrb5_cc_close(ctx, cc_src);
+
+ if (free_ctx && ctx)
+ pkrb5_free_context(ctx);
+
+ return code;
+}
+
+long
+khm_krb5_canon_cc_name(wchar_t * wcc_name,
+ size_t cb_cc_name) {
+ size_t cb_len;
+ wchar_t * colon;
+
+ if (FAILED(StringCbLength(wcc_name,
+ cb_cc_name,
+ &cb_len))) {
+#ifdef DEBUG
+ assert(FALSE);
+#else
+ return KHM_ERROR_TOO_LONG;
+#endif
+ }
+
+ cb_len += sizeof(wchar_t);
+
+ colon = wcschr(wcc_name, L':');
+
+ if (colon)
+ return 0;
+
+ if (cb_len + 4 * sizeof(wchar_t) > cb_cc_name)
+ return KHM_ERROR_TOO_LONG;
+
+ memmove(&wcc_name[4], &wcc_name[0], cb_len);
+ memmove(&wcc_name[0], L"API:", sizeof(wchar_t) * 4);
+
+ return 0;
+}
+
+int
+khm_krb5_cc_name_cmp(const wchar_t * cc_name_1,
+ const wchar_t * cc_name_2) {
+ if (!wcsncmp(cc_name_1, L"API:", 4))
+ cc_name_1 += 4;
+
+ if (!wcsncmp(cc_name_2, L"API:", 4))
+ cc_name_2 += 4;
+
+ return wcscmp(cc_name_1, cc_name_2);
+}
+
+static khm_int32 KHMAPI
+khmint_location_comp_func(khm_handle cred1,
+ khm_handle cred2,
+ void * rock) {
+ return kcdb_creds_comp_attr(cred1, cred2, KCDB_ATTR_LOCATION);
+}
+
+struct khmint_location_check {
+ khm_handle credset;
+ khm_handle cred;
+ wchar_t * ccname;
+ khm_boolean success;
+};
+
+static khm_int32 KHMAPI
+khmint_find_matching_cred_func(khm_handle cred,
+ void * rock) {
+ struct khmint_location_check * lc;
+
+ lc = (struct khmint_location_check *) rock;
+
+ if (!kcdb_creds_is_equal(cred, lc->cred))
+ return KHM_ERROR_SUCCESS;
+ if (kcdb_creds_comp_attr(cred, lc->cred, KCDB_ATTR_LOCATION))
+ return KHM_ERROR_SUCCESS;
+
+ /* found it */
+ lc->success = TRUE;
+
+ /* break the search */
+ return !KHM_ERROR_SUCCESS;
+}
+
+static khm_int32 KHMAPI
+khmint_location_check_func(khm_handle cred,
+ void * rock) {
+ khm_int32 t;
+ khm_size cb;
+ wchar_t ccname[KRB5_MAXCCH_CCNAME];
+ struct khmint_location_check * lc;
+
+ lc = (struct khmint_location_check *) rock;
+
+ if (KHM_FAILED(kcdb_cred_get_type(cred, &t)))
+ return KHM_ERROR_SUCCESS;
+
+ if (t != credtype_id_krb5)
+ return KHM_ERROR_SUCCESS;
+
+ cb = sizeof(ccname);
+ if (KHM_FAILED(kcdb_cred_get_attr(cred,
+ KCDB_ATTR_LOCATION,
+ NULL,
+ ccname,
+ &cb)))
+ return KHM_ERROR_SUCCESS;
+
+ if(wcscmp(ccname, lc->ccname))
+ return KHM_ERROR_SUCCESS;
+
+ lc->cred = cred;
+
+ lc->success = FALSE;
+
+ kcdb_credset_apply(lc->credset,
+ khmint_find_matching_cred_func,
+ (void *) lc);
+
+ if (!lc->success)
+ return KHM_ERROR_NOT_FOUND;
+ else
+ return KHM_ERROR_SUCCESS;
+}
+
+static khm_int32 KHMAPI
+khmint_delete_location_func(khm_handle cred,
+ void * rock) {
+ wchar_t cc_cred[KRB5_MAXCCH_CCNAME];
+ struct khmint_location_check * lc;
+ khm_size cb;
+
+ lc = (struct khmint_location_check *) rock;
+
+ cb = sizeof(cc_cred);
+
+ if (KHM_FAILED(kcdb_cred_get_attr(cred,
+ KCDB_ATTR_LOCATION,
+ NULL,
+ cc_cred,
+ &cb)))
+ return KHM_ERROR_SUCCESS;
+
+ if (wcscmp(cc_cred, lc->ccname))
+ return KHM_ERROR_SUCCESS;
+
+ kcdb_credset_del_cred_ref(lc->credset,
+ cred);
+
+ return KHM_ERROR_SUCCESS;
+}
+
+int
+khm_krb5_destroy_by_credset(khm_handle p_cs)
+{
+ khm_handle d_cs = NULL;
+ khm_int32 rv = KHM_ERROR_SUCCESS;
+ khm_size s, cb;
+ krb5_context ctx;
+ krb5_error_code code = 0;
+ int i;
+ wchar_t ccname[KRB5_MAXCCH_CCNAME];
+ struct khmint_location_check lc;
+
+ rv = kcdb_credset_create(&d_cs);
+
+ assert(KHM_SUCCEEDED(rv) && d_cs != NULL);
+
+ kcdb_credset_extract(d_cs, p_cs, NULL, credtype_id_krb5);
+
+ kcdb_credset_get_size(d_cs, &s);
+
+ if (s == 0) {
+ /* nothing to do */
+ kcdb_credset_delete(d_cs);
+ return 0;
+ }
+
+ code = pkrb5_init_context(&ctx);
+ if (code != 0) {
+ rv = code;
+ goto _cleanup;
+ }
+
+ /* we should synchronize the credential lists before we attempt to
+ make any assumptions on the state of the root credset */
+ khm_krb5_list_tickets(&ctx);
+
+ /* so, we need to make a decision about whether to destroy entire
+ ccaches or just individual credentials. Therefore we first
+ sort them by ccache. */
+ kcdb_credset_sort(d_cs,
+ khmint_location_comp_func,
+ NULL);
+
+ /* now, for each ccache we encounter, we check if we have all the
+ credentials from that ccache in the to-be-deleted list. */
+ for (i=0; i < (int) s; i++) {
+ khm_handle cred;
+
+ if (KHM_FAILED(kcdb_credset_get_cred(d_cs,
+ i,
+ &cred)))
+ continue;
+
+ cb = sizeof(ccname);
+ rv = kcdb_cred_get_attr(cred,
+ KCDB_ATTR_LOCATION,
+ NULL,
+ ccname,
+ &cb);
+
+#ifdef DEBUG
+ assert(KHM_SUCCEEDED(rv));
+#endif
+ kcdb_cred_release(cred);
+
+ lc.credset = d_cs;
+ lc.cred = NULL;
+ lc.ccname = ccname;
+ lc.success = FALSE;
+
+ kcdb_credset_apply(NULL,
+ khmint_location_check_func,
+ (void *) &lc);
+
+ if (lc.success) {
+ /* ok the destroy the ccache */
+ char a_ccname[KRB5_MAXCCH_CCNAME];
+ krb5_ccache cc = NULL;
+
+ UnicodeStrToAnsi(a_ccname,
+ sizeof(a_ccname),
+ ccname);
+
+ code = pkrb5_cc_resolve(ctx,
+ a_ccname,
+ &cc);
+ if (code)
+ goto _delete_this_set;
+
+ code = pkrb5_cc_destroy(ctx, cc);
+
+ if (code) {
+ /*TODO: report error */
+ }
+
+ _delete_this_set:
+
+ lc.credset = d_cs;
+ lc.ccname = ccname;
+
+ /* note that although we are deleting credentials off the
+ credential set, the size of the credential set does not
+ decrease since we are doing it from inside
+ kcdb_credset_apply(). The deleted creds will simply be
+ marked as deleted until kcdb_credset_purge() is
+ called. */
+
+ kcdb_credset_apply(d_cs,
+ khmint_delete_location_func,
+ (void *) &lc);
+ }
+ }
+
+ kcdb_credset_purge(d_cs);
+
+ /* the remainder need to be deleted one by one */
+
+ kcdb_credset_get_size(d_cs, &s);
+
+ for (i=0; i < (int) s; ) {
+ khm_handle cred;
+ char a_ccname[KRB5_MAXCCH_CCNAME];
+ char a_srvname[KCDB_CRED_MAXCCH_NAME];
+ wchar_t srvname[KCDB_CRED_MAXCCH_NAME];
+ krb5_ccache cc;
+ krb5_creds in_cred, out_cred;
+ krb5_principal princ;
+ khm_int32 etype;
+
+ if (KHM_FAILED(kcdb_credset_get_cred(d_cs,
+ i,
+ &cred))) {
+ i++;
+ continue;
+ }
+
+ cb = sizeof(ccname);
+ if (KHM_FAILED(kcdb_cred_get_attr(cred,
+ KCDB_ATTR_LOCATION,
+ NULL,
+ ccname,
+ &cb)))
+ goto _done_with_this_cred;
+
+ UnicodeStrToAnsi(a_ccname,
+ sizeof(a_ccname),
+ ccname);
+
+ code = pkrb5_cc_resolve(ctx,
+ a_ccname,
+ &cc);
+
+ if (code)
+ goto _skip_similar;
+
+ code = pkrb5_cc_get_principal(ctx, cc, &princ);
+
+ if (code) {
+ pkrb5_cc_close(ctx, cc);
+ goto _skip_similar;
+ }
+
+ _del_this_cred:
+
+ cb = sizeof(etype);
+
+ if (KHM_FAILED(kcdb_cred_get_attr(cred,
+ attr_id_key_enctype,
+ NULL,
+ &etype,
+ &cb)))
+ goto _do_next_cred;
+
+ cb = sizeof(srvname);
+ if (KHM_FAILED(kcdb_cred_get_name(cred,
+ srvname,
+ &cb)))
+ goto _do_next_cred;
+
+ UnicodeStrToAnsi(a_srvname, sizeof(a_srvname), srvname);
+
+ ZeroMemory(&in_cred, sizeof(in_cred));
+
+ code = pkrb5_parse_name(ctx, a_srvname, &in_cred.server);
+ if (code)
+ goto _do_next_cred;
+ in_cred.client = princ;
+ in_cred.keyblock.enctype = etype;
+
+ code = pkrb5_cc_retrieve_cred(ctx,
+ cc,
+ KRB5_TC_MATCH_SRV_NAMEONLY |
+ KRB5_TC_SUPPORTED_KTYPES,
+ &in_cred,
+ &out_cred);
+ if (code)
+ goto _do_next_cred_0;
+
+ code = pkrb5_cc_remove_cred(ctx, cc,
+ KRB5_TC_MATCH_SRV_NAMEONLY |
+ KRB5_TC_SUPPORTED_KTYPES |
+ KRB5_TC_MATCH_AUTHDATA,
+ &out_cred);
+
+ pkrb5_free_cred_contents(ctx, &out_cred);
+ _do_next_cred_0:
+ pkrb5_free_principal(ctx, in_cred.server);
+ _do_next_cred:
+
+ /* check if the next cred is also of the same ccache */
+ kcdb_cred_release(cred);
+
+ for (i++; i < (int) s; i++) {
+ if (KHM_FAILED(kcdb_credset_get_cred(d_cs,
+ i,
+ &cred)))
+ continue;
+ }
+
+ if (i < (int) s) {
+ wchar_t newcc[KRB5_MAXCCH_CCNAME];
+
+ cb = sizeof(newcc);
+ if (KHM_FAILED(kcdb_cred_get_attr(cred,
+ KCDB_ATTR_LOCATION,
+ NULL,
+ newcc,
+ &cb)) ||
+ wcscmp(newcc, ccname)) {
+ i--; /* we have to look at this again */
+ goto _done_with_this_set;
+ }
+ goto _del_this_cred;
+ }
+
+
+ _done_with_this_set:
+ pkrb5_free_principal(ctx, princ);
+
+ pkrb5_cc_close(ctx, cc);
+
+ _done_with_this_cred:
+ kcdb_cred_release(cred);
+ i++;
+ continue;
+
+ _skip_similar:
+ kcdb_cred_release(cred);
+
+ for (++i; i < (int) s; i++) {
+ wchar_t newcc[KRB5_MAXCCH_CCNAME];
+
+ if (KHM_FAILED(kcdb_credset_get_cred(d_cs,
+ i,
+ &cred)))
+ continue;
+
+ cb = sizeof(newcc);
+ if (KHM_FAILED(kcdb_cred_get_attr(cred,
+ KCDB_ATTR_LOCATION,
+ NULL,
+ &newcc,
+ &cb))) {
+ kcdb_cred_release(cred);
+ continue;
+ }
+
+ if (wcscmp(newcc, ccname)) {
+ kcdb_cred_release(cred);
+ break;
+ }
+ }
+ }
+
+ _cleanup:
+
+ if (d_cs)
+ kcdb_credset_delete(&d_cs);
+
+ return rv;
+}
+
+int
+khm_krb5_destroy_identity(khm_handle identity)
+{
+ krb5_context ctx;
+ krb5_ccache cache;
+ krb5_error_code rc;
+
+ ctx = NULL;
+ cache = NULL;
+
+ if (rc = khm_krb5_initialize(identity, &ctx, &cache))
+ return(rc);
+
+ rc = pkrb5_cc_destroy(ctx, cache);
+
+ if (ctx != NULL)
+ pkrb5_free_context(ctx);
+
+ return(rc);
+}
+
+static BOOL
+GetSecurityLogonSessionData(PSECURITY_LOGON_SESSION_DATA * ppSessionData)
+{
+ NTSTATUS Status = 0;
+ HANDLE TokenHandle;
+ TOKEN_STATISTICS Stats;
+ DWORD ReqLen;
+ BOOL Success;
+
+ if (!ppSessionData)
+ return FALSE;
+ *ppSessionData = NULL;
+
+ Success = OpenProcessToken( GetCurrentProcess(), TOKEN_QUERY, &TokenHandle );
+ if ( !Success )
+ return FALSE;
+
+ Success = GetTokenInformation( TokenHandle, TokenStatistics, &Stats, sizeof(TOKEN_STATISTICS), &ReqLen );
+ CloseHandle( TokenHandle );
+ if ( !Success )
+ return FALSE;
+
+ Status = pLsaGetLogonSessionData( &Stats.AuthenticationId, ppSessionData );
+ if ( FAILED(Status) || !ppSessionData )
+ return FALSE;
+
+ return TRUE;
+}
+
+// IsKerberosLogon() does not validate whether or not there are valid
+// tickets in the cache. It validates whether or not it is reasonable
+// to assume that if we attempted to retrieve valid tickets we could
+// do so. Microsoft does not automatically renew expired tickets.
+// Therefore, the cache could contain expired or invalid tickets.
+// Microsoft also caches the user's password and will use it to
+// retrieve new TGTs if the cache is empty and tickets are requested.
+
+static BOOL
+IsKerberosLogon(VOID)
+{
+ PSECURITY_LOGON_SESSION_DATA pSessionData = NULL;
+ BOOL Success = FALSE;
+
+ if ( GetSecurityLogonSessionData(&pSessionData) ) {
+ if ( pSessionData->AuthenticationPackage.Buffer ) {
+ WCHAR buffer[256];
+ WCHAR *usBuffer;
+ int usLength;
+
+ Success = FALSE;
+ usBuffer = (pSessionData->AuthenticationPackage).Buffer;
+ usLength = (pSessionData->AuthenticationPackage).Length;
+ if (usLength < 256)
+ {
+ lstrcpynW (buffer, usBuffer, usLength);
+ StringCbCatW (buffer, sizeof(buffer), L"");
+ if ( !lstrcmpW(L"Kerberos",buffer) )
+ Success = TRUE;
+ }
+ }
+ pLsaFreeReturnBuffer(pSessionData);
+ }
+ return Success;
+}
+
+
+BOOL
+khm_krb5_ms2mit(BOOL save_creds)
+{
+#ifdef NO_KRB5
+ return(FALSE);
+#else /* NO_KRB5 */
+ krb5_context kcontext = 0;
+ krb5_error_code code;
+ krb5_ccache ccache=0;
+ krb5_ccache mslsa_ccache=0;
+ krb5_creds creds;
+ krb5_cc_cursor cursor=0;
+ krb5_principal princ = 0;
+ char *cache_name = NULL;
+ char *princ_name = NULL;
+ BOOL rc = FALSE;
+
+ if ( !pkrb5_init_context )
+ goto cleanup;
+
+ if (code = pkrb5_init_context(&kcontext))
+ goto cleanup;
+
+ if (code = pkrb5_cc_resolve(kcontext, "MSLSA:", &mslsa_ccache))
+ goto cleanup;
+
+ if ( save_creds ) {
+ if (code = pkrb5_cc_get_principal(kcontext, mslsa_ccache, &princ))
+ goto cleanup;
+
+ if (code = pkrb5_unparse_name(kcontext, princ, &princ_name))
+ goto cleanup;
+
+ /* TODO: actually look up the preferred ccache name */
+ if ((code = pkrb5_cc_resolve(kcontext, princ_name, &ccache)) ||
+ (code = pkrb5_cc_default(kcontext, &ccache)))
+ goto cleanup;
+
+ if (code = pkrb5_cc_initialize(kcontext, ccache, princ))
+ goto cleanup;
+
+ if (code = pkrb5_cc_copy_creds(kcontext, mslsa_ccache, ccache))
+ goto cleanup;
+
+ rc = TRUE;
+ } else {
+ /* Enumerate tickets from cache looking for an initial ticket */
+ if ((code = pkrb5_cc_start_seq_get(kcontext, mslsa_ccache, &cursor)))
+ goto cleanup;
+
+ while (!(code = pkrb5_cc_next_cred(kcontext, mslsa_ccache, &cursor, &creds)))
+ {
+ if ( creds.ticket_flags & TKT_FLG_INITIAL ) {
+ rc = TRUE;
+ pkrb5_free_cred_contents(kcontext, &creds);
+ break;
+ }
+ pkrb5_free_cred_contents(kcontext, &creds);
+ }
+ pkrb5_cc_end_seq_get(kcontext, mslsa_ccache, &cursor);
+ }
+
+cleanup:
+ if (princ_name)
+ pkrb5_free_unparsed_name(kcontext, princ_name);
+ if (princ)
+ pkrb5_free_principal(kcontext, princ);
+ if (ccache)
+ pkrb5_cc_close(kcontext, ccache);
+ if (mslsa_ccache)
+ pkrb5_cc_close(kcontext, mslsa_ccache);
+ if (kcontext)
+ pkrb5_free_context(kcontext);
+ return(rc);
+#endif /* NO_KRB5 */
+}
+
+#define KRB_FILE "KRB.CON"
+#define KRBREALM_FILE "KRBREALM.CON"
+#define KRB5_FILE "KRB5.INI"
+
+BOOL
+khm_get_profile_file(LPSTR confname, UINT szConfname)
+{
+ char **configFile = NULL;
+ if (pkrb5_get_default_config_files(&configFile))
+ {
+ GetWindowsDirectoryA(confname,szConfname);
+ confname[szConfname-1] = '\0';
+ strncat(confname, "\\",sizeof(confname)-strlen(confname));
+ confname[szConfname-1] = '\0';
+ strncat(confname, KRB5_FILE,sizeof(confname)-strlen(confname));
+ confname[szConfname-1] = '\0';
+ return FALSE;
+ }
+
+ *confname = 0;
+
+ if (configFile)
+ {
+ strncpy(confname, *configFile, szConfname);
+ pkrb5_free_config_files(configFile);
+ }
+
+ if (!*confname)
+ {
+ GetWindowsDirectoryA(confname,szConfname);
+ confname[szConfname-1] = '\0';
+ strncat(confname, "\\",sizeof(confname)-strlen(confname));
+ confname[szConfname-1] = '\0';
+ strncat(confname, KRB5_FILE,sizeof(confname)-strlen(confname));
+ confname[szConfname-1] = '\0';
+ }
+
+ return FALSE;
+}
+
+BOOL
+khm_get_krb4_con_file(LPSTR confname, UINT szConfname)
+{
+ if (hKrb5 && !hKrb4) { // hold krb.con where krb5.ini is located
+ CHAR krbConFile[MAX_PATH]="";
+ LPSTR pFind;
+
+ //strcpy(krbConFile, CLeashApp::m_krbv5_profile->first_file->filename);
+ if (khm_get_profile_file(krbConFile, sizeof(krbConFile))) {
+ GetWindowsDirectoryA(krbConFile,sizeof(krbConFile));
+ krbConFile[MAX_PATH-1] = '\0';
+ strncat(krbConFile, "\\",sizeof(krbConFile)-strlen(krbConFile));
+ krbConFile[MAX_PATH-1] = '\0';
+ strncat(krbConFile, KRB5_FILE,sizeof(krbConFile)-strlen(krbConFile));
+ krbConFile[MAX_PATH-1] = '\0';
+ }
+
+ pFind = strrchr(krbConFile, '\\');
+ if (pFind) {
+ *pFind = 0;
+ strncat(krbConFile, "\\",sizeof(krbConFile)-strlen(krbConFile));
+ krbConFile[MAX_PATH-1] = '\0';
+ strncat(krbConFile, KRB_FILE,sizeof(krbConFile)-strlen(krbConFile));
+ krbConFile[MAX_PATH-1] = '\0';
+ }
+ else
+ krbConFile[0] = 0;
+
+ strncpy(confname, krbConFile, szConfname);
+ confname[szConfname-1] = '\0';
+ }
+ else if (hKrb4) {
+ unsigned int size = szConfname;
+ memset(confname, '\0', szConfname);
+ if (!pkrb_get_krbconf2(confname, &size))
+ { // Error has happened
+ GetWindowsDirectoryA(confname,szConfname);
+ confname[szConfname-1] = '\0';
+ strncat(confname, "\\",szConfname-strlen(confname));
+ confname[szConfname-1] = '\0';
+ strncat(confname,KRB_FILE,szConfname-strlen(confname));
+ confname[szConfname-1] = '\0';
+ }
+ }
+ return FALSE;
+}
+
+int
+readstring(FILE * file, char * buf, int len)
+{
+ int c,i;
+ memset(buf, '\0', sizeof(buf));
+ for (i=0, c=fgetc(file); c != EOF ; c=fgetc(file), i++) {
+ if (i < sizeof(buf)) {
+ if (c == '\n') {
+ buf[i] = '\0';
+ return i;
+ } else {
+ buf[i] = c;
+ }
+ } else {
+ if (c == '\n') {
+ buf[len-1] = '\0';
+ return(i);
+ }
+ }
+ }
+ if (c == EOF) {
+ if (i > 0 && i < len) {
+ buf[i] = '\0';
+ return(i);
+ } else {
+ buf[len-1] = '\0';
+ return(-1);
+ }
+ }
+ return(-1);
+}
+
+/*! \internal
+ \brief Return a list of configured realms
+
+ The string that is returned is a set of null terminated unicode
+ strings, each of which denotes one realm. The set is terminated
+ by a zero length null terminated string.
+
+ The caller should free the returned string using free()
+
+ \return The string with the list of realms or NULL if the
+ operation fails.
+*/
+wchar_t * khm_krb5_get_realm_list(void)
+{
+ wchar_t * rlist = NULL;
+
+ if (pprofile_get_subsection_names && pprofile_free_list) {
+ const char* rootSection[] = {"realms", NULL};
+ const char** rootsec = rootSection;
+ char **sections = NULL, **cpp = NULL, *value = NULL;
+
+ char krb5_conf[MAX_PATH+1];
+
+ if (!khm_get_profile_file(krb5_conf,sizeof(krb5_conf))) {
+ profile_t profile;
+ long retval;
+ const char *filenames[2];
+ wchar_t * d;
+ size_t cbsize;
+ size_t t;
+
+ filenames[0] = krb5_conf;
+ filenames[1] = NULL;
+ retval = pprofile_init(filenames, &profile);
+ if (!retval) {
+ retval = pprofile_get_subsection_names(profile, rootsec,
+ &sections);
+
+ if (!retval)
+ {
+ /* first figure out how much space to allocate */
+ cbsize = 0;
+ for (cpp = sections; *cpp; cpp++)
+ {
+ cbsize += sizeof(wchar_t) * (strlen(*cpp) + 1);
+ }
+ cbsize += sizeof(wchar_t); /* double null terminated */
+
+ rlist = malloc(cbsize);
+ d = rlist;
+ for (cpp = sections; *cpp; cpp++)
+ {
+ AnsiStrToUnicode(d, cbsize, *cpp);
+ t = wcslen(d) + 1;
+ d += t;
+ cbsize -= sizeof(wchar_t) * t;
+ }
+ *d = L'\0';
+ }
+
+ pprofile_free_list(sections);
+
+#if 0
+ retval = pprofile_get_string(profile, "libdefaults","noaddresses", 0, "true", &value);
+ if ( value ) {
+ disable_noaddresses = config_boolean_to_int(value);
+ pprofile_release_string(value);
+ }
+#endif
+ pprofile_release(profile);
+ }
+ }
+ } else {
+ FILE * file;
+ char krb_conf[MAX_PATH+1];
+ char * p;
+ size_t cbsize, t;
+ wchar_t * d;
+
+ if (!khm_get_krb4_con_file(krb_conf,sizeof(krb_conf)) &&
+ (file = fopen(krb_conf, "rt")))
+ {
+ char lineBuf[256];
+
+ /*TODO: compute the actual required buffer size instead of hardcoding */
+ cbsize = 16384; // arbitrary
+ rlist = malloc(cbsize);
+ d = rlist;
+
+ // Skip the default realm
+ readstring(file,lineBuf,sizeof(lineBuf));
+
+ // Read the defined realms
+ while (TRUE)
+ {
+ if (readstring(file,lineBuf,sizeof(lineBuf)) < 0)
+ break;
+
+ if (*(lineBuf + strlen(lineBuf) - 1) == '\r')
+ *(lineBuf + strlen(lineBuf) - 1) = 0;
+
+ for (p=lineBuf; *p ; p++)
+ {
+ if (isspace(*p)) {
+ *p = 0;
+ break;
+ }
+ }
+
+ if ( strncmp(".KERBEROS.OPTION.",lineBuf,17) ) {
+ t = strlen(lineBuf) + 1;
+ if(cbsize > (1 + t*sizeof(wchar_t))) {
+ AnsiStrToUnicode(d, cbsize, lineBuf);
+ d += t;
+ cbsize -= t * sizeof(wchar_t);
+ } else
+ break;
+ }
+ }
+
+ *d = L'\0';
+
+ fclose(file);
+ }
+ }
+
+ return rlist;
+}
+
+/*! \internal
+ \brief Get the default realm
+
+ A string will be returned that specifies the default realm. The
+ caller should free the string using free().
+
+ Returns NULL if the operation fails.
+*/
+wchar_t * khm_krb5_get_default_realm(void)
+{
+ wchar_t * realm;
+ size_t cch;
+ krb5_context ctx=0;
+ char * def = 0;
+
+ pkrb5_init_context(&ctx);
+ pkrb5_get_default_realm(ctx,&def);
+
+ if (def) {
+ cch = strlen(def) + 1;
+ realm = malloc(sizeof(wchar_t) * cch);
+ AnsiStrToUnicode(realm, sizeof(wchar_t) * cch, def);
+ pkrb5_free_default_realm(ctx, def);
+ } else
+ realm = NULL;
+
+ pkrb5_free_context(ctx);
+
+ return realm;
+}
+
+wchar_t * khm_get_realm_from_princ(wchar_t * princ) {
+ wchar_t * t;
+
+ if(!princ)
+ return NULL;
+
+ for (t = princ; *t; t++) {
+ if(*t == L'\\') { /* escape */
+ t++;
+ if(! *t) /* malformed */
+ break;
+ } else if (*t == L'@')
+ break;
+ }
+
+ if (*t == '@' && *(t+1) != L'\0')
+ return (t+1);
+ else
+ return NULL;
+}
+
+long
+khm_krb5_changepwd(char * principal,
+ char * password,
+ char * newpassword,
+ char** error_str)
+{
+ krb5_error_code rc = 0;
+ int result_code;
+ krb5_data result_code_string, result_string;
+ krb5_context context = 0;
+ krb5_principal princ = 0;
+ krb5_get_init_creds_opt opts;
+ krb5_creds creds;
+
+ result_string.data = 0;
+ result_code_string.data = 0;
+
+ if ( !pkrb5_init_context )
+ goto cleanup;
+
+ if (rc = pkrb5_init_context(&context)) {
+ goto cleanup;
+ }
+
+ if (rc = pkrb5_parse_name(context, principal, &princ)) {
+ goto cleanup;
+ }
+
+ pkrb5_get_init_creds_opt_init(&opts);
+ pkrb5_get_init_creds_opt_set_tkt_life(&opts, 5*60);
+ pkrb5_get_init_creds_opt_set_renew_life(&opts, 0);
+ pkrb5_get_init_creds_opt_set_forwardable(&opts, 0);
+ pkrb5_get_init_creds_opt_set_proxiable(&opts, 0);
+ pkrb5_get_init_creds_opt_set_address_list(&opts,NULL);
+
+ if (rc = pkrb5_get_init_creds_password(context, &creds, princ,
+ password, 0, 0, 0,
+ "kadmin/changepw", &opts)) {
+ if (rc == KRB5KRB_AP_ERR_BAD_INTEGRITY) {
+#if 0
+ com_err(argv[0], 0,
+ "Password incorrect while getting initial ticket");
+#endif
+ }
+ else {
+#if 0
+ com_err(argv[0], ret, "getting initial ticket");
+#endif
+ }
+ goto cleanup;
+ }
+
+ if (rc = pkrb5_change_password(context, &creds, newpassword,
+ &result_code, &result_code_string,
+ &result_string)) {
+#if 0
+ com_err(argv[0], ret, "changing password");
+#endif
+ goto cleanup;
+ }
+
+ if (result_code) {
+ int len = result_code_string.length +
+ (result_string.length ? (sizeof(": ") - 1) : 0) +
+ result_string.length;
+ if (len && error_str) {
+ *error_str = malloc(len + 1);
+ if (*error_str)
+ StringCchPrintfA(*error_str, len+1,
+ "%.*s%s%.*s",
+ result_code_string.length,
+ result_code_string.data,
+ result_string.length?": ":"",
+ result_string.length,
+ result_string.data);
+ }
+ rc = result_code;
+ goto cleanup;
+ }
+
+ cleanup:
+ if (result_string.data)
+ pkrb5_free_data_contents(context, &result_string);
+
+ if (result_code_string.data)
+ pkrb5_free_data_contents(context, &result_code_string);
+
+ if (princ)
+ pkrb5_free_principal(context, princ);
+
+ if (context)
+ pkrb5_free_context(context);
+
+ return rc;
+}
diff --git a/src/windows/identity/plugins/krb5/krb5funcs.h b/src/windows/identity/plugins/krb5/krb5funcs.h
new file mode 100644
index 0000000..79ca956
--- /dev/null
+++ b/src/windows/identity/plugins/krb5/krb5funcs.h
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2004 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+/* Adapted from multiple Leash header files */
+
+#ifndef __KHIMAIRA_KRB5FUNCS_H
+#define __KHIMAIRA_KRB5FUNCS_H
+
+#include<stdlib.h>
+#include<krb5.h>
+
+#include <windows.h>
+#define SECURITY_WIN32
+#include <security.h>
+#include <ntsecapi.h>
+
+#include <krb5common.h>
+
+#define LEASH_DEBUG_CLASS_GENERIC 0
+#define LEASH_DEBUG_CLASS_KRB4 1
+#define LEASH_DEBUG_CLASS_KRB4_APP 2
+
+#define LEASH_PRIORITY_LOW 0
+#define LEASH_PRIORITY_HIGH 1
+
+#define KRB5_DEFAULT_LIFE 60*60*10 /* 10 hours */
+
+#define KRB5_MAXCCH_CCNAME 1024
+
+// Function Prototypes.
+
+BOOL
+khm_krb5_ms2mit(BOOL);
+
+int
+khm_krb5_kinit(krb5_context alt_ctx,
+ char * principal_name,
+ char * password,
+ char * ccache,
+ krb5_deltat lifetime,
+ DWORD forwardable,
+ DWORD proxiable,
+ krb5_deltat renew_life,
+ DWORD addressless,
+ DWORD publicIP,
+ krb5_prompter_fct prompter,
+ void * p_data);
+
+long
+khm_krb5_changepwd(char * principal,
+ char * password,
+ char * newpassword,
+ char** error_str);
+
+int
+khm_krb5_destroy_by_credset(khm_handle p_cs);
+
+int
+khm_krb5_destroy_identity(khm_handle identity);
+
+long
+khm_convert524(krb5_context ctx);
+
+int
+khm_krb5_renew(khm_handle identity);
+
+wchar_t *
+khm_krb5_get_default_realm(void);
+
+wchar_t *
+khm_krb5_get_realm_list(void);
+
+long
+khm_krb5_list_tickets(krb5_context *krbv5Context);
+
+long
+khm_krb4_list_tickets(void);
+
+wchar_t *
+khm_get_realm_from_princ(wchar_t * princ);
+
+long
+khm_krb5_copy_ccache_by_name(krb5_context in_ctx,
+ wchar_t * wscc_dest,
+ wchar_t * wscc_src);
+
+long
+khm_krb5_canon_cc_name(wchar_t * wcc_name,
+ size_t cb_cc_name);
+
+int
+khm_krb5_cc_name_cmp(const wchar_t * cc_name_1,
+ const wchar_t * cc_name_2);
+
+BOOL
+khm_get_profile_file(LPSTR confname, UINT szConfname);
+
+#endif
diff --git a/src/windows/identity/plugins/krb5/krb5identpro.c b/src/windows/identity/plugins/krb5/krb5identpro.c
new file mode 100644
index 0000000..c568e49
--- /dev/null
+++ b/src/windows/identity/plugins/krb5/krb5identpro.c
@@ -0,0 +1,1108 @@
+/*
+ * Copyright (c) 2004 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#include<krbcred.h>
+#include<kherror.h>
+#include<khmsgtypes.h>
+#include<commctrl.h>
+#include<strsafe.h>
+#include<krb5.h>
+#include<assert.h>
+
+#define K5_NCID_UN_LABEL (KHUI_CW_ID_MIN + 0)
+#define K5_NCID_UN (KHUI_CW_ID_MIN + 1)
+#define K5_NCID_REALM_LABEL (KHUI_CW_ID_MIN + 2)
+#define K5_NCID_REALM (KHUI_CW_ID_MIN + 3)
+
+#define NC_UNCHANGE_TIMEOUT 3000
+#define NC_UNCHANGE_TIMER 2
+#define NC_REALMCHANGE_TIMEOUT NC_UNCHANGE_TIMEOUT
+#define NC_REALMCHANGE_TIMER 3
+
+typedef struct tag_k5_new_cred_data {
+ HWND hw_username_label;
+ HWND hw_username;
+ HWND hw_realm_label;
+ HWND hw_realm;
+} k5_new_cred_data;
+
+int
+k5_get_realm_from_nc(khui_new_creds * nc,
+ wchar_t * buf,
+ khm_size cch_buf) {
+ k5_new_cred_data * d;
+
+ d = (k5_new_cred_data *) nc->ident_aux;
+ return GetWindowText(d->hw_realm, buf, (int) cch_buf);
+}
+
+/* set the primary identity of a new credentials dialog depending on
+ the selection of the username and realm
+
+ Runs in the UI thread
+*/
+static void
+set_identity_from_ui(khui_new_creds * nc,
+ k5_new_cred_data * d) {
+ wchar_t un[KCDB_IDENT_MAXCCH_NAME];
+ wchar_t * realm;
+ khm_size cch;
+ khm_size cch_left;
+ khm_handle ident;
+ LRESULT idx = CB_ERR;
+
+ cch = GetWindowTextLength(d->hw_username);
+
+ /* we already set the max length of the edit control to be this.
+ shouldn't exceed it unless the edit control is confused. */
+ assert(cch < KCDB_IDENT_MAXCCH_NAME - 1);
+
+ GetWindowText(d->hw_username, un, ARRAYLENGTH(un));
+
+ realm = khm_get_realm_from_princ(un);
+ if (realm) /* realm was specified */
+ goto _set_ident;
+
+ /* the cch we got from GetWindowTextLength can not be trusted to
+ be exact. For caveats see MSDN for GetWindowTextLength. */
+ StringCchLength(un, KCDB_IDENT_MAXCCH_NAME, &cch);
+
+ realm = un + cch; /* now points at terminating NULL */
+ cch_left = KCDB_IDENT_MAXCCH_NAME - cch;
+
+ *realm++ = L'@';
+ cch_left--;
+
+ cch = GetWindowTextLength(d->hw_realm);
+ if (cch == 0 || cch >= cch_left)
+ goto _set_null_ident;
+
+ GetWindowText(d->hw_realm, realm, (int) cch_left);
+
+ _set_ident:
+ if (KHM_FAILED(kcdb_identity_create(un,
+ KCDB_IDENT_FLAG_CREATE,
+ &ident)))
+ goto _set_null_ident;
+
+ khui_cw_set_primary_id(nc, ident);
+
+ kcdb_identity_release(ident);
+ return;
+
+ _set_null_ident:
+ khui_cw_set_primary_id(nc, NULL);
+ return;
+}
+
+static BOOL
+update_crossfeed(khui_new_creds * nc,
+ k5_new_cred_data * d,
+ int ctrl_id_src) {
+ wchar_t un[KCDB_IDENT_MAXCCH_NAME];
+ wchar_t * un_realm;
+ wchar_t realm[KCDB_IDENT_MAXCCH_NAME];
+ khm_size cch;
+ khm_size cch_left;
+
+ cch = (khm_size) GetWindowTextLength(d->hw_username);
+#ifdef DEBUG
+ assert(cch < KCDB_IDENT_MAXCCH_NAME);
+#endif
+ if (cch == 0)
+ return FALSE;
+
+ GetWindowText(d->hw_username,
+ un,
+ ARRAYLENGTH(un));
+
+ un_realm = khm_get_realm_from_princ(un);
+
+ if (un_realm == NULL)
+ return FALSE;
+
+ if (ctrl_id_src == K5_NCID_UN) {
+ SendMessage(d->hw_realm,
+ CB_SELECTSTRING,
+ (WPARAM) -1,
+ (LPARAM) un_realm);
+
+ SetWindowText(d->hw_realm,
+ un_realm);
+
+ return TRUE;
+ }
+ /* else... */
+
+ cch_left = KCDB_IDENT_MAXCCH_NAME - (un_realm - un);
+
+ cch = (khm_size) GetWindowTextLength(d->hw_realm);
+
+#ifdef DEBUG
+ assert(cch < KCDB_IDENT_MAXCCH_NAME);
+#endif
+ if (cch == 0)
+ return FALSE;
+
+ GetWindowText(d->hw_realm, realm,
+ ARRAYLENGTH(realm));
+
+ StringCchCopy(un_realm, cch_left, realm);
+
+ SendMessage(d->hw_username,
+ CB_SELECTSTRING,
+ (WPARAM) -1,
+ (LPARAM) un);
+
+ SetWindowText(d->hw_username, un);
+
+ return TRUE;
+}
+
+/* Handle window messages for the identity specifiers
+
+ runs in UI thread */
+static LRESULT
+handle_wnd_msg(khui_new_creds * nc,
+ HWND hwnd,
+ UINT uMsg,
+ WPARAM wParam,
+ LPARAM lParam) {
+ k5_new_cred_data * d;
+
+ d = (k5_new_cred_data *) nc->ident_aux;
+
+ switch(uMsg) {
+ case WM_COMMAND:
+ switch(wParam) {
+ case MAKEWPARAM(K5_NCID_UN, CBN_EDITCHANGE):
+ /* the username has changed. Instead of handling this
+ for every keystroke, set a timer that elapses some
+ time afterwards and then handle the event. */
+ SetTimer(hwnd, NC_UNCHANGE_TIMER,
+ NC_UNCHANGE_TIMEOUT, NULL);
+ return TRUE;
+
+ case MAKEWPARAM(K5_NCID_UN, CBN_KILLFOCUS):
+ case MAKEWPARAM(K5_NCID_UN, CBN_CLOSEUP):
+ KillTimer(hwnd, NC_UNCHANGE_TIMER);
+
+ update_crossfeed(nc,d,K5_NCID_UN);
+ set_identity_from_ui(nc,d);
+ return TRUE;
+
+ case MAKEWPARAM(K5_NCID_REALM,CBN_EDITCHANGE):
+ SetTimer(hwnd, NC_REALMCHANGE_TIMER,
+ NC_REALMCHANGE_TIMEOUT, NULL);
+ return TRUE;
+
+ case MAKEWPARAM(K5_NCID_REALM,CBN_KILLFOCUS):
+ case MAKEWPARAM(K5_NCID_REALM,CBN_CLOSEUP):
+ KillTimer(hwnd, NC_REALMCHANGE_TIMER);
+
+ update_crossfeed(nc,d,K5_NCID_REALM);
+ set_identity_from_ui(nc, d);
+ return TRUE;
+ }
+ break;
+
+ case WM_TIMER:
+ if(wParam == NC_UNCHANGE_TIMER) {
+ KillTimer(hwnd, NC_UNCHANGE_TIMER);
+
+ update_crossfeed(nc, d, K5_NCID_UN);
+ set_identity_from_ui(nc,d);
+ return TRUE;
+ } else if (wParam == NC_REALMCHANGE_TIMER) {
+ KillTimer(hwnd, NC_REALMCHANGE_TIMER);
+
+ update_crossfeed(nc, d, K5_NCID_REALM);
+ set_identity_from_ui(nc, d);
+ return TRUE;
+ }
+ break;
+ }
+ return FALSE;
+}
+
+/* UI Callback
+
+ runs in UI thread */
+static LRESULT KHMAPI
+ui_cb(khui_new_creds * nc,
+ UINT cmd,
+ HWND hwnd,
+ UINT uMsg,
+ WPARAM wParam,
+ LPARAM lParam) {
+ k5_new_cred_data * d;
+
+ d = (k5_new_cred_data *) nc->ident_aux;
+
+ switch(cmd) {
+ case WMNC_IDENT_INIT:
+ {
+ wchar_t defident[KCDB_IDENT_MAXCCH_NAME];
+ wchar_t wbuf[1024];
+ wchar_t * ms = NULL;
+ wchar_t * t;
+ wchar_t * defrealm = NULL;
+ LRESULT lr;
+ khm_size cb_ms;
+ khm_size cb;
+ HWND hw_parent;
+ khm_int32 rv;
+ khm_handle hident;
+
+ hw_parent = (HWND) lParam;
+ defident[0] = L'\0';
+
+#ifdef DEBUG
+ assert(d == NULL);
+ assert(hw_parent != NULL);
+#endif
+
+ d = malloc(sizeof(*d));
+ assert(d);
+ ZeroMemory(d, sizeof(*d));
+
+ khui_cw_lock_nc(nc);
+ nc->ident_aux = (LPARAM) d;
+ khui_cw_unlock_nc(nc);
+
+ LoadString(hResModule, IDS_NC_USERNAME,
+ wbuf, ARRAYLENGTH(wbuf));
+
+ d->hw_username_label = CreateWindow
+ (L"STATIC",
+ wbuf,
+ SS_SIMPLE | WS_CHILD | WS_VISIBLE,
+ 0, 0, 100, 100, /* bogus values */
+ hw_parent,
+ (HMENU) K5_NCID_UN_LABEL,
+ hInstance,
+ NULL);
+ assert(d->hw_username_label != NULL);
+
+ d->hw_username = CreateWindow
+ (L"COMBOBOX",
+ L"",
+ CBS_DROPDOWN | CBS_AUTOHSCROLL | CBS_SORT |
+ WS_CHILD | WS_VISIBLE | WS_TABSTOP,
+ 0, 0, 100, 100, /* bogus values */
+ hw_parent,
+ (HMENU) K5_NCID_UN,
+ hInstance,
+ NULL);
+ assert(d->hw_username != NULL);
+
+ SendMessage(d->hw_username,
+ CB_LIMITTEXT,
+ (WPARAM)(KCDB_IDENT_MAXCCH_NAME - 1),
+ 0);
+
+ SendMessage(d->hw_username,
+ CB_SETEXTENDEDUI,
+ (WPARAM) TRUE,
+ 0);
+
+ khui_cw_add_control_row(nc,
+ d->hw_username_label,
+ d->hw_username,
+ KHUI_CTRLSIZE_SMALL);
+
+ LoadString(hResModule, IDS_NC_REALM,
+ wbuf, ARRAYLENGTH(wbuf));
+
+ d->hw_realm_label = CreateWindow
+ (L"STATIC",
+ wbuf,
+ SS_SIMPLE | WS_CHILD | WS_VISIBLE,
+ 0, 0, 100, 100, /* bogus */
+ hw_parent,
+ (HMENU) K5_NCID_REALM_LABEL,
+ hInstance,
+ NULL);
+ assert(d->hw_realm_label != NULL);
+
+ d->hw_realm = CreateWindow
+ (L"COMBOBOX",
+ L"",
+ CBS_DROPDOWN | CBS_AUTOHSCROLL | CBS_SORT |
+ WS_CHILD | WS_VISIBLE | WS_TABSTOP,
+ 0, 0, 100, 100, /* bogus */
+ hw_parent,
+ (HMENU) K5_NCID_REALM,
+ hInstance,
+ NULL);
+ assert(d->hw_realm != NULL);
+
+ SendMessage(d->hw_realm,
+ CB_LIMITTEXT,
+ (WPARAM) (KCDB_IDENT_MAXCCH_NAME - 1),
+ 0);
+
+ SendMessage(d->hw_realm,
+ CB_SETEXTENDEDUI,
+ (WPARAM) TRUE,
+ 0);
+
+ khui_cw_add_control_row(nc,
+ d->hw_realm_label,
+ d->hw_realm,
+ KHUI_CTRLSIZE_SMALL);
+
+ /* add the LRU realms and principals to the dropdown
+ lists */
+ rv = khc_read_multi_string(csp_params,
+ L"LRUPrincipals",
+ NULL,
+ &cb_ms);
+
+ if (rv != KHM_ERROR_TOO_LONG)
+ goto _add_lru_realms;
+
+ ms = malloc(cb_ms);
+ assert(ms != NULL);
+
+ cb = cb_ms;
+ rv = khc_read_multi_string(csp_params,
+ L"LRUPrincipals",
+ ms,
+ &cb);
+
+ assert(KHM_SUCCEEDED(rv));
+
+ /* the first of these is considered the default identity
+ if no other default is known */
+ StringCbCopy(defident, sizeof(defident), ms);
+
+ t = ms;
+ while(t && *t) {
+ SendMessage(d->hw_username,
+ CB_ADDSTRING,
+ 0,
+ (LPARAM) t);
+
+ t = multi_string_next(t);
+ }
+
+ _add_lru_realms:
+ /* add the default realm first */
+ defrealm = khm_krb5_get_default_realm();
+ if (defrealm) {
+ SendMessage(d->hw_realm,
+ CB_ADDSTRING,
+ 0,
+ (LPARAM) defrealm);
+ }
+
+ rv = khc_read_multi_string(csp_params,
+ L"LRURealms",
+ NULL,
+ &cb);
+
+ if (rv != KHM_ERROR_TOO_LONG)
+ goto _done_adding_lru;
+
+ if (ms != NULL) {
+ if (cb_ms < cb) {
+ free(ms);
+ ms = malloc(cb);
+ assert(ms);
+ cb_ms = cb;
+ }
+ } else {
+ ms = malloc(cb);
+ cb_ms = cb;
+ }
+
+ rv = khc_read_multi_string(csp_params,
+ L"LRURealms",
+ ms,
+ &cb);
+
+ assert(KHM_SUCCEEDED(rv));
+
+ for (t = ms; t && *t; t = multi_string_next(t)) {
+ lr = SendMessage(d->hw_realm,
+ CB_FINDSTRINGEXACT,
+ (WPARAM) -1,
+ (LPARAM) t);
+ if (lr != CB_ERR)
+ continue;
+
+ SendMessage(d->hw_realm,
+ CB_ADDSTRING,
+ 0,
+ (LPARAM) t);
+ }
+
+ _done_adding_lru:
+ /* set the current selection of the realms list */
+ if (defrealm) {
+ SendMessage(d->hw_realm,
+ CB_SELECTSTRING,
+ (WPARAM) -1,
+ (LPARAM) defrealm);
+ } else {
+ SendMessage(d->hw_realm,
+ CB_SETCURSEL,
+ (WPARAM) 0,
+ (LPARAM) 0);
+ }
+
+ if (defrealm)
+ free(defrealm);
+
+ if (ms)
+ free(ms);
+
+ /* now see about that default identity */
+ if (nc->ctx.identity) {
+ cb = sizeof(defident);
+ kcdb_identity_get_name(nc->ctx.identity,
+ defident,
+ &cb);
+ }
+
+ if (defident[0] == L'\0' &&
+ KHM_SUCCEEDED(kcdb_identity_get_default(&hident))) {
+ cb = sizeof(defident);
+ kcdb_identity_get_name(hident, defident, &cb);
+ kcdb_identity_release(hident);
+ }
+
+ if (defident[0] == L'\0') {
+ DWORD dw;
+
+ dw = ARRAYLENGTH(defident);
+ GetUserName(defident, &dw);
+ }
+
+ t = khm_get_realm_from_princ(defident);
+ if (t) {
+ /* there is a realm */
+ assert(t != defident);
+ *--t = L'\0';
+ t++;
+
+ SendMessage(d->hw_realm,
+ CB_SELECTSTRING,
+ (WPARAM) -1,
+ (LPARAM) t);
+
+ SendMessage(d->hw_realm,
+ WM_SETTEXT,
+ 0,
+ (LPARAM) t);
+ }
+
+ if (defident[0] != L'\0') {
+ /* there is a username */
+ SendMessage(d->hw_username,
+ CB_SELECTSTRING,
+ (WPARAM) -1,
+ (LPARAM) defident);
+
+ SendMessage(d->hw_username,
+ WM_SETTEXT,
+ 0,
+ (LPARAM) defident);
+ }
+
+ set_identity_from_ui(nc, d);
+ }
+ return TRUE;
+
+ case WMNC_IDENT_WMSG:
+ return handle_wnd_msg(nc, hwnd, uMsg, wParam, lParam);
+
+ case WMNC_IDENT_EXIT:
+ {
+#ifdef DEBUG
+ assert(d != NULL);
+#endif
+ khui_cw_lock_nc(nc);
+ nc->ident_aux = 0;
+ khui_cw_unlock_nc(nc);
+
+ /* since we created all the windows as child windows of
+ the new creds window, they will be destroyed when that
+ window is destroyed. */
+ free(d);
+ }
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static khm_int32
+k5_ident_valiate_name(khm_int32 msg_type,
+ khm_int32 msg_subtype,
+ khm_ui_4 uparam,
+ void * vparam) {
+ krb5_principal princ = NULL;
+ char princ_name[KCDB_IDENT_MAXCCH_NAME];
+ kcdb_ident_name_xfer * nx;
+ krb5_error_code code;
+
+ nx = (kcdb_ident_name_xfer *) vparam;
+
+ if(UnicodeStrToAnsi(princ_name, sizeof(princ_name),
+ nx->name_src) == 0) {
+ nx->result = KHM_ERROR_INVALID_NAME;
+ return KHM_ERROR_SUCCESS;
+ }
+
+ assert(k5_identpro_ctx != NULL);
+
+ code = pkrb5_parse_name(k5_identpro_ctx,
+ princ_name,
+ &princ);
+
+ if (code) {
+ nx->result = KHM_ERROR_INVALID_NAME;
+ return KHM_ERROR_SUCCESS;
+ }
+
+ if (princ != NULL)
+ pkrb5_free_principal(k5_identpro_ctx,
+ princ);
+
+ nx->result = KHM_ERROR_SUCCESS;
+
+ return KHM_ERROR_SUCCESS;
+}
+
+static khm_int32
+k5_ident_set_default(khm_int32 msg_type,
+ khm_int32 msg_subtype,
+ khm_ui_4 uparam,
+ void * vparam) {
+
+ /* Logic for setting the default identity:
+
+ When setting identity I as the default;
+
+ - If KRB5CCNAME is set
+ - If I["Krb5CCName"] == %KRB5CCNAME%
+ - do nothing
+ - Else
+ - Copy the contents of I["Krb5CCName"] to %KRB5CCNAME
+ - Set I["Krb5CCName"] to %KRB5CCNAME
+ - Else
+ - Set HKCU\Software\MIT\kerberos5,ccname to
+ "API:".I["Krb5CCName"]
+ */
+
+ if (uparam) {
+ /* an identity is being made default */
+ khm_handle def_ident = (khm_handle) vparam;
+ wchar_t env_ccname[KRB5_MAXCCH_CCNAME];
+ wchar_t id_ccname[KRB5_MAXCCH_CCNAME];
+ khm_size cb;
+ DWORD dw;
+ LONG l;
+
+#ifdef DEBUG
+ assert(def_ident != NULL);
+#endif
+
+ cb = sizeof(id_ccname);
+ if (KHM_FAILED(kcdb_identity_get_attr(def_ident,
+ attr_id_krb5_ccname,
+ NULL,
+ id_ccname,
+ &cb)))
+ return KHM_ERROR_UNKNOWN;
+
+ khm_krb5_canon_cc_name(id_ccname, sizeof(id_ccname));
+
+ StringCbLength(id_ccname, sizeof(id_ccname), &cb);
+ cb += sizeof(wchar_t);
+
+ dw = GetEnvironmentVariable(L"KRB5CCNAME",
+ env_ccname,
+ ARRAYLENGTH(env_ccname));
+
+ if (dw == 0 &&
+ GetLastError() == ERROR_ENVVAR_NOT_FOUND) {
+ /* KRB5CCNAME not set */
+ HKEY hk_ccname;
+ DWORD dwType;
+ DWORD dwSize;
+ wchar_t reg_ccname[KRB5_MAXCCH_CCNAME];
+
+ l = RegOpenKeyEx(HKEY_CURRENT_USER,
+ L"Software\\MIT\\kerberos5",
+ 0,
+ KEY_READ | KEY_WRITE,
+ &hk_ccname);
+
+ if (l != ERROR_SUCCESS)
+ l = RegCreateKeyEx(HKEY_CURRENT_USER,
+ L"Software\\MIT\\kerberos5",
+ 0,
+ NULL,
+ REG_OPTION_NON_VOLATILE,
+ KEY_READ | KEY_WRITE,
+ NULL,
+ &hk_ccname,
+ &dw);
+
+ if (l != ERROR_SUCCESS)
+ return KHM_ERROR_UNKNOWN;
+
+ dwSize = sizeof(reg_ccname);
+
+ l = RegQueryValueEx(hk_ccname,
+ L"ccname",
+ NULL,
+ &dwType,
+ (LPBYTE) reg_ccname,
+ &dwSize);
+
+ if (l != ERROR_SUCCESS ||
+ dwType != REG_SZ ||
+ khm_krb5_cc_name_cmp(reg_ccname, id_ccname)) {
+
+ /* we have to write the new value in */
+
+ l = RegSetValueEx(hk_ccname,
+ L"ccname",
+ 0,
+ REG_SZ,
+ (BYTE *) id_ccname,
+ (DWORD) cb);
+ }
+
+ RegCloseKey(hk_ccname);
+
+ if (l == ERROR_SUCCESS)
+ return KHM_ERROR_SUCCESS;
+ else
+ return KHM_ERROR_UNKNOWN;
+
+ } else if (dw > ARRAYLENGTH(env_ccname)) {
+ /* buffer was not enough */
+#ifdef DEBUG
+ assert(FALSE);
+#else
+ return KHM_ERROR_UNKNOWN;
+#endif
+ } else {
+ /* KRB5CCNAME is set */
+ long code;
+ krb5_context ctx;
+
+ /* if the %KRB5CCNAME is the same as the identity
+ ccache, then it is already the default. */
+ if (!khm_krb5_cc_name_cmp(id_ccname, env_ccname))
+ return KHM_ERROR_SUCCESS;
+
+ /* if not, we have to copy the contents of id_ccname
+ to env_ccname */
+ code = pkrb5_init_context(&ctx);
+ if (code)
+ return KHM_ERROR_UNKNOWN;
+
+ code = khm_krb5_copy_ccache_by_name(ctx,
+ env_ccname,
+ id_ccname);
+
+ if (code == 0)
+ khm_krb5_list_tickets(&ctx);
+
+ if (ctx)
+ pkrb5_free_context(ctx);
+
+ return (code == 0)?KHM_ERROR_SUCCESS:KHM_ERROR_UNKNOWN;
+ }
+ } else {
+ /* the default identity is being forgotten */
+
+ /* we don't really do anything about this case */
+ }
+
+ return KHM_ERROR_SUCCESS;
+}
+
+static khm_int32
+k5_ident_get_ui_cb(khm_int32 msg_type,
+ khm_int32 msg_subtype,
+ khm_ui_4 uparam,
+ void * vparam) {
+ khui_ident_new_creds_cb * cb;
+
+ cb = (khui_ident_new_creds_cb *) vparam;
+
+ *cb = ui_cb;
+
+ return KHM_ERROR_SUCCESS;
+}
+
+static khm_int32
+k5_ident_notify_create(khm_int32 msg_type,
+ khm_int32 msg_subtype,
+ khm_ui_4 uparam,
+ void * vparam) {
+
+ /* a new identity has been created. What we want to do at
+ this point is to check if the identity belongs to krb5
+ and to see if it is the default. */
+
+ krb5_ccache cc = NULL;
+ krb5_error_code code;
+ krb5_principal princ = NULL;
+ char * princ_nameA = NULL;
+ wchar_t princ_nameW[KCDB_IDENT_MAXCCH_NAME];
+ wchar_t id_nameW[KCDB_IDENT_MAXCCH_NAME];
+ khm_size cb;
+ khm_handle ident;
+
+ ident = (khm_handle) vparam;
+
+ assert(k5_identpro_ctx != NULL);
+
+ code = pkrb5_cc_default(k5_identpro_ctx, &cc);
+ if (code)
+ goto _nc_cleanup;
+
+ code = pkrb5_cc_get_principal(k5_identpro_ctx,
+ cc,
+ &princ);
+ if (code)
+ goto _nc_cleanup;
+
+ code = pkrb5_unparse_name(k5_identpro_ctx,
+ princ,
+ &princ_nameA);
+ if (code)
+ goto _nc_cleanup;
+
+ AnsiStrToUnicode(princ_nameW,
+ sizeof(princ_nameW),
+ princ_nameA);
+
+ cb = sizeof(id_nameW);
+
+ if (KHM_FAILED(kcdb_identity_get_name(ident,
+ id_nameW,
+ &cb)))
+ goto _nc_cleanup;
+
+ if (!wcscmp(id_nameW, princ_nameW)) {
+ kcdb_identity_set_default_int(ident);
+ }
+
+ _nc_cleanup:
+ if (princ_nameA)
+ pkrb5_free_unparsed_name(k5_identpro_ctx,
+ princ_nameA);
+ if (princ)
+ pkrb5_free_principal(k5_identpro_ctx,
+ princ);
+ if (cc)
+ pkrb5_cc_close(k5_identpro_ctx, cc);
+
+
+ return KHM_ERROR_SUCCESS;
+}
+
+static khm_int32 KHMAPI
+k5_ident_update_apply_proc(khm_handle cred,
+ void * rock) {
+ wchar_t ccname[KRB5_MAXCCH_CCNAME];
+ khm_handle tident = (khm_handle) rock;
+ khm_handle ident = NULL;
+ khm_int32 t;
+ khm_int32 flags;
+ __int64 t_expire;
+ __int64 t_rexpire;
+ khm_size cb;
+ khm_int32 rv = KHM_ERROR_SUCCESS;
+
+ if (KHM_FAILED(kcdb_cred_get_type(cred, &t)) ||
+ t != credtype_id_krb5 ||
+ KHM_FAILED(kcdb_cred_get_identity(cred, &ident)))
+ return KHM_ERROR_SUCCESS;
+
+ if (ident != tident)
+ goto _cleanup;
+
+ if (KHM_FAILED(kcdb_cred_get_flags(cred, &flags)))
+ flags = 0;
+
+ cb = sizeof(t_expire);
+ if (KHM_SUCCEEDED(kcdb_cred_get_attr(cred,
+ KCDB_ATTR_EXPIRE,
+ NULL,
+ &t_expire,
+ &cb))) {
+ __int64 t_cexpire;
+
+ cb = sizeof(t_cexpire);
+ if ((flags & KCDB_CRED_FLAG_INITIAL) ||
+ KHM_FAILED(kcdb_identity_get_attr(tident,
+ KCDB_ATTR_EXPIRE,
+ NULL,
+ &t_cexpire,
+ &cb)) ||
+ t_cexpire > t_expire)
+ kcdb_identity_set_attr(tident, KCDB_ATTR_EXPIRE,
+ &t_expire, sizeof(t_expire));
+ } else if (flags & KCDB_CRED_FLAG_INITIAL) {
+ kcdb_identity_set_attr(tident, KCDB_ATTR_EXPIRE, NULL, 0);
+ }
+
+ cb = sizeof(ccname);
+ if (KHM_SUCCEEDED(kcdb_cred_get_attr(cred, KCDB_ATTR_LOCATION,
+ NULL,
+ ccname,
+ &cb))) {
+ kcdb_identity_set_attr(tident, attr_id_krb5_ccname,
+ ccname, cb);
+ } else {
+ kcdb_identity_set_attr(tident, attr_id_krb5_ccname,
+ NULL, 0);
+ }
+
+ if (!(flags & KCDB_CRED_FLAG_INITIAL))
+ goto _cleanup;
+
+ cb = sizeof(t);
+ if (KHM_SUCCEEDED(kcdb_cred_get_attr(cred,
+ attr_id_krb5_flags,
+ NULL,
+ &t,
+ &cb))) {
+ kcdb_identity_set_attr(tident, attr_id_krb5_flags,
+ &t, sizeof(t));
+
+ cb = sizeof(t_rexpire);
+ if (!(t & TKT_FLG_RENEWABLE) ||
+ KHM_FAILED(kcdb_cred_get_attr(cred,
+ KCDB_ATTR_RENEW_EXPIRE,
+ NULL,
+ &t_rexpire,
+ &cb))) {
+ kcdb_identity_set_attr(tident, KCDB_ATTR_RENEW_EXPIRE,
+ NULL, 0);
+ } else {
+ kcdb_identity_set_attr(tident, KCDB_ATTR_RENEW_EXPIRE,
+ &t_rexpire, sizeof(t_rexpire));
+ }
+ } else {
+ kcdb_identity_set_attr(tident, attr_id_krb5_flags,
+ NULL, 0);
+ kcdb_identity_set_attr(tident, KCDB_ATTR_RENEW_EXPIRE,
+ NULL, 0);
+ }
+
+ rv = KHM_ERROR_EXIT;
+
+ _cleanup:
+ if (ident)
+ kcdb_identity_release(ident);
+
+ return rv;
+}
+
+static khm_int32
+k5_ident_update(khm_int32 msg_type,
+ khm_int32 msg_subtype,
+ khm_ui_4 uparam,
+ void * vparam) {
+
+ khm_handle ident;
+
+ ident = (khm_handle) vparam;
+ if (ident == NULL)
+ return KHM_ERROR_SUCCESS;
+
+ kcdb_credset_apply(NULL,
+ k5_ident_update_apply_proc,
+ (void *) ident);
+
+ return KHM_ERROR_SUCCESS;
+}
+
+
+static khm_int32
+k5_ident_init(khm_int32 msg_type,
+ khm_int32 msg_subtype,
+ khm_ui_4 uparam,
+ void * vparam) {
+ /* just like notify_create, except now we set the default identity
+ based on what we find in the configuration */
+ krb5_ccache cc = NULL;
+ krb5_error_code code;
+ krb5_principal princ = NULL;
+ char * princ_nameA = NULL;
+ wchar_t princ_nameW[KCDB_IDENT_MAXCCH_NAME];
+ khm_handle ident = NULL;
+
+ assert(k5_identpro_ctx != NULL);
+
+ code = pkrb5_cc_default(k5_identpro_ctx, &cc);
+ if (code)
+ goto _nc_cleanup;
+
+ code = pkrb5_cc_get_principal(k5_identpro_ctx,
+ cc,
+ &princ);
+ if (code)
+ goto _nc_cleanup;
+
+ code = pkrb5_unparse_name(k5_identpro_ctx,
+ princ,
+ &princ_nameA);
+ if (code)
+ goto _nc_cleanup;
+
+ AnsiStrToUnicode(princ_nameW,
+ sizeof(princ_nameW),
+ princ_nameA);
+
+ if (KHM_FAILED(kcdb_identity_create(princ_nameW,
+ 0,
+ &ident)))
+ goto _nc_cleanup;
+
+ kcdb_identity_set_default_int(ident);
+
+ _nc_cleanup:
+ if (princ_nameA)
+ pkrb5_free_unparsed_name(k5_identpro_ctx,
+ princ_nameA);
+ if (princ)
+ pkrb5_free_principal(k5_identpro_ctx,
+ princ);
+ if (cc)
+ pkrb5_cc_close(k5_identpro_ctx, cc);
+
+ if (ident)
+ kcdb_identity_release(ident);
+
+ return KHM_ERROR_SUCCESS;
+}
+
+static khm_int32
+k5_ident_exit(khm_int32 msg_type,
+ khm_int32 msg_subtype,
+ khm_ui_4 uparam,
+ void * vparam) {
+ /* don't really do anything */
+ return KHM_ERROR_SUCCESS;
+}
+
+#if 0
+/* copy and paste template for ident provider messages */
+static khm_int32
+k5_ident_(khm_int32 msg_type,
+ khm_int32 msg_subtype,
+ khm_ui_4 uparam,
+ void * vparam) {
+}
+#endif
+
+khm_int32 KHMAPI
+k5_msg_ident(khm_int32 msg_type,
+ khm_int32 msg_subtype,
+ khm_ui_4 uparam,
+ void * vparam)
+{
+ switch(msg_subtype) {
+ case KMSG_IDENT_INIT:
+ return k5_ident_init(msg_type,
+ msg_subtype,
+ uparam,
+ vparam);
+
+ case KMSG_IDENT_EXIT:
+ return k5_ident_exit(msg_type,
+ msg_subtype,
+ uparam,
+ vparam);
+
+ case KMSG_IDENT_VALIDATE_NAME:
+ return k5_ident_valiate_name(msg_type,
+ msg_subtype,
+ uparam,
+ vparam);
+
+ case KMSG_IDENT_VALIDATE_IDENTITY:
+ /* TODO: handle KMSG_IDENT_VALIDATE_IDENTITY */
+ break;
+
+ case KMSG_IDENT_CANON_NAME:
+ /* TODO: handle KMSG_IDENT_CANON_NAME */
+ break;
+
+ case KMSG_IDENT_COMPARE_NAME:
+ /* TODO: handle KMSG_IDENT_COMPARE_NAME */
+ break;
+
+ case KMSG_IDENT_SET_DEFAULT:
+ return k5_ident_set_default(msg_type,
+ msg_subtype,
+ uparam,
+ vparam);
+
+ case KMSG_IDENT_SET_SEARCHABLE:
+ /* TODO: handle KMSG_IDENT_SET_SEARCHABLE */
+ break;
+
+ case KMSG_IDENT_GET_INFO:
+ /* TODO: handle KMSG_IDENT_GET_INFO */
+ break;
+
+ case KMSG_IDENT_UPDATE:
+ return k5_ident_update(msg_type,
+ msg_subtype,
+ uparam,
+ vparam);
+
+ case KMSG_IDENT_ENUM_KNOWN:
+ /* TODO: handle KMSG_IDENT_ENUM_KNOWN */
+ break;
+
+ case KMSG_IDENT_GET_UI_CALLBACK:
+ return k5_ident_get_ui_cb(msg_type,
+ msg_subtype,
+ uparam,
+ vparam);
+
+ case KMSG_IDENT_NOTIFY_CREATE:
+ return k5_ident_notify_create(msg_type,
+ msg_subtype,
+ uparam,
+ vparam);
+ }
+
+ return KHM_ERROR_SUCCESS;
+}
diff --git a/src/windows/identity/plugins/krb5/krb5newcreds.c b/src/windows/identity/plugins/krb5/krb5newcreds.c
new file mode 100644
index 0000000..968e0e2
--- /dev/null
+++ b/src/windows/identity/plugins/krb5/krb5newcreds.c
@@ -0,0 +1,2167 @@
+/*
+ * Copyright (c) 2004 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#include<krbcred.h>
+#include<kherror.h>
+#include<khmsgtypes.h>
+#include<strsafe.h>
+#include<krb5.h>
+
+#include<assert.h>
+
+extern LPVOID k5_main_fiber;
+extern LPVOID k5_kinit_fiber;
+
+typedef struct k5_dlg_data_t {
+ khui_new_creds * nc;
+
+ khui_tracker tc_lifetime;
+ khui_tracker tc_renew;
+
+ BOOL dirty;
+
+ DWORD renewable;
+ DWORD forwardable;
+ DWORD proxiable;
+ DWORD addressless;
+ DWORD publicIP;
+
+ wchar_t * cred_message; /* overrides the credential text, if
+ non-NULL */
+} k5_dlg_data;
+
+
+INT_PTR
+k5_handle_wm_initdialog(HWND hwnd,
+ WPARAM wParam,
+ LPARAM lParam)
+{
+ HWND hw;
+ k5_dlg_data * d;
+ khui_new_creds_by_type * nct;
+
+ d = malloc(sizeof(*d));
+ ZeroMemory(d, sizeof(*d));
+ /* lParam is a pointer to a khui_new_creds structure */
+ d->nc = (khui_new_creds *) lParam;
+ khui_cw_find_type(d->nc, credtype_id_krb5, &nct);
+
+#pragma warning(push)
+#pragma warning(disable: 4244)
+ SetWindowLongPtr(hwnd, DWLP_USER, (LPARAM) d);
+#pragma warning(pop)
+
+ nct->aux = (LPARAM) d;
+
+ if (d->nc->subtype == KMSG_CRED_NEW_CREDS) {
+ khui_tracker_initialize(&d->tc_lifetime);
+ khui_tracker_initialize(&d->tc_renew);
+
+ hw = GetDlgItem(hwnd, IDC_NCK5_LIFETIME_EDIT);
+ khui_tracker_install(hw, &d->tc_lifetime);
+
+ hw = GetDlgItem(hwnd, IDC_NCK5_RENEW_EDIT);
+ khui_tracker_install(hw, &d->tc_renew);
+ }
+ return TRUE;
+}
+
+INT_PTR
+k5_handle_wm_destroy(HWND hwnd,
+ WPARAM wParam,
+ LPARAM lParam)
+{
+ k5_dlg_data * d;
+ khui_new_creds_by_type * nct = NULL;
+
+ d = (k5_dlg_data *) (LONG_PTR)
+ GetWindowLongPtr(hwnd, DWLP_USER);
+#ifdef DEBUG
+ assert(d);
+#endif
+
+ khui_cw_find_type(d->nc, credtype_id_krb5, &nct);
+
+#ifdef DEBUG
+ assert(nct);
+#endif
+
+ nct->aux = 0;
+
+ if (d->nc->subtype == KMSG_CRED_NEW_CREDS) {
+ khui_tracker_kill_controls(&d->tc_renew);
+ khui_tracker_kill_controls(&d->tc_lifetime);
+ }
+
+ free(d);
+
+ return TRUE;
+}
+
+INT_PTR
+k5_handle_wmnc_notify(HWND hwnd,
+ WPARAM wParam,
+ LPARAM lParam)
+{
+ switch(HIWORD(wParam)) {
+ case WMNC_DIALOG_MOVE:
+ {
+ k5_dlg_data * d;
+
+ d = (k5_dlg_data *)(LONG_PTR)
+ GetWindowLongPtr(hwnd, DWLP_USER);
+
+ if (d->nc->subtype == KMSG_CRED_NEW_CREDS) {
+ khui_tracker_reposition(&d->tc_lifetime);
+ khui_tracker_reposition(&d->tc_renew);
+ }
+
+ return TRUE;
+ }
+ break;
+
+ case WMNC_DIALOG_SETUP:
+ {
+ k5_dlg_data * d;
+
+ d = (k5_dlg_data *)(LONG_PTR)
+ GetWindowLongPtr(hwnd, DWLP_USER);
+
+ if (d->nc->subtype == KMSG_CRED_PASSWORD)
+ return TRUE;
+
+ /* need to update the controls with d->* */
+ if(d->renewable) {
+ SendDlgItemMessage(hwnd, IDC_NCK5_RENEWABLE,
+ BM_SETCHECK, BST_CHECKED,
+ 0);
+ EnableWindow(GetDlgItem(hwnd, IDC_NCK5_RENEW_EDIT),
+ TRUE);
+ } else {
+ SendDlgItemMessage(hwnd, IDC_NCK5_RENEWABLE,
+ BM_SETCHECK, BST_UNCHECKED, 0);
+ EnableWindow(GetDlgItem(hwnd, IDC_NCK5_RENEW_EDIT),
+ FALSE);
+ }
+
+ khui_tracker_refresh(&d->tc_lifetime);
+ khui_tracker_refresh(&d->tc_renew);
+
+ if(d->forwardable) {
+ SendDlgItemMessage(hwnd, IDC_NCK5_FORWARDABLE,
+ BM_SETCHECK, BST_CHECKED, 0);
+ } else {
+ SendDlgItemMessage(hwnd, IDC_NCK5_FORWARDABLE,
+ BM_SETCHECK, BST_UNCHECKED, 0);
+ }
+ }
+ break;
+
+ case WMNC_UPDATE_CREDTEXT:
+ {
+ k5_dlg_data * d;
+ khui_new_creds * nc;
+ khui_new_creds_by_type * nct;
+ wchar_t sbuf[1024];
+ wchar_t fbuf[256];
+ wchar_t tbuf[256];
+ size_t cbsize;
+ khm_int32 flags;
+
+ d = (k5_dlg_data *)(LONG_PTR)
+ GetWindowLongPtr(hwnd, DWLP_USER);
+ nc = d->nc;
+ khui_cw_find_type(nc, credtype_id_krb5, &nct);
+
+ if(nct == NULL)
+ break;
+
+ if(nct->credtext)
+ free(nct->credtext);
+ nct->credtext = NULL;
+
+ tbuf[0] = L'\0';
+
+ if (nc->n_identities > 0 &&
+ KHM_SUCCEEDED(kcdb_identity_get_flags(nc->identities[0],
+ &flags)) &&
+ (flags & KCDB_IDENT_FLAG_VALID) &&
+ nc->subtype == KMSG_CRED_NEW_CREDS) {
+
+ if (is_k5_identpro)
+ k5_get_realm_from_nc(nc, tbuf, ARRAYLENGTH(tbuf));
+ else
+ GetDlgItemText(hwnd, IDC_NCK5_REALM, tbuf,
+ ARRAYLENGTH(tbuf));
+
+ /*TODO: if additional realms were specified, then those
+ must be listed as well */
+ LoadString(hResModule, IDS_KRB5_CREDTEXT_0,
+ fbuf, ARRAYLENGTH(fbuf));
+ StringCbPrintf(sbuf, sizeof(sbuf), fbuf,
+ tbuf);
+
+ StringCbLength(sbuf, sizeof(sbuf), &cbsize);
+ cbsize += sizeof(wchar_t);
+
+ nct->credtext = malloc(cbsize);
+
+ StringCbCopy(nct->credtext, cbsize, sbuf);
+ } else if (nc->n_identities > 0 &&
+ nc->subtype == KMSG_CRED_PASSWORD) {
+ cbsize = sizeof(tbuf);
+ kcdb_identity_get_name(nc->identities[0], tbuf, &cbsize);
+
+ LoadString(hResModule, IDS_KRB5_CREDTEXT_P0,
+ fbuf, ARRAYLENGTH(fbuf));
+ StringCbPrintf(sbuf, sizeof(sbuf), fbuf, tbuf);
+
+ StringCbLength(sbuf, sizeof(sbuf), &cbsize);
+ cbsize += sizeof(wchar_t);
+
+ nct->credtext = malloc(cbsize);
+
+ StringCbCopy(nct->credtext, cbsize, sbuf);
+ } else {
+ if (d->cred_message) {
+ StringCbLength(d->cred_message, KHUI_MAXCB_BANNER,
+ &cbsize);
+ cbsize += sizeof(wchar_t);
+
+ nct->credtext = malloc(cbsize);
+
+ StringCbCopy(nct->credtext, cbsize, d->cred_message);
+ }
+ }
+ }
+ break;
+
+ case WMNC_IDENTITY_CHANGE:
+ {
+ /* There has been a change of identity */
+ k5_dlg_data * d;
+
+ d = (k5_dlg_data *)(LONG_PTR)
+ GetWindowLongPtr(hwnd, DWLP_USER);
+
+ kmq_post_sub_msg(k5_sub, KMSG_CRED,
+ KMSG_CRED_DIALOG_NEW_IDENTITY,
+ 0, (void *) d->nc);
+ }
+ break;
+
+ case WMNC_DIALOG_PREPROCESS:
+ {
+ k5_dlg_data * d;
+
+ d = (k5_dlg_data *)(LONG_PTR)
+ GetWindowLongPtr(hwnd, DWLP_USER);
+
+ if(d->dirty) {
+ kmq_post_sub_msg(k5_sub, KMSG_CRED,
+ KMSG_CRED_DIALOG_NEW_OPTIONS,
+ 0, (void *) d->nc);
+
+ /* the above notification effectively takes
+ all our changes into account. The data we
+ have is no longer dirty */
+ d->dirty = FALSE;
+ }
+ }
+ break;
+ }
+
+ return 0;
+}
+
+INT_PTR
+k5_handle_wm_command(HWND hwnd,
+ WPARAM wParam,
+ LPARAM lParam)
+{
+ int cid;
+ int notif;
+ k5_dlg_data * d;
+
+ d = (k5_dlg_data *)(LONG_PTR) GetWindowLongPtr(hwnd, DWLP_USER);
+
+ cid = LOWORD(wParam);
+ notif = HIWORD(wParam);
+
+ if(notif == BN_CLICKED && cid == IDC_NCK5_RENEWABLE) {
+ int c;
+ c = (int) SendDlgItemMessage(hwnd, IDC_NCK5_RENEWABLE,
+ BM_GETCHECK, 0, 0);
+ if(c==BST_CHECKED) {
+ EnableWindow(GetDlgItem(hwnd, IDC_NCK5_RENEW_EDIT), TRUE);
+ d->renewable = TRUE;
+ } else {
+ EnableWindow(GetDlgItem(hwnd, IDC_NCK5_RENEW_EDIT), FALSE);
+ d->renewable = FALSE;
+ }
+ d->dirty = TRUE;
+ } else if(notif == BN_CLICKED && cid == IDC_NCK5_FORWARDABLE) {
+ int c;
+ c = (int) SendDlgItemMessage(hwnd, IDC_NCK5_RENEWABLE,
+ BM_GETCHECK, 0, 0);
+ if(c==BST_CHECKED) {
+ d->forwardable = TRUE;
+ } else {
+ d->forwardable = FALSE;
+ }
+ d->dirty = TRUE;
+ } else if((notif == CBN_SELCHANGE ||
+ notif == CBN_KILLFOCUS) &&
+ cid == IDC_NCK5_REALM &&
+ !is_k5_identpro) {
+ /* find out what the realm of the current identity
+ is, and if they are the same, then we don't do
+ anything */
+ wchar_t idname[KCDB_IDENT_MAXCCH_NAME];
+ wchar_t realm[KCDB_IDENT_MAXCCH_NAME];
+ wchar_t *r;
+ khm_size cbsize;
+ khm_handle ident;
+ int idx;
+
+ if(d->nc->n_identities > 0) {
+ if(notif == CBN_SELCHANGE) {
+ idx = (int) SendDlgItemMessage(hwnd, IDC_NCK5_REALM,
+ CB_GETCURSEL, 0, 0);
+ SendDlgItemMessage(hwnd, IDC_NCK5_REALM,
+ CB_GETLBTEXT, idx, (LPARAM) realm);
+ } else {
+ GetDlgItemText(hwnd, IDC_NCK5_REALM,
+ realm, ARRAYLENGTH(realm));
+ }
+ cbsize = sizeof(idname);
+ if(KHM_SUCCEEDED(kcdb_identity_get_name(d->nc->identities[0],
+ idname, &cbsize))) {
+ r = wcschr(idname, L'@');
+ if(r && !wcscmp(realm, r+1))
+ return 0; /* nothing to do */
+
+ if(!r) {
+ r = idname + wcslen(idname);
+ *r++ = L'@';
+ *r++ = 0;
+ }
+
+ /* if we get here, we have a new user */
+ StringCchCopy(r+1,
+ ARRAYLENGTH(idname) - ((r+1) - idname),
+ realm);
+ if(KHM_SUCCEEDED(kcdb_identity_create(idname,
+ KCDB_IDENT_FLAG_CREATE,
+ &ident))) {
+ khui_cw_set_primary_id(d->nc, ident);
+ kcdb_identity_release(ident);
+ }
+ return 0;
+ }
+ }
+
+ /* if we get here, we have a new realm, but there is no
+ identity */
+ PostMessage(d->nc->hwnd, KHUI_WM_NC_NOTIFY,
+ MAKEWPARAM(0, WMNC_UPDATE_CREDTEXT), 0);
+ }
+
+ return 0;
+}
+
+
+/* Dialog procedure for the Krb5 credentials type panel.
+
+ NOTE: Runs in the context of the UI thread
+*/
+INT_PTR CALLBACK
+k5_nc_dlg_proc(HWND hwnd,
+ UINT uMsg,
+ WPARAM wParam,
+ LPARAM lParam)
+{
+ switch(uMsg) {
+ case WM_INITDIALOG:
+ return k5_handle_wm_initdialog(hwnd, wParam, lParam);
+
+ case WM_COMMAND:
+ return k5_handle_wm_command(hwnd, wParam, lParam);
+
+ case KHUI_WM_NC_NOTIFY:
+ return k5_handle_wmnc_notify(hwnd, wParam, lParam);
+
+ case WM_DESTROY:
+ return k5_handle_wm_destroy(hwnd, wParam, lParam);
+ }
+ return FALSE;
+}
+
+/* forward dcl */
+krb5_error_code KRB5_CALLCONV
+k5_kinit_prompter(krb5_context context,
+ void *data,
+ const char *name,
+ const char *banner,
+ int num_prompts,
+ krb5_prompt prompts[]);
+
+
+
+fiber_job g_fjob; /* global fiber job object */
+
+static BOOL
+k5_cached_kinit_prompter(void);
+
+static BOOL
+k5_cp_check_continue(void);
+
+/*
+ Runs in the context of the krb5 plugin's slave fiber
+*/
+VOID CALLBACK
+k5_kinit_fiber_proc(PVOID lpParameter)
+{
+ while(TRUE)
+ {
+ if(g_fjob.command == FIBER_CMD_KINIT) {
+ g_fjob.state = FIBER_STATE_KINIT;
+
+ g_fjob.prompt_set = 0;
+
+ if (k5_cached_kinit_prompter()) {
+ SwitchToFiber(k5_main_fiber);
+
+ if (g_fjob.command != FIBER_CMD_CONTINUE)
+ goto _switch_to_main;
+
+ if (!k5_cp_check_continue()) {
+ goto _switch_to_main;
+ }
+ }
+
+ g_fjob.code = khm_krb5_kinit(
+ 0,
+ g_fjob.principal,
+ g_fjob.password,
+ g_fjob.ccache,
+ g_fjob.lifetime,
+ g_fjob.forwardable,
+ g_fjob.proxiable,
+ (g_fjob.renewable ? g_fjob.renew_life : 0),
+ g_fjob.addressless,
+ g_fjob.publicIP,
+ k5_kinit_prompter,
+ &g_fjob);
+ }
+
+ _switch_to_main:
+ g_fjob.state = FIBER_STATE_NONE;
+
+ SwitchToFiber(k5_main_fiber);
+ }
+}
+
+/* return TRUE if we should go ahead with creds acquisition */
+static BOOL
+k5_cp_check_continue(void) {
+ khm_size i;
+ khm_size n_p;
+ khui_new_creds_prompt * p;
+ size_t cch;
+
+#ifdef DEBUG
+ assert(g_fjob.nc);
+#endif
+
+ if (KHM_FAILED(khui_cw_get_prompt_count(g_fjob.nc, &n_p))) {
+#ifdef DEBUG
+ assert(FALSE);
+#endif
+ return TRUE;
+ }
+
+ khui_cw_sync_prompt_values(g_fjob.nc);
+
+ g_fjob.null_password = FALSE;
+
+ /* we are just checking whether there was a password field that
+ was left empty, in which case we can't continue with the
+ credentials acquisition. */
+ for (i=0; i < n_p; i++) {
+ if(KHM_FAILED(khui_cw_get_prompt(g_fjob.nc,
+ (int) i,
+ &p)))
+ continue;
+ if(p->type == KHUI_NCPROMPT_TYPE_PASSWORD) {
+ if (p->value == NULL ||
+ FAILED(StringCchLength(p->value, KHUI_MAXCCH_PROMPT,
+ &cch)) ||
+ cch == 0) {
+ g_fjob.null_password = TRUE;
+ return FALSE;
+ } else
+ break;
+ }
+ }
+
+ return TRUE;
+}
+
+/* returns true if we find cached prompts */
+static BOOL
+k5_cached_kinit_prompter(void) {
+ BOOL rv = FALSE;
+ khm_handle ident;
+ khm_handle csp_idconfig = NULL;
+ khm_handle csp_k5config = NULL;
+ khm_handle csp_prcache = NULL;
+ khm_size cb;
+ khm_size n_cur_prompts;
+ khm_int32 n_prompts;
+ khm_int32 i;
+
+#ifdef DEBUG
+ assert(g_fjob.nc);
+#endif
+
+ ident = g_fjob.identity;
+ if (!ident)
+ return FALSE;
+
+ /* don't need to hold ident, since it is already held in g_fjob
+ and it doesn't change until we return */
+
+ if (KHM_FAILED(kcdb_identity_get_config(ident, 0, &csp_idconfig)) ||
+
+ KHM_FAILED(khc_open_space(csp_idconfig, CSNAME_KRB5CRED,
+ 0, &csp_k5config)) ||
+
+ KHM_FAILED(khc_open_space(csp_k5config, CSNAME_PROMPTCACHE,
+ 0, &csp_prcache)) ||
+
+ KHM_FAILED(khc_read_int32(csp_prcache, L"PromptCount",
+ &n_prompts)) ||
+ n_prompts == 0)
+
+ goto _cleanup;
+
+ /* check if there are any prompts currently showing. If there are
+ we check if they are the same as the ones we are going to show.
+ In which case we just reuse the exisitng prompts */
+ if (KHM_FAILED(khui_cw_get_prompt_count(g_fjob.nc,
+ &n_cur_prompts)) ||
+ n_prompts != (khm_int32) n_cur_prompts)
+ goto _show_new_prompts;
+
+ for(i = 0; i < n_prompts; i++) {
+ wchar_t wsname[8];
+ wchar_t wprompt[KHUI_MAXCCH_PROMPT];
+ khm_handle csp_p = NULL;
+ khm_int32 p_type;
+ khm_int32 p_flags;
+ khui_new_creds_prompt * p;
+
+ if (KHM_FAILED(khui_cw_get_prompt(g_fjob.nc, i, &p)))
+ break;
+
+ StringCbPrintf(wsname, sizeof(wsname), L"%d", i);
+
+ if (KHM_FAILED(khc_open_space(csp_prcache, wsname, 0, &csp_p)))
+ break;
+
+ cb = sizeof(wprompt);
+ if (KHM_FAILED(khc_read_string(csp_p, L"Prompt",
+ wprompt, &cb))) {
+ khc_close_space(csp_p);
+ break;
+ }
+
+ if (KHM_FAILED(khc_read_int32(csp_p, L"Type", &p_type)))
+ p_type = 0;
+
+ if (KHM_FAILED(khc_read_int32(csp_p, L"Flags", &p_flags)))
+ p_flags = 0;
+
+ if ( /* if we received a prompt string,
+ then it should be the same as the
+ one that is displayed */
+ (wprompt[0] &&
+ (p->prompt == NULL ||
+ wcscmp(wprompt, p->prompt))) ||
+
+ /* if we didn't receive one, then
+ there shouldn't be one displayed.
+ This case really shouldn't happen
+ in reality, but we check anyway. */
+ (!wprompt[0] &&
+ p->prompt != NULL) ||
+
+ /* the type should match */
+ (p_type != p->type) ||
+
+ /* if this prompt should be hidden,
+ then it must also be so */
+ (p_flags != p->flags)
+ ) {
+
+ khc_close_space(csp_p);
+ break;
+
+ }
+
+
+ khc_close_space(csp_p);
+ }
+
+ if (i == n_prompts) {
+ rv = TRUE;
+ goto _cleanup;
+ }
+
+ _show_new_prompts:
+
+ khui_cw_clear_prompts(g_fjob.nc);
+
+ {
+ wchar_t wbanner[KHUI_MAXCCH_BANNER];
+ wchar_t wpname[KHUI_MAXCCH_PNAME];
+
+ cb = sizeof(wbanner);
+ if (KHM_FAILED(khc_read_string(csp_prcache, L"Banner",
+ wbanner, &cb)))
+ wbanner[0] = 0;
+
+ cb = sizeof(wpname);
+ if (KHM_FAILED(khc_read_string(csp_prcache, L"Name",
+ wpname, &cb)))
+ wpname[0] = 0;
+
+ khui_cw_begin_custom_prompts(g_fjob.nc,
+ n_prompts,
+ (wbanner[0]? wbanner: NULL),
+ (wpname[0]? wpname: NULL));
+ }
+
+ for(i = 0; i < n_prompts; i++) {
+ wchar_t wsname[8];
+ wchar_t wprompt[KHUI_MAXCCH_PROMPT];
+ khm_handle csp_p = NULL;
+ khm_int32 p_type;
+ khm_int32 p_flags;
+
+ StringCbPrintf(wsname, sizeof(wsname), L"%d", i);
+
+ if (KHM_FAILED(khc_open_space(csp_prcache, wsname, 0, &csp_p)))
+ break;
+
+ cb = sizeof(wprompt);
+ if (KHM_FAILED(khc_read_string(csp_p, L"Prompt",
+ wprompt, &cb))) {
+ khc_close_space(csp_p);
+ break;
+ }
+
+ if (KHM_FAILED(khc_read_int32(csp_p, L"Type", &p_type)))
+ p_type = 0;
+
+ if (KHM_FAILED(khc_read_int32(csp_p, L"Flags", &p_flags)))
+ p_flags = 0;
+
+ khui_cw_add_prompt(g_fjob.nc, p_type, wprompt, NULL, p_flags);
+
+ khc_close_space(csp_p);
+ }
+
+ if (i < n_prompts) {
+ khui_cw_clear_prompts(g_fjob.nc);
+ } else {
+ rv = TRUE;
+ }
+
+ _cleanup:
+
+ if (csp_prcache)
+ khc_close_space(csp_prcache);
+
+ if (csp_k5config)
+ khc_close_space(csp_k5config);
+
+ if (csp_idconfig)
+ khc_close_space(csp_idconfig);
+
+ return rv;
+}
+
+/* Runs in the context of the Krb5 plugin's slave fiber */
+krb5_error_code KRB5_CALLCONV
+k5_kinit_prompter(krb5_context context,
+ void *data,
+ const char *name,
+ const char *banner,
+ int num_prompts,
+ krb5_prompt prompts[])
+{
+ int i;
+ khui_new_creds * nc;
+ krb5_prompt_type * ptypes;
+ khm_size ncp;
+ krb5_error_code code = 0;
+ BOOL new_prompts = TRUE;
+
+ khm_handle csp_prcache = NULL;
+
+ nc = g_fjob.nc;
+
+ if(pkrb5_get_prompt_types)
+ ptypes = pkrb5_get_prompt_types(context);
+ else
+ ptypes = NULL;
+
+ /* check if we are already showing the right prompts */
+ khui_cw_get_prompt_count(nc, &ncp);
+
+ if (num_prompts != (int) ncp)
+ goto _show_new_prompts;
+
+ for (i=0; i < num_prompts; i++) {
+ wchar_t wprompt[KHUI_MAXCCH_PROMPT];
+ khui_new_creds_prompt * p;
+
+ if(prompts[i].prompt) {
+ AnsiStrToUnicode(wprompt, sizeof(wprompt),
+ prompts[i].prompt);
+ } else {
+ wprompt[0] = 0;
+ }
+
+ if (KHM_FAILED(khui_cw_get_prompt(nc, i, &p)))
+ break;
+
+ if ( /* if we received a prompt string,
+ then it should be the same as the
+ one that is displayed */
+ (wprompt[0] &&
+ (p->prompt == NULL ||
+ wcscmp(wprompt, p->prompt))) ||
+ /* if we didn't receive one, then
+ there shouldn't be one displayed.
+ This case really shouldn't happen
+ in reality, but we check anyway. */
+ (!wprompt[0] &&
+ p->prompt != NULL) ||
+ /* the type should match */
+ (ptypes &&
+ ptypes[i] != p->type) ||
+ (!ptypes &&
+ p->type != 0) ||
+ /* if this prompt should be hidden,
+ then it must also be so */
+ (prompts[i].hidden &&
+ !(p->flags & KHUI_NCPROMPT_FLAG_HIDDEN)) ||
+ (!prompts[i].hidden &&
+ (p->flags & KHUI_NCPROMPT_FLAG_HIDDEN))
+ )
+ break;
+ }
+
+ if (i < num_prompts)
+ goto _show_new_prompts;
+
+ new_prompts = FALSE;
+
+ /* ok. looks like we are already showing the same set of prompts
+ that we were supposed to show. Sync up the values and go
+ ahead. */
+ khui_cw_sync_prompt_values(nc);
+ goto _process_prompts;
+
+ _show_new_prompts:
+ /* special case. if there are no actual input controls involved,
+ then we have to show an alerter window and pass through */
+ if (num_prompts == 0) {
+ wchar_t wbanner[KHUI_MAXCCH_BANNER];
+ wchar_t wname[KHUI_MAXCCH_PNAME];
+ wchar_t wident[KCDB_IDENT_MAXCCH_NAME];
+ wchar_t wmsg[KHUI_MAXCCH_MESSAGE];
+ wchar_t wfmt[KHUI_MAXCCH_BANNER];
+ khm_size cb;
+
+ if (!banner) {
+ code = 0;
+ g_fjob.null_password = FALSE;
+ goto _exit;
+ } else {
+ AnsiStrToUnicode(wbanner, sizeof(wbanner), banner);
+ }
+
+ if (name) {
+ AnsiStrToUnicode(wname, sizeof(wname), name);
+ } else {
+ LoadString(hResModule,
+ IDS_KRB5_WARNING,
+ wname,
+ ARRAYLENGTH(wname));
+ }
+
+ cb = sizeof(wident);
+ if (KHM_FAILED(kcdb_identity_get_name(g_fjob.identity, wident, &cb)))
+ wident[0] = L'\0';
+
+ LoadString(hResModule,
+ IDS_KRB5_WARN_FMT,
+ wfmt,
+ ARRAYLENGTH(wfmt));
+
+ StringCbPrintf(wmsg, sizeof(wmsg), wfmt, wident, wbanner);
+
+ khui_alert_show_simple(wname, wmsg, KHERR_WARNING);
+
+ code = 0;
+ g_fjob.null_password = FALSE;
+ goto _exit;
+ }
+
+ /* in addition to showing new prompts, we also cache the set of
+ prompts. */
+ if(g_fjob.prompt_set == 0) {
+ khm_handle csp_idconfig = NULL;
+ khm_handle csp_idk5 = NULL;
+
+ kcdb_identity_get_config(g_fjob.identity,
+ KHM_FLAG_CREATE,
+ &csp_idconfig);
+
+ if (csp_idconfig != NULL)
+ khc_open_space(csp_idconfig,
+ CSNAME_KRB5CRED,
+ KHM_FLAG_CREATE,
+ &csp_idk5);
+
+ if (csp_idk5 != NULL)
+ khc_open_space(csp_idk5,
+ CSNAME_PROMPTCACHE,
+ KHM_FLAG_CREATE,
+ &csp_prcache);
+
+ khc_close_space(csp_idconfig);
+ khc_close_space(csp_idk5);
+ }
+
+ {
+ wchar_t wbanner[KHUI_MAXCCH_BANNER];
+ wchar_t wname[KHUI_MAXCCH_PNAME];
+
+ if(banner)
+ AnsiStrToUnicode(wbanner, sizeof(wbanner), banner);
+ if(name)
+ AnsiStrToUnicode(wname, sizeof(wname), name);
+
+ khui_cw_clear_prompts(nc);
+
+ khui_cw_begin_custom_prompts(
+ nc,
+ num_prompts,
+ (banner)?wbanner:NULL,
+ (name)?wname:NULL);
+
+ if (banner && csp_prcache)
+ khc_write_string(csp_prcache,
+ L"Banner",
+ wbanner);
+ else if (csp_prcache)
+ khc_write_string(csp_prcache,
+ L"Banner",
+ L"");
+
+ if (name && csp_prcache)
+ khc_write_string(csp_prcache,
+ L"Name",
+ wname);
+ else if (csp_prcache)
+ khc_write_string(csp_prcache,
+ L"Name",
+ L"");
+
+ if (csp_prcache)
+ khc_write_int32(csp_prcache,
+ L"PromptCount",
+ (khm_int32) num_prompts);
+ }
+
+ for(i=0; i < num_prompts; i++) {
+ wchar_t wprompt[KHUI_MAXCCH_PROMPT];
+
+ if(prompts[i].prompt) {
+ AnsiStrToUnicode(wprompt, sizeof(wprompt),
+ prompts[i].prompt);
+ } else {
+ wprompt[0] = 0;
+ }
+
+ khui_cw_add_prompt(
+ nc,
+ (ptypes?ptypes[i]:0),
+ wprompt,
+ NULL,
+ (prompts[i].hidden?KHUI_NCPROMPT_FLAG_HIDDEN:0));
+
+ if (csp_prcache) {
+ khm_handle csp_p = NULL;
+ wchar_t wnum[8]; /* should be enough for 10
+ million prompts */
+
+ wnum[0] = 0;
+ StringCbPrintf(wnum, sizeof(wnum), L"%d", i);
+
+ khc_open_space(csp_prcache, wnum,
+ KHM_FLAG_CREATE, &csp_p);
+
+ if (csp_p) {
+ khc_write_string(csp_p, L"Prompt", wprompt);
+ khc_write_int32(csp_p, L"Type", (ptypes?ptypes[i]:0));
+ khc_write_int32(csp_p, L"Flags",
+ (prompts[i].hidden?
+ KHUI_NCPROMPT_FLAG_HIDDEN:0));
+
+ khc_close_space(csp_p);
+ }
+ }
+ }
+
+ if (csp_prcache) {
+ khc_close_space(csp_prcache);
+ csp_prcache = NULL;
+ }
+
+ _process_prompts:
+ /* switch back to main thread if we showed new prompts */
+ if (new_prompts)
+ SwitchToFiber(k5_main_fiber);
+
+ /* we get here after the user selects an action that either
+ cancles the credentials acquisition operation or triggers the
+ actual acquisition of credentials. */
+ if(g_fjob.command != FIBER_CMD_CONTINUE &&
+ g_fjob.command != FIBER_CMD_KINIT) {
+ code = -2;
+ goto _exit;
+ }
+
+ g_fjob.null_password = FALSE;
+
+ /* otherwise, we need to get the data back from the UI and
+ return 0 */
+ for(i=0; i<num_prompts; i++) {
+ krb5_data * d;
+ wchar_t wbuf[512];
+ khm_size cbbuf;
+ size_t cch;
+
+ d = prompts[i].reply;
+
+ cbbuf = sizeof(wbuf);
+ if(KHM_SUCCEEDED(khui_cw_get_prompt_value(nc, i, wbuf, &cbbuf))) {
+ UnicodeStrToAnsi(d->data, d->length, wbuf);
+ if(SUCCEEDED(StringCchLengthA(d->data, d->length, &cch)))
+ d->length = (unsigned int) cch;
+ else
+ d->length = 0;
+ } else {
+#ifdef DEBUG
+ assert(FALSE);
+#endif
+ d->length = 0;
+ }
+
+ if (ptypes &&
+ ptypes[i] == KRB5_PROMPT_TYPE_PASSWORD &&
+ d->length == 0)
+
+ g_fjob.null_password = TRUE;
+ }
+
+ _exit:
+
+ g_fjob.prompt_set++;
+
+ /* entering a NULL password is equivalent to cancelling out */
+ if (g_fjob.null_password)
+ return -2;
+ else
+ return code;
+}
+
+
+void
+k5_read_dlg_params(khm_handle conf,
+ k5_dlg_data * d)
+{
+ khm_int32 i;
+
+ khc_read_int32(conf, L"Renewable", &d->renewable);
+ khc_read_int32(conf, L"Forwardable", &d->forwardable);
+ khc_read_int32(conf, L"Proxiable", &d->proxiable);
+ khc_read_int32(conf, L"Addressless", &d->addressless);
+
+ khc_read_int32(conf, L"DefaultLifetime", &i);
+ d->tc_lifetime.current = i;
+ khc_read_int32(conf, L"MaxLifetime", &i);
+ d->tc_lifetime.max = i;
+ khc_read_int32(conf, L"MinLifetime", &i);
+ d->tc_lifetime.min = i;
+
+ khc_read_int32(conf, L"DefaultRenewLifetime", &i);
+ d->tc_renew.current = i;
+ khc_read_int32(conf, L"MaxRenewLifetime", &i);
+ d->tc_renew.max = i;
+ khc_read_int32(conf, L"MinRenewLifetime", &i);
+ d->tc_renew.min = i;
+
+ /* however, if this has externally supplied defaults, we have to
+ use them too. */
+ if (d->nc && d->nc->ctx.vparam &&
+ d->nc->ctx.cb_vparam == sizeof(NETID_DLGINFO)) {
+ LPNETID_DLGINFO pdlginfo;
+
+ pdlginfo = (LPNETID_DLGINFO) d->nc->ctx.vparam;
+ if (pdlginfo->size == NETID_DLGINFO_V1_SZ &&
+ pdlginfo->in.use_defaults == 0) {
+ d->forwardable = pdlginfo->in.forwardable;
+ d->addressless = pdlginfo->in.noaddresses;
+ d->tc_lifetime.current = pdlginfo->in.lifetime;
+ d->tc_renew.current = pdlginfo->in.renew_till;
+
+ if (pdlginfo->in.renew_till == 0)
+ d->renewable = FALSE;
+ else
+ d->renewable = TRUE;
+
+ d->proxiable = pdlginfo->in.proxiable;
+ d->publicIP = pdlginfo->in.publicip;
+ }
+ }
+
+ /* once we read the new data, in, it is no longer considered
+ dirty */
+ d->dirty = FALSE;
+}
+
+void
+k5_write_dlg_params(khm_handle conf,
+ k5_dlg_data * d)
+{
+ khc_write_int32(conf, L"Renewable", d->renewable);
+ khc_write_int32(conf, L"Forwardable", d->forwardable);
+ khc_write_int32(conf, L"Proxiable", d->proxiable);
+ khc_write_int32(conf, L"Addressless", d->addressless);
+
+ khc_write_int32(conf, L"DefaultLifetime",
+ (khm_int32) d->tc_lifetime.current);
+ khc_write_int32(conf, L"MaxLifetime",
+ (khm_int32) d->tc_lifetime.max);
+ khc_write_int32(conf, L"MinLifetime",
+ (khm_int32) d->tc_lifetime.min);
+
+ khc_write_int32(conf, L"DefaultRenewLifetime",
+ (khm_int32) d->tc_renew.current);
+ khc_write_int32(conf, L"MaxRenewLifetime",
+ (khm_int32) d->tc_renew.max);
+ khc_write_int32(conf, L"MinRenewLifetime",
+ (khm_int32) d->tc_renew.min);
+
+ /* as in k5_read_dlg_params, once we write the data in, the local
+ data is no longer dirty */
+ d->dirty = FALSE;
+}
+
+void
+k5_prep_kinit_job(khui_new_creds * nc)
+{
+ khui_new_creds_by_type * nct;
+ k5_dlg_data * d;
+ wchar_t idname[KCDB_IDENT_MAXCCH_NAME];
+ khm_size cbbuf;
+ size_t size;
+ khm_handle ident;
+ LPNETID_DLGINFO pdlginfo;
+
+ khui_cw_find_type(nc, credtype_id_krb5, &nct);
+ if (!nct)
+ return;
+
+ d = (k5_dlg_data *)(LONG_PTR)
+ GetWindowLongPtr(nct->hwnd_panel, DWLP_USER);
+
+ khui_cw_lock_nc(nc);
+ ident = nc->identities[0];
+ kcdb_identity_hold(ident);
+ khui_cw_unlock_nc(nc);
+
+ cbbuf = sizeof(idname);
+ kcdb_identity_get_name(ident, idname, &cbbuf);
+ StringCchLength(idname, ARRAYLENGTH(idname), &size);
+ size++;
+
+ ZeroMemory(&g_fjob, sizeof(g_fjob));
+ g_fjob.command = FIBER_CMD_KINIT;
+ g_fjob.nc = nc;
+ g_fjob.nct = nct;
+ g_fjob.dialog = nct->hwnd_panel;
+ g_fjob.principal = malloc(size);
+ UnicodeStrToAnsi(g_fjob.principal, size, idname);
+ g_fjob.password = NULL;
+ g_fjob.lifetime = (krb5_deltat) d->tc_lifetime.current;
+ g_fjob.forwardable = d->forwardable;
+ g_fjob.proxiable = d->proxiable;
+ g_fjob.renewable = d->renewable;
+ g_fjob.renew_life = (krb5_deltat) d->tc_renew.current;
+ g_fjob.addressless = d->addressless;
+ g_fjob.publicIP = 0;
+ g_fjob.code = 0;
+ g_fjob.identity = ident;
+ g_fjob.prompt_set = 0;
+
+ /* if we have external parameters, we should use them as well */
+ if (nc->ctx.cb_vparam == sizeof(NETID_DLGINFO) &&
+ (pdlginfo = nc->ctx.vparam) &&
+ pdlginfo->size == NETID_DLGINFO_V1_SZ) {
+ wchar_t * t;
+
+ if (pdlginfo->in.ccache[0] &&
+ SUCCEEDED(StringCchLength(pdlginfo->in.ccache,
+ NETID_CCACHE_NAME_SZ,
+ &size))) {
+ g_fjob.ccache = malloc(sizeof(char) * (size + 1));
+#ifdef DEBUG
+ assert(g_fjob.ccache);
+#endif
+ UnicodeStrToAnsi(g_fjob.ccache, size + 1,
+ pdlginfo->in.ccache);
+
+ /* this is the same as the output cache */
+
+ StringCbCopy(pdlginfo->out.ccache, sizeof(pdlginfo->out.ccache),
+ pdlginfo->in.ccache);
+ } else {
+ g_fjob.ccache = NULL;
+
+ StringCbCopy(pdlginfo->out.ccache, sizeof(pdlginfo->out.ccache),
+ idname);
+
+ khm_krb5_canon_cc_name(pdlginfo->out.ccache,
+ sizeof(pdlginfo->out.ccache));
+ }
+
+ t = khm_get_realm_from_princ(idname);
+
+ if (t) {
+ StringCbCopy(pdlginfo->out.realm,
+ sizeof(pdlginfo->out.realm),
+ t);
+
+ if ((t - idname) > 1) {
+ StringCchCopyN(pdlginfo->out.username,
+ ARRAYLENGTH(pdlginfo->out.username),
+ idname,
+ (t - idname) - 1);
+ } else {
+ StringCbCopy(pdlginfo->out.username,
+ sizeof(pdlginfo->out.username),
+ L"");
+ }
+ } else {
+ StringCbCopy(pdlginfo->out.username,
+ sizeof(pdlginfo->out.username),
+ idname);
+ StringCbCopy(pdlginfo->out.realm,
+ sizeof(pdlginfo->out.realm),
+ L"");
+ }
+ }
+
+ /* leave identity held, since we added a reference above */
+}
+
+void
+k5_free_kinit_job(void)
+{
+ if (g_fjob.principal)
+ free(g_fjob.principal);
+
+ if (g_fjob.password)
+ free(g_fjob.password);
+
+ if (g_fjob.identity)
+ kcdb_identity_release(g_fjob.identity);
+
+ if (g_fjob.ccache)
+ free(g_fjob.ccache);
+
+ ZeroMemory(&g_fjob, sizeof(g_fjob));
+}
+
+static khm_int32 KHMAPI
+k5_find_tgt_filter(khm_handle cred,
+ khm_int32 flags,
+ void * rock) {
+ khm_handle ident = (khm_handle) rock;
+ khm_handle cident = NULL;
+ khm_int32 f;
+ khm_int32 rv;
+
+ if (KHM_SUCCEEDED(kcdb_cred_get_identity(cred,
+ &cident)) &&
+ cident == ident &&
+ KHM_SUCCEEDED(kcdb_cred_get_flags(cred, &f)) &&
+ (f & KCDB_CRED_FLAG_INITIAL))
+ rv = 1;
+ else
+ rv = 0;
+
+ if (cident)
+ kcdb_identity_release(cident);
+
+ return rv;
+}
+
+/* Handler for CRED type messages
+
+ Runs in the context of the Krb5 plugin
+*/
+khm_int32 KHMAPI
+k5_msg_cred_dialog(khm_int32 msg_type,
+ khm_int32 msg_subtype,
+ khm_ui_4 uparam,
+ void * vparam)
+{
+ khm_int32 rv = KHM_ERROR_SUCCESS;
+
+ switch(msg_subtype) {
+
+ case KMSG_CRED_PASSWORD:
+ case KMSG_CRED_NEW_CREDS:
+ {
+ khui_new_creds * nc;
+ khui_new_creds_by_type * nct;
+ wchar_t wbuf[256];
+ size_t cbsize;
+
+ nc = (khui_new_creds *) vparam;
+
+ nct = malloc(sizeof(*nct));
+ ZeroMemory(nct, sizeof(*nct));
+
+ nct->type = credtype_id_krb5;
+ nct->ordinal = 1;
+
+ LoadString(hResModule, IDS_KRB5_SHORT_DESC,
+ wbuf, ARRAYLENGTH(wbuf));
+ StringCbLength(wbuf, sizeof(wbuf), &cbsize);
+ cbsize += sizeof(wchar_t);
+
+ nct->name = malloc(cbsize);
+ StringCbCopy(nct->name, cbsize, wbuf);
+
+ nct->h_module = hResModule;
+ nct->dlg_proc = k5_nc_dlg_proc;
+ if (nc->subtype == KMSG_CRED_PASSWORD)
+ nct->dlg_template = MAKEINTRESOURCE(IDD_NC_KRB5_PASSWORD);
+ else
+ nct->dlg_template = MAKEINTRESOURCE(IDD_NC_KRB5);
+
+ khui_cw_add_type(nc, nct);
+ }
+ break;
+
+ case KMSG_CRED_RENEW_CREDS:
+ {
+ khui_new_creds * nc;
+ khui_new_creds_by_type * nct;
+
+ nc = (khui_new_creds *) vparam;
+
+ nct = malloc(sizeof(*nct));
+ ZeroMemory(nct, sizeof(*nct));
+
+ nct->type = credtype_id_krb5;
+
+ khui_cw_add_type(nc, nct);
+ }
+ break;
+
+ case KMSG_CRED_DIALOG_PRESTART:
+ {
+ khui_new_creds * nc;
+ khui_new_creds_by_type * nct;
+ k5_dlg_data * d;
+ HWND hwnd;
+ wchar_t * realms;
+ wchar_t * t;
+ wchar_t * defrealm;
+
+ nc = (khui_new_creds *) vparam;
+
+ khui_cw_find_type(nc, credtype_id_krb5, &nct);
+
+ if(!nct)
+ break;
+
+ hwnd = nct->hwnd_panel;
+ d = (k5_dlg_data *)(LONG_PTR)
+ GetWindowLongPtr(nct->hwnd_panel, DWLP_USER);
+
+ if (!is_k5_identpro) {
+
+ /* enumerate all realms and place in realms combo box */
+ SendDlgItemMessage(hwnd, IDC_NCK5_REALM,
+ CB_RESETCONTENT,
+ 0, 0);
+
+ realms = khm_krb5_get_realm_list();
+ if(realms) {
+ t = realms;
+ while(t && *t) {
+ SendDlgItemMessage(hwnd, IDC_NCK5_REALM,
+ CB_ADDSTRING,
+ 0, (LPARAM) t);
+ t = multi_string_next(t);
+ }
+ free(realms);
+ }
+
+ /* and set the default realm */
+ defrealm = khm_krb5_get_default_realm();
+ if(defrealm) {
+ SendDlgItemMessage(hwnd, IDC_NCK5_REALM,
+ CB_SELECTSTRING,
+ (WPARAM) -1,
+ (LPARAM) defrealm);
+
+ SendDlgItemMessage(hwnd, IDC_NCK5_REALM,
+ WM_SETTEXT,
+ 0, (LPARAM) defrealm);
+ free(defrealm);
+ }
+ } else { /* if krb5 is the identity provider */
+ HWND hw_realms;
+
+ /* in this case, the realm selection is done by the
+ identity provider prompts. */
+
+ hw_realms = GetDlgItem(hwnd, IDC_NCK5_REALM);
+#ifdef DEBUG
+ assert(hw_realms);
+#endif
+ EnableWindow(hw_realms, FALSE);
+ }
+
+ if (nc->subtype == KMSG_CRED_NEW_CREDS) {
+ k5_read_dlg_params(csp_params, d);
+ }
+
+ PostMessage(hwnd, KHUI_WM_NC_NOTIFY,
+ MAKEWPARAM(0,WMNC_DIALOG_SETUP), 0);
+ }
+ break;
+
+ case KMSG_CRED_DIALOG_NEW_IDENTITY:
+ {
+ khui_new_creds * nc;
+ khui_new_creds_by_type * nct;
+ k5_dlg_data * d;
+
+ nc = (khui_new_creds *) vparam;
+
+ khui_cw_find_type(nc, credtype_id_krb5, &nct);
+ if (!nct)
+ break;
+
+ d = (k5_dlg_data *)(LONG_PTR)
+ GetWindowLongPtr(nct->hwnd_panel, DWLP_USER);
+
+ /* we only load the identity specific defaults if the user
+ hasn't changed the options */
+ khui_cw_lock_nc(nc);
+
+ if(!d->dirty && nc->n_identities > 0 &&
+ nc->subtype == KMSG_CRED_NEW_CREDS) {
+
+ khm_handle h_id = NULL;
+ khm_handle h_idk5 = NULL;
+
+ do {
+ if(KHM_FAILED
+ (kcdb_identity_get_config(nc->identities[0],
+ 0,
+ &h_id)))
+ break;
+
+ if(KHM_FAILED
+ (khc_open_space(h_id, CSNAME_KRB5CRED,
+ 0, &h_idk5)))
+ break;
+
+ if(KHM_FAILED(khc_shadow_space(h_idk5, csp_params)))
+ break;
+
+ k5_read_dlg_params(h_idk5, d);
+
+ PostMessage(nct->hwnd_panel, KHUI_WM_NC_NOTIFY,
+ MAKEWPARAM(0,WMNC_DIALOG_SETUP), 0);
+ } while(FALSE);
+
+ if(h_id)
+ khc_close_space(h_id);
+ if(h_idk5)
+ khc_close_space(h_idk5);
+ }
+
+ khui_cw_unlock_nc(nc);
+ }
+
+ /* fallthrough */
+ case KMSG_CRED_DIALOG_NEW_OPTIONS:
+ {
+ khui_new_creds * nc;
+ khui_new_creds_by_type * nct;
+ k5_dlg_data * d;
+
+ nc = (khui_new_creds *) vparam;
+
+ khui_cw_find_type(nc, credtype_id_krb5, &nct);
+ if (!nct)
+ break;
+
+ d = (k5_dlg_data *)(LONG_PTR)
+ GetWindowLongPtr(nct->hwnd_panel, DWLP_USER);
+
+ if (nc->subtype == KMSG_CRED_PASSWORD) {
+ khm_size n_prompts = 0;
+
+ khui_cw_get_prompt_count(nc, &n_prompts);
+
+ if (nc->n_identities == 0) {
+ if (n_prompts)
+ khui_cw_clear_prompts(nc);
+ } else if (n_prompts != 3) {
+ wchar_t wbuf[KHUI_MAXCCH_BANNER];
+
+ khui_cw_clear_prompts(nc);
+
+ LoadString(hResModule, IDS_NC_PWD_BANNER,
+ wbuf, ARRAYLENGTH(wbuf));
+ khui_cw_begin_custom_prompts(nc, 3, NULL, wbuf);
+
+ LoadString(hResModule, IDS_NC_PWD_PWD,
+ wbuf, ARRAYLENGTH(wbuf));
+ khui_cw_add_prompt(nc, KHUI_NCPROMPT_TYPE_PASSWORD,
+ wbuf, NULL, KHUI_NCPROMPT_FLAG_HIDDEN);
+
+ LoadString(hResModule, IDS_NC_PWD_NPWD,
+ wbuf, ARRAYLENGTH(wbuf));
+ khui_cw_add_prompt(nc, KHUI_NCPROMPT_TYPE_NEW_PASSWORD,
+ wbuf, NULL, KHUI_NCPROMPT_FLAG_HIDDEN);
+
+ LoadString(hResModule, IDS_NC_PWD_NPWD_AGAIN,
+ wbuf, ARRAYLENGTH(wbuf));
+ khui_cw_add_prompt(nc, KHUI_NCPROMPT_TYPE_NEW_PASSWORD_AGAIN,
+ wbuf, NULL, KHUI_NCPROMPT_FLAG_HIDDEN);
+ }
+
+ return KHM_ERROR_SUCCESS;
+ }
+ /* else; nc->subtype == KMSG_CRED_NEW_CREDS */
+
+ assert(nc->subtype == KMSG_CRED_NEW_CREDS);
+
+ /* if the fiber is already in a kinit, cancel it */
+ if(g_fjob.state == FIBER_STATE_KINIT) {
+ g_fjob.command = FIBER_CMD_CANCEL;
+ SwitchToFiber(k5_kinit_fiber);
+ /* we get here when the cancel operation completes */
+ k5_free_kinit_job();
+ }
+
+ khui_cw_lock_nc(nc);
+
+ if(nc->n_identities > 0) {
+ khm_handle ident = nc->identities[0];
+
+ kcdb_identity_hold(ident);
+
+ k5_prep_kinit_job(nc);
+ khui_cw_unlock_nc(nc);
+
+ SwitchToFiber(k5_kinit_fiber);
+ /* we get here when the fiber switches back */
+ if(g_fjob.state == FIBER_STATE_NONE) {
+ wchar_t msg[KHUI_MAXCCH_BANNER];
+ khm_size cb;
+
+ /* we can't possibly have succeeded without a
+ password */
+ if(g_fjob.code) {
+ if (is_k5_identpro)
+ kcdb_identity_set_flags(ident,
+ KCDB_IDENT_FLAG_INVALID);
+
+ khui_cw_clear_prompts(nc);
+ }
+
+ if (d->cred_message) {
+ free(d->cred_message);
+ d->cred_message = NULL;
+ }
+
+ msg[0] = L'\0';
+
+ switch(g_fjob.code) {
+ case KRB5KDC_ERR_NAME_EXP:
+ /* principal expired */
+ LoadString(hResModule, IDS_K5ERR_NAME_EXPIRED,
+ msg, ARRAYLENGTH(msg));
+ break;
+
+ case KRB5KDC_ERR_KEY_EXP:
+ /* password needs changing */
+ LoadString(hResModule, IDS_K5ERR_KEY_EXPIRED,
+ msg, ARRAYLENGTH(msg));
+ break;
+
+ default:
+ {
+ DWORD dw_dummy;
+ kherr_suggestion sug_dummy;
+ wchar_t fmt[KHUI_MAXCCH_BANNER];
+ wchar_t desc[KHUI_MAXCCH_BANNER];
+
+ LoadString(hResModule, IDS_K5ERR_FMT,
+ fmt, ARRAYLENGTH(fmt));
+
+ khm_err_describe(g_fjob.code,
+ desc,
+ sizeof(desc),
+ &dw_dummy,
+ &sug_dummy);
+
+ StringCbPrintf(msg, sizeof(msg), fmt, desc);
+ }
+ }
+
+ if (msg[0]) {
+ StringCbLength(msg, sizeof(msg), &cb);
+ cb += sizeof(wchar_t);
+
+ d->cred_message = malloc(cb);
+ StringCbCopy(d->cred_message, cb, msg);
+ }
+
+ k5_free_kinit_job();
+
+ } else if(g_fjob.state == FIBER_STATE_KINIT) {
+ /* this is what we want. Leave the fiber there. */
+
+ if(is_k5_identpro)
+ kcdb_identity_set_flags(ident,
+ KCDB_IDENT_FLAG_VALID);
+ } else {
+ /* huh?? */
+#ifdef DEBUG
+ assert(FALSE);
+#endif
+ }
+
+ /* since the attributes of the identity have changed,
+ we should update the cred text as well */
+ kcdb_identity_release(ident);
+ khui_cw_lock_nc(nc);
+ PostMessage(nc->hwnd, KHUI_WM_NC_NOTIFY,
+ MAKEWPARAM(0, WMNC_UPDATE_CREDTEXT), 0);
+ } else {
+ khui_cw_unlock_nc(nc);
+ khui_cw_clear_prompts(nc);
+ khui_cw_lock_nc(nc);
+ }
+
+ khui_cw_unlock_nc(nc);
+ }
+ break;
+
+ case KMSG_CRED_PROCESS:
+ {
+ khui_new_creds * nc;
+ khui_new_creds_by_type * nct;
+ k5_dlg_data * d;
+
+ khm_int32 r;
+
+ nc = (khui_new_creds *) vparam;
+
+ khui_cw_find_type(nc, credtype_id_krb5, &nct);
+
+ if(!nct)
+ break;
+
+ /* reset the null_password flag, just in case */
+ g_fjob.null_password = FALSE;
+
+ if (nc->subtype == KMSG_CRED_NEW_CREDS) {
+ d = (k5_dlg_data *) nct->aux;
+
+ _begin_task(0);
+ _report_mr0(KHERR_NONE, MSG_CTX_INITAL_CREDS);
+ _describe();
+
+ if (g_fjob.state == FIBER_STATE_KINIT) {
+ if(nc->result == KHUI_NC_RESULT_CANCEL) {
+ g_fjob.command = FIBER_CMD_CANCEL;
+ SwitchToFiber(k5_kinit_fiber);
+
+ /* if we cancelled out, then we shouldn't care
+ about the return code. */
+#ifdef DEBUG
+ assert(g_fjob.state == FIBER_STATE_NONE);
+#endif
+ g_fjob.code = 0;
+ } else if (nc->result == KHUI_NC_RESULT_GET_CREDS) {
+ khui_cw_sync_prompt_values(nc);
+ g_fjob.command = FIBER_CMD_CONTINUE;
+ SwitchToFiber(k5_kinit_fiber);
+
+ /* We get back here once the fiber finishes
+ processing */
+ }
+#ifdef DEBUG
+ else {
+ assert(FALSE);
+ }
+#endif
+ } else {
+ /* we weren't in a KINIT state */
+ if (nc->result == KHUI_NC_RESULT_CANCEL) {
+ /* nothing to report */
+ g_fjob.code = 0;
+ } else if (nc->result == KHUI_NC_RESULT_GET_CREDS) {
+ /* g_fjob.code should have the result of the
+ last kinit attempt. We should leave it
+ as-is */
+ }
+#ifdef DEBUG
+ else {
+ /* unknown result */
+ assert(FALSE);
+ }
+#endif
+ }
+
+ /* special case: if there was no password entered, and
+ if there is a valid TGT we allow the credential
+ acquisition to go through */
+ if (g_fjob.state == FIBER_STATE_NONE &&
+ g_fjob.code &&
+ g_fjob.null_password &&
+
+ (nc->n_identities == 0 ||
+ nc->identities[0] == NULL ||
+ KHM_SUCCEEDED(kcdb_credset_find_filtered
+ (NULL,
+ -1,
+ k5_find_tgt_filter,
+ nc->identities[0],
+ NULL,
+ NULL))))
+ g_fjob.code = 0;
+
+
+ if(g_fjob.code != 0) {
+ wchar_t tbuf[1024];
+ DWORD suggestion;
+ kherr_suggestion suggest_code;
+
+ khm_err_describe(g_fjob.code, tbuf, sizeof(tbuf),
+ &suggestion, &suggest_code);
+
+ _report_cs0(KHERR_ERROR, tbuf);
+ if (suggestion != 0)
+ _suggest_mr(suggestion, suggest_code);
+
+ _resolve();
+
+ r = KHUI_NC_RESPONSE_FAILED;
+
+ if (suggest_code == KHERR_SUGGEST_RETRY) {
+ r |= KHUI_NC_RESPONSE_NOEXIT |
+ KHUI_NC_RESPONSE_PENDING;
+ }
+
+#ifdef DEBUG
+ assert(g_fjob.state == FIBER_STATE_NONE);
+#endif
+
+ } else if (nc->result == KHUI_NC_RESULT_GET_CREDS &&
+ g_fjob.state == FIBER_STATE_NONE) {
+ khm_handle sp = NULL;
+ khm_handle ep = NULL;
+ krb5_context ctx = NULL;
+ wchar_t * wbuf;
+ wchar_t * idname;
+ wchar_t * atsign;
+ khm_size cb;
+ khm_size cb_ms;
+ khm_int32 rv;
+
+ r = KHUI_NC_RESPONSE_SUCCESS |
+ KHUI_NC_RESPONSE_EXIT;
+
+ /* if we successfully obtained credentials, we
+ should save the current settings in the
+ identity config space */
+
+ assert(nc->n_identities > 0);
+ assert(nc->identities[0]);
+
+ if(KHM_SUCCEEDED
+ (kcdb_identity_get_config(nc->identities[0],
+ KHM_FLAG_CREATE,
+ &sp)) &&
+ KHM_SUCCEEDED
+ (khc_open_space(sp, CSNAME_KRB5CRED,
+ KHM_FLAG_CREATE, &ep))) {
+ k5_write_dlg_params(ep, d);
+ }
+
+ if(ep != NULL)
+ khc_close_space(ep);
+ if(sp != NULL)
+ khc_close_space(sp);
+
+ /* We should also quickly refresh the credentials
+ so that the identity flags and ccache
+ properties reflect the current state of
+ affairs. This has to be done here so that
+ other credentials providers which depend on
+ Krb5 can properly find the initial creds to
+ obtain their respective creds. */
+
+ khm_krb5_list_tickets(&ctx);
+
+ /* also add the principal and the realm in to the
+ LRU lists */
+ rv = kcdb_identity_get_name(nc->identities[0],
+ NULL,
+ &cb);
+ assert(rv == KHM_ERROR_TOO_LONG);
+
+ idname = malloc(cb);
+ assert(idname);
+
+ rv = kcdb_identity_get_name(nc->identities[0],
+ idname,
+ &cb);
+ assert(KHM_SUCCEEDED(rv));
+
+ rv = khc_read_multi_string(csp_params,
+ L"LRUPrincipals",
+ NULL,
+ &cb_ms);
+ if (rv != KHM_ERROR_TOO_LONG)
+ cb_ms = cb + sizeof(wchar_t);
+ else
+ cb_ms += cb + sizeof(wchar_t);
+
+ wbuf = malloc(cb_ms);
+ assert(wbuf);
+
+ cb = cb_ms;
+
+ if (rv == KHM_ERROR_TOO_LONG) {
+ rv = khc_read_multi_string(csp_params,
+ L"LRUPrincipals",
+ wbuf,
+ &cb);
+ assert(KHM_SUCCEEDED(rv));
+
+ if (multi_string_find(wbuf,
+ idname,
+ KHM_CASE_SENSITIVE)
+ != NULL)
+ /* it's already there */
+ goto _add_realm_to_LRU;
+ } else {
+ multi_string_init(wbuf, cb_ms);
+ }
+
+ cb = cb_ms;
+ rv = multi_string_prepend(wbuf, &cb, idname);
+ assert(KHM_SUCCEEDED(rv));
+
+ rv = khc_write_multi_string(csp_params,
+ L"LRUPrincipals",
+ wbuf);
+
+ _add_realm_to_LRU:
+
+ atsign = wcschr(idname, L'@');
+ assert(atsign != NULL);
+
+ atsign++;
+ assert(*atsign != L'\0');
+
+ cb = cb_ms;
+ rv = khc_read_multi_string(csp_params,
+ L"LRURealms",
+ wbuf,
+ &cb);
+
+ if (rv == KHM_ERROR_TOO_LONG) {
+ free(wbuf);
+ wbuf = malloc(cb);
+ assert(wbuf);
+
+ cb_ms = cb;
+
+ rv = khc_read_multi_string(csp_params,
+ L"LRURealms",
+ wbuf,
+ &cb);
+
+ assert(KHM_SUCCEEDED(rv));
+ } else if (rv == KHM_ERROR_SUCCESS) {
+ if (multi_string_find(wbuf,
+ atsign,
+ KHM_CASE_SENSITIVE)
+ != NULL)
+ goto _done_with_LRU;
+ } else {
+ multi_string_init(wbuf, cb_ms);
+ }
+
+ cb = cb_ms;
+ rv = multi_string_prepend(wbuf,
+ &cb,
+ atsign);
+
+ if (rv == KHM_ERROR_TOO_LONG) {
+ wbuf = realloc(wbuf, cb);
+
+ rv = multi_string_prepend(wbuf,
+ &cb,
+ atsign);
+
+ assert(KHM_SUCCEEDED(rv));
+ }
+
+ rv = khc_write_multi_string(csp_params,
+ L"LRURealms",
+ wbuf);
+ assert(KHM_SUCCEEDED(rv));
+
+ _done_with_LRU:
+
+ if (ctx != NULL)
+ pkrb5_free_context(ctx);
+
+ if (idname)
+ free(idname);
+
+ if (wbuf)
+ free(wbuf);
+ } else if (g_fjob.state == FIBER_STATE_NONE) {
+ /* the user cancelled the operation */
+ r = KHUI_NC_RESPONSE_EXIT |
+ KHUI_NC_RESPONSE_SUCCESS;
+ }
+
+ if(g_fjob.state == FIBER_STATE_NONE) {
+ khui_cw_set_response(nc, credtype_id_krb5, r);
+
+ if (r & KHUI_NC_RESPONSE_NOEXIT) {
+ /* if we are retrying the call, we should
+ restart the kinit fiber */
+#ifdef DEBUG
+ assert(r & KHUI_NC_RESPONSE_PENDING);
+#endif
+
+ k5_prep_kinit_job(nc);
+ SwitchToFiber(k5_kinit_fiber);
+ } else {
+ /* free up the fiber data fields. */
+ k5_free_kinit_job();
+ }
+ } else {
+ khui_cw_set_response(nc, credtype_id_krb5,
+ KHUI_NC_RESPONSE_NOEXIT |
+ KHUI_NC_RESPONSE_PENDING | r);
+ }
+
+ _end_task();
+ } else if (nc->subtype == KMSG_CRED_RENEW_CREDS) {
+
+ _begin_task(0);
+ _report_mr0(KHERR_NONE, MSG_CTX_RENEW_CREDS);
+ _describe();
+
+ if (nc->ctx.scope == KHUI_SCOPE_IDENT ||
+ (nc->ctx.scope == KHUI_SCOPE_CREDTYPE &&
+ nc->ctx.cred_type == credtype_id_krb5)) {
+ int code;
+
+ if (nc->ctx.identity != 0)
+ code = khm_krb5_renew(nc->ctx.identity);
+ else
+ code = 1; /* it just has to be non-zero */
+
+ if (code == 0) {
+ khui_cw_set_response(nc, credtype_id_krb5,
+ KHUI_NC_RESPONSE_EXIT |
+ KHUI_NC_RESPONSE_SUCCESS);
+ } else if (nc->ctx.identity == 0) {
+
+ _report_mr0(KHERR_ERROR, MSG_ERR_NO_IDENTITY);
+
+ khui_cw_set_response(nc, credtype_id_krb5,
+ KHUI_NC_RESPONSE_EXIT |
+ KHUI_NC_RESPONSE_FAILED);
+ } else {
+ wchar_t tbuf[1024];
+ DWORD suggestion;
+ kherr_suggestion sug_id;
+
+ khm_err_describe(code, tbuf, sizeof(tbuf),
+ &suggestion, &sug_id);
+
+ _report_cs0(KHERR_ERROR, tbuf);
+ if (suggestion)
+ _suggest_mr(suggestion, sug_id);
+
+ _resolve();
+
+ khui_cw_set_response(nc, credtype_id_krb5,
+ ((sug_id == KHERR_SUGGEST_RETRY)?KHUI_NC_RESPONSE_NOEXIT:KHUI_NC_RESPONSE_EXIT) |
+ KHUI_NC_RESPONSE_FAILED);
+ }
+ } else {
+ khui_cw_set_response(nc, credtype_id_krb5,
+ KHUI_NC_RESPONSE_EXIT |
+ KHUI_NC_RESPONSE_SUCCESS);
+ }
+
+ _end_task();
+ } else if (nc->subtype == KMSG_CRED_PASSWORD &&
+ nc->result == KHUI_NC_RESULT_GET_CREDS) {
+
+ _begin_task(0);
+ _report_mr0(KHERR_NONE, MSG_CTX_PASSWD);
+ _describe();
+
+ khui_cw_lock_nc(nc);
+
+ if (nc->n_identities == 0 ||
+ nc->identities[0] == NULL) {
+ _report_mr0(KHERR_ERROR, MSG_PWD_NO_IDENTITY);
+ _suggest_mr(MSG_PWD_S_NO_IDENTITY, KHERR_SUGGEST_RETRY);
+
+ khui_cw_set_response(nc, credtype_id_krb5,
+ KHUI_NC_RESPONSE_FAILED |
+ KHUI_NC_RESPONSE_NOEXIT);
+ } else {
+ wchar_t widname[KCDB_IDENT_MAXCCH_NAME];
+ char idname[KCDB_IDENT_MAXCCH_NAME];
+ wchar_t wpwd[KHUI_MAXCCH_PASSWORD];
+ char pwd[KHUI_MAXCCH_PASSWORD];
+ wchar_t wnpwd[KHUI_MAXCCH_PASSWORD];
+ char npwd[KHUI_MAXCCH_PASSWORD];
+ wchar_t wnpwd2[KHUI_MAXCCH_PASSWORD];
+ wchar_t * wresult;
+ char * result;
+ khm_size n_prompts = 0;
+ khm_size cb;
+ khm_int32 rv = KHM_ERROR_SUCCESS;
+ long code = 0;
+ khm_handle ident;
+
+ khui_cw_get_prompt_count(nc, &n_prompts);
+ assert(n_prompts == 3);
+
+ ident = nc->identities[0];
+ cb = sizeof(widname);
+ rv = kcdb_identity_get_name(ident, widname, &cb);
+ if (KHM_FAILED(rv)) {
+#ifdef DEBUG
+ assert(FALSE);
+#endif
+ _report_mr0(KHERR_ERROR, MSG_PWD_UNKNOWN);
+ goto _pwd_exit;
+ }
+
+ cb = sizeof(wpwd);
+ rv = khui_cw_get_prompt_value(nc, 0, wpwd, &cb);
+ if (KHM_FAILED(rv)) {
+#ifdef DEBUG
+ assert(FALSE);
+#endif
+ _report_mr0(KHERR_ERROR, MSG_PWD_UNKNOWN);
+ goto _pwd_exit;
+ }
+
+ cb = sizeof(wnpwd);
+ rv = khui_cw_get_prompt_value(nc, 1, wnpwd, &cb);
+ if (KHM_FAILED(rv)) {
+#ifdef DEBUG
+ assert(FALSE);
+#endif
+ _report_mr0(KHERR_ERROR, MSG_PWD_UNKNOWN);
+ goto _pwd_exit;
+ }
+
+ cb = sizeof(wnpwd2);
+ rv = khui_cw_get_prompt_value(nc, 2, wnpwd2, &cb);
+ if (KHM_FAILED(rv)) {
+#ifdef DEBUG
+ assert(FALSE);
+#endif
+ _report_mr0(KHERR_ERROR, MSG_PWD_UNKNOWN);
+ goto _pwd_exit;
+ }
+
+ if (wcscmp(wnpwd, wnpwd2)) {
+ rv = KHM_ERROR_INVALID_PARM;
+ _report_mr0(KHERR_ERROR, MSG_PWD_NOT_SAME);
+ _suggest_mr(MSG_PWD_S_NOT_SAME, KHERR_SUGGEST_INTERACT);
+ goto _pwd_exit;
+ }
+
+ if (!wcscmp(wpwd, wnpwd)) {
+ rv = KHM_ERROR_INVALID_PARM;
+ _report_mr0(KHERR_ERROR, MSG_PWD_SAME);
+ _suggest_mr(MSG_PWD_S_SAME, KHERR_SUGGEST_INTERACT);
+ goto _pwd_exit;
+ }
+
+ UnicodeStrToAnsi(idname, sizeof(idname), widname);
+ UnicodeStrToAnsi(pwd, sizeof(pwd), wpwd);
+ UnicodeStrToAnsi(npwd, sizeof(npwd), wnpwd);
+
+ result = NULL;
+
+ code = khm_krb5_changepwd(idname,
+ pwd,
+ npwd,
+ &result);
+
+ if (code)
+ rv = KHM_ERROR_UNKNOWN;
+
+ /* result is only set when code != 0 */
+ if (code && result) {
+ size_t len;
+
+ StringCchLengthA(result, KHERR_MAXCCH_STRING,
+ &len);
+ wresult = malloc((len + 1) * sizeof(wchar_t));
+#ifdef DEBUG
+ assert(wresult);
+#endif
+ AnsiStrToUnicode(wresult, (len + 1) * sizeof(wchar_t),
+ result);
+
+ _report_cs1(KHERR_ERROR, L"%1!s!", _cstr(wresult));
+ _resolve();
+
+ free(result);
+ free(wresult);
+
+ /* leave wresult. It will get freed when the
+ reported event is freed. */
+
+ /* we don't need to report anything more */
+ code = 0;
+ }
+
+ _pwd_exit:
+ if (KHM_FAILED(rv)) {
+ if (code) {
+ wchar_t tbuf[1024];
+ DWORD suggestion;
+ kherr_suggestion sug_id;
+
+ khm_err_describe(code, tbuf, sizeof(tbuf),
+ &suggestion, &sug_id);
+ _report_cs0(KHERR_ERROR, tbuf);
+
+ if (suggestion)
+ _suggest_mr(suggestion, sug_id);
+
+ _resolve();
+ }
+
+ khui_cw_set_response(nc, credtype_id_krb5,
+ KHUI_NC_RESPONSE_NOEXIT|
+ KHUI_NC_RESPONSE_FAILED);
+ } else {
+ khui_cw_set_response(nc, credtype_id_krb5,
+ KHUI_NC_RESPONSE_SUCCESS |
+ KHUI_NC_RESPONSE_EXIT);
+ }
+ }
+
+ khui_cw_unlock_nc(nc);
+
+ _end_task();
+ } /* KMSG_CRED_PASSWORD */
+ }
+ break;
+
+ case KMSG_CRED_END:
+ {
+ khui_new_creds * nc;
+ khui_new_creds_by_type * nct;
+
+ nc = (khui_new_creds *) vparam;
+ khui_cw_find_type(nc, credtype_id_krb5, &nct);
+
+ if(!nct)
+ break;
+
+ khui_cw_del_type(nc, credtype_id_krb5);
+
+ if(nct->name)
+ free(nct->name);
+
+ free(nct);
+ }
+ break;
+
+ case KMSG_CRED_IMPORT:
+ {
+ khm_krb5_ms2mit(TRUE);
+ }
+ break;
+ }
+
+ return rv;
+}
diff --git a/src/windows/identity/plugins/krb5/krb5plugin.c b/src/windows/identity/plugins/krb5/krb5plugin.c
new file mode 100644
index 0000000..4b53ed3
--- /dev/null
+++ b/src/windows/identity/plugins/krb5/krb5plugin.c
@@ -0,0 +1,230 @@
+/*
+ * Copyright (c) 2004 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#include<krbcred.h>
+#include<kherror.h>
+#include<khmsgtypes.h>
+#include<commctrl.h>
+#include<strsafe.h>
+#include<krb5.h>
+
+khm_int32 credtype_id_krb5 = KCDB_CREDTYPE_INVALID;
+khm_boolean krb5_initialized = FALSE;
+khm_handle krb5_credset = NULL;
+
+khm_handle k5_sub = NULL;
+
+LPVOID k5_main_fiber = NULL;
+LPVOID k5_kinit_fiber = NULL;
+
+VOID CALLBACK k5_kinit_fiber_proc(PVOID lpParameter);
+
+krb5_context k5_identpro_ctx = NULL;
+
+/* The system message handler.
+
+ Runs in the context of the plugin thread */
+khm_int32 KHMAPI k5_msg_system(khm_int32 msg_type, khm_int32 msg_subtype, khm_ui_4 uparam, void * vparam)
+{
+ khm_int32 rv = KHM_ERROR_SUCCESS;
+
+ switch(msg_subtype) {
+ case KMSG_SYSTEM_INIT:
+ {
+ kcdb_credtype ct;
+ wchar_t buf[KCDB_MAXCCH_SHORT_DESC];
+ size_t cbsize;
+
+ /* perform critical registrations and initialization
+ stuff */
+ ZeroMemory(&ct, sizeof(ct));
+ ct.id = KCDB_CREDTYPE_AUTO;
+ ct.name = KRB5_CREDTYPE_NAME;
+
+ if(LoadString(hResModule, IDS_KRB5_SHORT_DESC, buf, ARRAYLENGTH(buf)))
+ {
+ StringCbLength(buf, KCDB_MAXCB_SHORT_DESC, &cbsize);
+ cbsize += sizeof(wchar_t);
+ ct.short_desc = malloc(cbsize);
+ StringCbCopy(ct.short_desc, cbsize, buf);
+ }
+
+ /* even though ideally we should be setting limits
+ based KCDB_MAXCB_LONG_DESC, our long description
+ actually fits nicely in KCDB_MAXCB_SHORT_DESC */
+ if(LoadString(hResModule, IDS_KRB5_LONG_DESC, buf, ARRAYLENGTH(buf)))
+ {
+ StringCbLength(buf, KCDB_MAXCB_SHORT_DESC, &cbsize);
+ cbsize += sizeof(wchar_t);
+ ct.long_desc = malloc(cbsize);
+ StringCbCopy(ct.long_desc, cbsize, buf);
+ }
+
+ ct.icon = NULL; /* TODO: set a proper icon */
+
+ kmq_create_subscription(k5_msg_callback, &ct.sub);
+
+ rv = kcdb_credtype_register(&ct, &credtype_id_krb5);
+
+ if(KHM_SUCCEEDED(rv))
+ rv = kcdb_credset_create(&krb5_credset);
+
+ if(ct.short_desc)
+ free(ct.short_desc);
+
+ if(ct.long_desc)
+ free(ct.long_desc);
+
+ if (is_k5_identpro)
+ kcdb_identity_set_type(credtype_id_krb5);
+
+ if(KHM_SUCCEEDED(rv)) {
+ krb5_context ctx = NULL;
+
+ krb5_initialized = TRUE;
+
+ khm_krb5_list_tickets(&ctx);
+
+ if(ctx != NULL)
+ pkrb5_free_context(ctx);
+
+ /* now convert this thread to a fiber and create a
+ separate fiber to do kinit stuff */
+ k5_main_fiber = ConvertThreadToFiber(NULL);
+ k5_kinit_fiber = CreateFiber(0,k5_kinit_fiber_proc,NULL);
+
+ ZeroMemory(&g_fjob, sizeof(g_fjob));
+
+ kmq_create_subscription(k5_msg_callback, &k5_sub);
+
+ pkrb5_init_context(&k5_identpro_ctx);
+
+ k5_register_config_panels();
+ }
+ }
+ break;
+
+ case KMSG_SYSTEM_EXIT:
+
+ k5_unregister_config_panels();
+
+ if(credtype_id_krb5 >= 0)
+ {
+ /* basically just unregister the credential type */
+ kcdb_credtype_unregister(credtype_id_krb5);
+
+ /* kcdb knows how to deal with bad handles */
+ kcdb_credset_delete(krb5_credset);
+ krb5_credset = NULL;
+ }
+
+ if(k5_main_fiber != NULL) {
+ ConvertFiberToThread();
+ k5_main_fiber = NULL;
+ }
+
+ if(k5_sub != NULL) {
+ kmq_delete_subscription(k5_sub);
+ k5_sub = NULL;
+ }
+
+ if (k5_identpro_ctx) {
+ pkrb5_free_context(k5_identpro_ctx);
+ k5_identpro_ctx = NULL;
+ }
+
+ break;
+ }
+
+ return rv;
+}
+
+
+/* Handler for CRED type messages
+
+ Runs in the context of the Krb5 plugin
+*/
+khm_int32 KHMAPI k5_msg_cred(khm_int32 msg_type, khm_int32 msg_subtype, khm_ui_4 uparam, void * vparam)
+{
+ khm_int32 rv = KHM_ERROR_SUCCESS;
+
+ switch(msg_subtype) {
+ case KMSG_CRED_REFRESH:
+ {
+ krb5_context ctx = NULL;
+
+ khm_krb5_list_tickets(&ctx);
+
+ if(ctx != NULL)
+ pkrb5_free_context(ctx);
+ }
+ break;
+
+ case KMSG_CRED_DESTROY_CREDS:
+ {
+ khui_action_context * ctx;
+
+ ctx = (khui_action_context *) vparam;
+
+ if (ctx->credset)
+ khm_krb5_destroy_by_credset(ctx->credset);
+ }
+ break;
+
+ case KMSG_CRED_PP_BEGIN:
+ k5_pp_begin((khui_property_sheet *) vparam);
+ break;
+
+ case KMSG_CRED_PP_END:
+ k5_pp_end((khui_property_sheet *) vparam);
+ break;
+
+ default:
+ if(IS_CRED_ACQ_MSG(msg_subtype))
+ return k5_msg_cred_dialog(msg_type, msg_subtype,
+ uparam, vparam);
+ }
+
+ return rv;
+}
+
+/* The main message handler. We don't do much here, except delegate
+ to other message handlers
+
+ Runs in the context of the Krb5 plugin
+*/
+khm_int32 KHMAPI k5_msg_callback(khm_int32 msg_type, khm_int32 msg_subtype, khm_ui_4 uparam, void * vparam)
+{
+ switch(msg_type) {
+ case KMSG_SYSTEM:
+ return k5_msg_system(msg_type, msg_subtype, uparam, vparam);
+ case KMSG_CRED:
+ return k5_msg_cred(msg_type, msg_subtype, uparam, vparam);
+ case KMSG_IDENT:
+ return k5_msg_ident(msg_type, msg_subtype, uparam, vparam);
+ }
+ return KHM_ERROR_SUCCESS;
+}
diff --git a/src/windows/identity/plugins/krb5/krb5props.c b/src/windows/identity/plugins/krb5/krb5props.c
new file mode 100644
index 0000000..9134de2
--- /dev/null
+++ b/src/windows/identity/plugins/krb5/krb5props.c
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2004 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#include<krbcred.h>
+#include<kherror.h>
+#include<khmsgtypes.h>
+#include<commctrl.h>
+#include<strsafe.h>
+#include<krb5.h>
+
+/* Property page
+
+ Runs in the context of the UI thread.
+ */
+INT_PTR CALLBACK krb5_pp_proc(HWND hwnd,
+ UINT uMsg,
+ WPARAM wParam,
+ LPARAM lParam
+ )
+{
+ switch(uMsg) {
+ case WM_INITDIALOG:
+ {
+ khui_property_sheet * s;
+ PROPSHEETPAGE * p;
+ wchar_t buf[512];
+ khm_size cbsize;
+
+ p = (PROPSHEETPAGE *) lParam;
+ s = (khui_property_sheet *) p->lParam;
+
+#pragma warning(push)
+#pragma warning(disable: 4244)
+ SetWindowLongPtr(hwnd, DWLP_USER, (LONG_PTR) s);
+#pragma warning(pop)
+
+ if(s->cred) {
+ cbsize = sizeof(buf);
+ kcdb_cred_get_name(s->cred, buf, &cbsize);
+ SetDlgItemText(hwnd, IDC_PPK5_NAME, buf);
+
+ cbsize = sizeof(buf);
+ kcdb_cred_get_attr_string(s->cred, KCDB_ATTR_ISSUE, buf, &cbsize, 0);
+ SetDlgItemText(hwnd, IDC_PPK5_ISSUE, buf);
+
+ cbsize = sizeof(buf);
+ kcdb_cred_get_attr_string(s->cred, KCDB_ATTR_EXPIRE, buf, &cbsize, 0);
+ SetDlgItemText(hwnd, IDC_PPK5_VALID, buf);
+
+ cbsize = sizeof(buf);
+ kcdb_cred_get_attr_string(s->cred, KCDB_ATTR_RENEW_EXPIRE, buf, &cbsize, 0);
+ SetDlgItemText(hwnd, IDC_PPK5_RENEW, buf);
+
+ /*TODO: select other properties */
+ } else {
+ /*TODO: select properties */
+ }
+ }
+ return FALSE;
+ }
+
+ return FALSE;
+}
+
+void k5_pp_begin(khui_property_sheet * s)
+{
+ PROPSHEETPAGE *p;
+
+ if(s->credtype == credtype_id_krb5) {
+ p = malloc(sizeof(*p));
+ ZeroMemory(p, sizeof(*p));
+
+ p->dwSize = sizeof(*p);
+ p->dwFlags = 0;
+ p->hInstance = hResModule;
+ p->pszTemplate = (s->cred)? MAKEINTRESOURCE(IDD_PP_KRB5C): MAKEINTRESOURCE(IDD_PP_KRB5);
+ p->pfnDlgProc = krb5_pp_proc;
+ p->lParam = (LPARAM) s;
+ khui_ps_add_page(s, credtype_id_krb5, 0, p, NULL);
+ }
+}
+
+void k5_pp_end(khui_property_sheet * s)
+{
+ khui_property_page * p = NULL;
+
+ khui_ps_find_page(s, credtype_id_krb5, &p);
+ if(p) {
+ if(p->p_page)
+ free(p->p_page);
+ p->p_page = NULL;
+ }
+}
+
diff --git a/src/windows/identity/plugins/krb5/krb5util.c b/src/windows/identity/plugins/krb5/krb5util.c
new file mode 100644
index 0000000..b892531
--- /dev/null
+++ b/src/windows/identity/plugins/krb5/krb5util.c
@@ -0,0 +1,1362 @@
+/*
+ * Copyright (c) 2004 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#include <windows.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <winsock.h>
+#include "leashdll.h"
+#include <KerberosIV/krb.h>
+#include <prot.h>
+#include <time.h>
+
+#include <leashwin.h>
+#include "leasherr.h"
+#include "leash-int.h"
+#include "leashids.h"
+
+#include <mitwhich.h>
+
+#include <winkrbid.h>
+#include "reminder.h"
+
+static char FAR *err_context;
+
+char KRB_HelpFile[_MAX_PATH] = HELPFILE;
+
+#define LEN 64 /* Maximum Hostname Length */
+
+#define LIFE DEFAULT_TKT_LIFE /* lifetime of ticket in 5-minute units */
+
+char *
+short_date(dp)
+ long *dp;
+{
+ register char *cp;
+ cp = ctime(dp) + 4; // skip day of week
+ // cp[15] = '\0';
+ cp[12] = '\0'; // Don't display seconds
+ return (cp);
+}
+
+
+static
+char*
+clean_string(
+ char* s
+ )
+{
+ char* p = s;
+ char* b = s;
+
+ if (!s) return s;
+
+ for (p = s; *p; p++) {
+ switch (*p) {
+ case '\007':
+ /* Add more cases here */
+ break;
+ default:
+ *b = *p;
+ b++;
+ }
+ }
+ *b = *p;
+ return s;
+}
+
+static
+int
+leash_error_message(
+ const char *error,
+ int rcL,
+ int rc4,
+ int rc5,
+ int rcA,
+ char* result_string,
+ int displayMB
+ )
+{
+ char message[2048];
+ char *p = message;
+ int size = sizeof(message);
+ int n;
+
+ // XXX: ignore AFS for now.
+
+ if (!rc5 && !rc4 && !rcL)
+ return 0;
+
+ n = _snprintf(p, size, "%s\n\n", error);
+ p += n;
+ size -= n;
+
+ if (rc5 && !result_string)
+ {
+ n = _snprintf(p, size,
+ "Kerberos 5: %s (error %ld)\n",
+ perror_message(rc5),
+ rc5 & 255 // XXX: & 255??!!!
+ );
+ p += n;
+ size -= n;
+ }
+ if (rc4 && !result_string)
+ {
+ char buffer[1024];
+ n = _snprintf(p, size,
+ "Kerberos 4: %s\n",
+ err_describe(buffer, rc4)
+ );
+ p += n;
+ size -= n;
+ }
+ if (rcL)
+ {
+ char buffer[1024];
+ n = _snprintf(p, size,
+ "\n%s\n",
+ err_describe(buffer, rcL)
+ );
+ p += n;
+ size -= n;
+ }
+ if (result_string)
+ {
+ n = _snprintf(p, size,
+ "%s\n",
+ result_string);
+ p += n;
+ size -= n;
+ }
+ if ( displayMB )
+ MessageBox(NULL, message, "Leash", MB_OK | MB_ICONERROR | MB_TASKMODAL |
+ MB_SETFOREGROUND);
+
+ if (rc5) return rc5;
+ if (rc4) return rc4;
+ if (rcL) return rcL;
+ return 0;
+}
+
+
+static
+char *
+make_postfix(
+ const char * base,
+ const char * postfix,
+ char ** rcopy
+ )
+{
+ int base_size;
+ int ret_size;
+ char * copy = 0;
+ char * ret = 0;
+
+ base_size = strlen(base) + 1;
+ ret_size = base_size + strlen(postfix) + 1;
+ copy = malloc(base_size);
+ ret = malloc(ret_size);
+
+ if (!copy || !ret)
+ goto cleanup;
+
+ strncpy(copy, base, base_size);
+ copy[base_size - 1] = 0;
+
+ strncpy(ret, base, base_size);
+ strncpy(ret + (base_size - 1), postfix, ret_size - (base_size - 1));
+ ret[ret_size - 1] = 0;
+
+ cleanup:
+ if (!copy || !ret) {
+ if (copy)
+ free(copy);
+ if (ret)
+ free(ret);
+ copy = ret = 0;
+ }
+ // INVARIANT: (ret ==> copy) && (copy ==> ret)
+ *rcopy = copy;
+ return ret;
+}
+
+static
+long
+make_temp_cache_v4(
+ const char * postfix
+ )
+{
+ static char * old_cache = 0;
+
+ if (!pkrb_set_tkt_string || !ptkt_string || !pdest_tkt)
+ return 0; // XXX - is this appropriate?
+
+ if (old_cache) {
+ pdest_tkt();
+ pkrb_set_tkt_string(old_cache);
+ free(old_cache);
+ old_cache = 0;
+ }
+
+ if (postfix)
+ {
+ char * tmp_cache = make_postfix(ptkt_string(), postfix, &old_cache);
+
+ if (!tmp_cache)
+ return KFAILURE;
+
+ pkrb_set_tkt_string(tmp_cache);
+ free(tmp_cache);
+ }
+ return 0;
+}
+
+static
+long
+make_temp_cache_v5(
+ const char * postfix,
+ krb5_context * pctx
+ )
+{
+ static krb5_context ctx = 0;
+ static char * old_cache = 0;
+
+ // INVARIANT: old_cache ==> ctx && ctx ==> old_cache
+
+ if (pctx)
+ *pctx = 0;
+
+ if (!pkrb5_init_context || !pkrb5_free_context || !pkrb5_cc_resolve ||
+ !pkrb5_cc_default_name || !pkrb5_cc_set_default_name)
+ return 0;
+
+ if (old_cache) {
+ krb5_ccache cc = 0;
+ if (!pkrb5_cc_resolve(ctx, pkrb5_cc_default_name(ctx), &cc))
+ pkrb5_cc_destroy(ctx, cc);
+ pkrb5_cc_set_default_name(ctx, old_cache);
+ free(old_cache);
+ old_cache = 0;
+ }
+ if (ctx) {
+ pkrb5_free_context(ctx);
+ ctx = 0;
+ }
+
+ if (postfix)
+ {
+ char * tmp_cache = 0;
+ krb5_error_code rc = 0;
+
+ rc = pkrb5_init_context(&ctx);
+ if (rc) goto cleanup;
+
+ tmp_cache = make_postfix(pkrb5_cc_default_name(ctx), postfix,
+ &old_cache);
+
+ if (!tmp_cache) {
+ rc = ENOMEM;
+ goto cleanup;
+ }
+
+ rc = pkrb5_cc_set_default_name(ctx, tmp_cache);
+
+ cleanup:
+ if (rc && ctx) {
+ pkrb5_free_context(ctx);
+ ctx = 0;
+ }
+ if (tmp_cache)
+ free(tmp_cache);
+ if (pctx)
+ *pctx = ctx;
+ return rc;
+ }
+ return 0;
+}
+
+long
+Leash_checkpwd(
+ char *principal,
+ char *password
+ )
+{
+ return Leash_int_checkpwd(principal, password, 0);
+}
+
+long
+Leash_int_checkpwd(
+ char * principal,
+ char * password,
+ int displayErrors
+ )
+{
+ long rc = 0;
+ krb5_context ctx = 0; // statically allocated in make_temp_cache_v5
+ // XXX - we ignore errors in make_temp_cache_v? This is BAD!!!
+ make_temp_cache_v4("_checkpwd");
+ make_temp_cache_v5("_checkpwd", &ctx);
+ rc = Leash_int_kinit_ex( ctx, 0,
+ principal, password, 0, 0, 0, 0,
+ Leash_get_default_noaddresses(),
+ Leash_get_default_publicip(),
+ displayErrors
+ );
+ make_temp_cache_v4(0);
+ make_temp_cache_v5(0, &ctx);
+ return rc;
+}
+
+static
+long
+Leash_changepwd_v5(char * principal,
+ char * password,
+ char * newpassword,
+ char** error_str)
+{
+ krb5_error_code rc = 0;
+ int result_code;
+ krb5_data result_code_string, result_string;
+ krb5_context context = 0;
+ krb5_principal princ = 0;
+ krb5_get_init_creds_opt opts;
+ krb5_creds creds;
+ DWORD addressless = 0;
+
+ result_string.data = 0;
+ result_code_string.data = 0;
+
+ if ( !pkrb5_init_context )
+ goto cleanup;
+
+ if (rc = pkrb5_init_context(&context)) {
+#if 0
+ com_err(argv[0], ret, "initializing kerberos library");
+#endif
+ goto cleanup;
+ }
+
+ if (rc = pkrb5_parse_name(context, principal, &princ)) {
+#if 0
+ com_err(argv[0], ret, "parsing client name");
+#endif
+ goto cleanup;
+ }
+
+ pkrb5_get_init_creds_opt_init(&opts);
+ pkrb5_get_init_creds_opt_set_tkt_life(&opts, 5*60);
+ pkrb5_get_init_creds_opt_set_renew_life(&opts, 0);
+ pkrb5_get_init_creds_opt_set_forwardable(&opts, 0);
+ pkrb5_get_init_creds_opt_set_proxiable(&opts, 0);
+
+ addressless = Leash_get_default_noaddresses();
+ if (addressless)
+ pkrb5_get_init_creds_opt_set_address_list(&opts,NULL);
+
+
+ if (rc = pkrb5_get_init_creds_password(context, &creds, princ, password,
+ 0, 0, 0, "kadmin/changepw", &opts)) {
+ if (rc == KRB5KRB_AP_ERR_BAD_INTEGRITY) {
+#if 0
+ com_err(argv[0], 0,
+ "Password incorrect while getting initial ticket");
+#endif
+ }
+ else {
+#if 0
+ com_err(argv[0], ret, "getting initial ticket");
+#endif
+ }
+ goto cleanup;
+ }
+
+ if (rc = pkrb5_change_password(context, &creds, newpassword,
+ &result_code, &result_code_string,
+ &result_string)) {
+#if 0
+ com_err(argv[0], ret, "changing password");
+#endif
+ goto cleanup;
+ }
+
+ if (result_code) {
+ int len = result_code_string.length +
+ (result_string.length ? (sizeof(": ") - 1) : 0) +
+ result_string.length;
+ if (len && error_str) {
+ *error_str = malloc(len + 1);
+ if (*error_str)
+ _snprintf(*error_str, len + 1,
+ "%.*s%s%.*s",
+ result_code_string.length, result_code_string.data,
+ result_string.length?": ":"",
+ result_string.length, result_string.data);
+ }
+ rc = result_code;
+ goto cleanup;
+ }
+
+ cleanup:
+ if (result_string.data)
+ pkrb5_free_data_contents(context, &result_string);
+
+ if (result_code_string.data)
+ pkrb5_free_data_contents(context, &result_code_string);
+
+ if (princ)
+ pkrb5_free_principal(context, princ);
+
+ if (context)
+ pkrb5_free_context(context);
+
+ return rc;
+}
+
+static
+long
+Leash_changepwd_v4(
+ char * principal,
+ char * password,
+ char * newpassword,
+ char** error_str
+ )
+{
+ long k_errno;
+
+ if (!pkrb_set_tkt_string || !ptkt_string || !pkadm_change_your_password ||
+ !pdest_tkt)
+ return KFAILURE;
+
+ k_errno = make_temp_cache_v4("_chgpwd");
+ if (k_errno) return k_errno;
+ k_errno = pkadm_change_your_password(principal, password, newpassword,
+ error_str);
+ make_temp_cache_v4(0);
+ return k_errno;
+}
+
+/*
+ * Leash_changepwd
+ *
+ * Try to change the password using one of krb5 or krb4 -- whichever one
+ * works. We return ok on the first one that works.
+ */
+long
+Leash_changepwd(
+ char * principal,
+ char * password,
+ char * newpassword,
+ char** result_string
+ )
+{
+ return Leash_int_changepwd(principal, password, newpassword, result_string, 0);
+}
+
+long
+Leash_int_changepwd(
+ char * principal,
+ char * password,
+ char * newpassword,
+ char** result_string,
+ int displayErrors
+ )
+{
+ char* v5_error_str = 0;
+ char* v4_error_str = 0;
+ char* error_str = 0;
+ int rc4 = 0;
+ int rc5 = 0;
+ int rc = 0;
+ if (hKrb5)
+ rc = rc5 = Leash_changepwd_v5(principal, password, newpassword,
+ &v5_error_str);
+ if (hKrb4 &&
+ Leash_get_default_use_krb4() &&
+ (!hKrb5 || rc5))
+ rc = rc4 = Leash_changepwd_v4(principal, password, newpassword,
+ &v4_error_str);
+ if (!rc)
+ return 0;
+ if (v5_error_str || v4_error_str) {
+ int len = 0;
+ char v5_prefix[] = "Kerberos 5: ";
+ char sep[] = "\n";
+ char v4_prefix[] = "Kerberos 4: ";
+
+ clean_string(v5_error_str);
+ clean_string(v4_error_str);
+
+ if (v5_error_str)
+ len += sizeof(sep) + sizeof(v5_prefix) + strlen(v5_error_str) +
+ sizeof(sep);
+ if (v4_error_str)
+ len += sizeof(sep) + sizeof(v4_prefix) + strlen(v4_error_str) +
+ sizeof(sep);
+ error_str = malloc(len + 1);
+ if (error_str) {
+ char* p = error_str;
+ int size = len + 1;
+ int n;
+ if (v5_error_str) {
+ n = _snprintf(p, size, "%s%s%s%s",
+ sep, v5_prefix, v5_error_str, sep);
+ p += n;
+ size -= n;
+ }
+ if (v4_error_str) {
+ n = _snprintf(p, size, "%s%s%s%s",
+ sep, v4_prefix, v4_error_str, sep);
+ p += n;
+ size -= n;
+ }
+ if (result_string)
+ *result_string = error_str;
+ }
+ }
+ return leash_error_message("Error while changing password.",
+ rc4, rc4, rc5, 0, error_str,
+ displayErrors
+ );
+}
+
+int (*Lcom_err)(LPSTR,long,LPSTR,...);
+LPSTR (*Lerror_message)(long);
+LPSTR (*Lerror_table_name)(long);
+
+
+long
+Leash_kinit(
+ char * principal,
+ char * password,
+ int lifetime
+ )
+{
+ return Leash_int_kinit_ex( 0, 0,
+ principal,
+ password,
+ lifetime,
+ Leash_get_default_forwardable(),
+ Leash_get_default_proxiable(),
+ Leash_get_default_renew_till(),
+ Leash_get_default_noaddresses(),
+ Leash_get_default_publicip(),
+ 0
+ );
+}
+
+long
+Leash_kinit_ex(
+ char * principal,
+ char * password,
+ int lifetime,
+ int forwardable,
+ int proxiable,
+ int renew_life,
+ int addressless,
+ unsigned long publicip
+ )
+{
+ return Leash_int_kinit_ex( 0, /* krb5 context */
+ 0, /* parent window */
+ principal,
+ password,
+ lifetime,
+ forwardable,
+ proxiable,
+ renew_life,
+ addressless,
+ publicip,
+ 0
+ );
+}
+
+long
+Leash_int_kinit_ex(
+ krb5_context ctx,
+ HWND hParent,
+ char * principal,
+ char * password,
+ int lifetime,
+ int forwardable,
+ int proxiable,
+ int renew_life,
+ int addressless,
+ unsigned long publicip,
+ int displayErrors
+ )
+{
+ LPCSTR functionName;
+ char aname[ANAME_SZ];
+ char inst[INST_SZ];
+ char realm[REALM_SZ];
+ char first_part[256];
+ char second_part[256];
+ char temp[1024];
+ int count;
+ int i;
+ int rc4 = 0;
+ int rc5 = 0;
+ int rcA = 0;
+ int rcL = 0;
+
+ if (lifetime < 5)
+ lifetime = 1;
+ else
+ lifetime /= 5;
+
+ if (renew_life > 0 && renew_life < 5)
+ renew_life = 1;
+ else
+ renew_life /= 5;
+
+ /* This should be changed if the maximum ticket lifetime */
+ /* changes */
+
+ if (lifetime > 255)
+ lifetime = 255;
+
+ err_context = "parsing principal";
+
+ memset(temp, '\0', sizeof(temp));
+ memset(inst, '\0', sizeof(inst));
+ memset(realm, '\0', sizeof(realm));
+ memset(first_part, '\0', sizeof(first_part));
+ memset(second_part, '\0', sizeof(second_part));
+
+ sscanf(principal, "%[/0-9a-zA-Z._-]@%[/0-9a-zA-Z._-]", first_part, second_part);
+ strcpy(temp, first_part);
+ strcpy(realm, second_part);
+ memset(first_part, '\0', sizeof(first_part));
+ memset(second_part, '\0', sizeof(second_part));
+ if (sscanf(temp, "%[@0-9a-zA-Z._-]/%[@0-9a-zA-Z._-]", first_part, second_part) == 2)
+ {
+ strcpy(aname, first_part);
+ strcpy(inst, second_part);
+ }
+ else
+ {
+ count = 0;
+ i = 0;
+ for (i = 0; temp[i]; i++)
+ {
+ if (temp[i] == '.')
+ ++count;
+ }
+ if (count > 1)
+ {
+ strcpy(aname, temp);
+ }
+ else
+ {
+ if (pkname_parse != NULL)
+ {
+ memset(first_part, '\0', sizeof(first_part));
+ memset(second_part, '\0', sizeof(second_part));
+ sscanf(temp, "%[@/0-9a-zA-Z_-].%[@/0-9a-zA-Z_-]", first_part, second_part);
+ strcpy(aname, first_part);
+ strcpy(inst, second_part);
+ }
+ else
+ {
+ strcpy(aname, temp);
+ }
+ }
+ }
+
+ memset(temp, '\0', sizeof(temp));
+ strcpy(temp, aname);
+ if (strlen(inst) != 0)
+ {
+ strcat(temp, "/");
+ strcat(temp, inst);
+ }
+ if (strlen(realm) != 0)
+ {
+ strcat(temp, "@");
+ strcat(temp, realm);
+ }
+
+ rc5 = Leash_krb5_kinit(ctx, hParent,
+ temp, password, lifetime,
+ forwardable,
+ proxiable,
+ renew_life,
+ addressless,
+ publicip
+ );
+ if ( Leash_get_default_use_krb4() ) {
+ if ( !rc5 ) {
+ if (!Leash_convert524(ctx))
+ rc4 = KFAILURE;
+ } else {
+ if (pkname_parse == NULL)
+ {
+ goto cleanup;
+ }
+
+ err_context = "getting realm";
+ if (!*realm && (rc4 = (int)(*pkrb_get_lrealm)(realm, 1)))
+ {
+ functionName = "krb_get_lrealm()";
+ rcL = LSH_FAILEDREALM;
+ goto cleanup;
+ }
+
+ err_context = "checking principal";
+ if ((!*aname) || (!(rc4 = (int)(*pk_isname)(aname))))
+ {
+ functionName = "krb_get_lrealm()";
+ rcL = LSH_INVPRINCIPAL;
+ goto cleanup;
+ }
+
+ /* optional instance */
+ if (!(rc4 = (int)(*pk_isinst)(inst)))
+ {
+ functionName = "k_isinst()";
+ rcL = LSH_INVINSTANCE;
+ goto cleanup;
+ }
+
+ if (!(rc4 = (int)(*pk_isrealm)(realm)))
+ {
+ functionName = "k_isrealm()";
+ rcL = LSH_INVREALM;
+ goto cleanup;
+ }
+
+ err_context = "fetching ticket";
+ rc4 = (*pkrb_get_pw_in_tkt)(aname, inst, realm, "krbtgt", realm,
+ lifetime, password);
+ if (rc4) /* XXX: do we want: && (rc != NO_TKT_FIL) as well? */
+ {
+ functionName = "krb_get_pw_in_tkt()";
+ rcL = KRBERR(rc4);
+ goto cleanup;
+ }
+ }
+ }
+
+#ifndef NO_AFS
+ if ( !rc5 || (Leash_get_default_use_krb4() && !rc4) ) {
+ char c;
+ char *r;
+ char *t;
+ for ( r=realm, t=temp; c=*r; r++,t++ )
+ *t = isupper(c) ? tolower(c) : c;
+ *t = '\0';
+
+ rcA = Leash_afs_klog("afs", temp, realm, lifetime);
+ if (rcA)
+ rcA = Leash_afs_klog("afs", "", realm, lifetime);
+ }
+#endif /* NO_AFS */
+
+ cleanup:
+ return leash_error_message("Ticket initialization failed.",
+ rcL, (rc5 && rc4)?KRBERR(rc4):0, rc5, rcA, 0,
+ displayErrors);
+}
+
+long FAR
+Leash_renew(void)
+{
+ if ( hKrb5 && !LeashKRB5_renew() ) {
+ int lifetime;
+ lifetime = Leash_get_default_lifetime() / 5;
+ if (hKrb4 && Leash_get_default_use_krb4())
+ Leash_convert524(0);
+#ifndef NO_AFS
+ {
+ TicketList * list = NULL, * token;
+ afs_get_tokens(NULL,&list,NULL);
+ for ( token = list ; token ; token = token->next )
+ Leash_afs_klog("afs", token->realm, "", lifetime);
+ not_an_API_LeashFreeTicketList(&list);
+ }
+#endif /* NO_AFS */
+ return 1;
+ }
+ return 0;
+}
+
+static BOOL
+GetSecurityLogonSessionData(PSECURITY_LOGON_SESSION_DATA * ppSessionData)
+{
+ NTSTATUS Status = 0;
+ HANDLE TokenHandle;
+ TOKEN_STATISTICS Stats;
+ DWORD ReqLen;
+ BOOL Success;
+
+ if (!ppSessionData || !pLsaGetLogonSessionData)
+ return FALSE;
+ *ppSessionData = NULL;
+
+ Success = OpenProcessToken( GetCurrentProcess(), TOKEN_QUERY, &TokenHandle );
+ if ( !Success )
+ return FALSE;
+
+ Success = GetTokenInformation( TokenHandle, TokenStatistics, &Stats, sizeof(TOKEN_STATISTICS), &ReqLen );
+ CloseHandle( TokenHandle );
+ if ( !Success )
+ return FALSE;
+
+ Status = pLsaGetLogonSessionData( &Stats.AuthenticationId, ppSessionData );
+ if ( FAILED(Status) || !ppSessionData )
+ return FALSE;
+
+ return TRUE;
+}
+
+// IsKerberosLogon() does not validate whether or not there are valid tickets in the
+// cache. It validates whether or not it is reasonable to assume that if we
+// attempted to retrieve valid tickets we could do so. Microsoft does not
+// automatically renew expired tickets. Therefore, the cache could contain
+// expired or invalid tickets. Microsoft also caches the user's password
+// and will use it to retrieve new TGTs if the cache is empty and tickets
+// are requested.
+
+static BOOL
+IsKerberosLogon(VOID)
+{
+ PSECURITY_LOGON_SESSION_DATA pSessionData = NULL;
+ BOOL Success = FALSE;
+
+ if ( GetSecurityLogonSessionData(&pSessionData) ) {
+ if ( pSessionData->AuthenticationPackage.Buffer ) {
+ WCHAR buffer[256];
+ WCHAR *usBuffer;
+ int usLength;
+
+ Success = FALSE;
+ usBuffer = (pSessionData->AuthenticationPackage).Buffer;
+ usLength = (pSessionData->AuthenticationPackage).Length;
+ if (usLength < 256)
+ {
+ lstrcpyn (buffer, usBuffer, usLength);
+ lstrcat (buffer,L"");
+ if ( !lstrcmp(L"Kerberos",buffer) )
+ Success = TRUE;
+ }
+ }
+ pLsaFreeReturnBuffer(pSessionData);
+ }
+ return Success;
+}
+
+
+// This looks really ugly because it is. The result of IsKerberosLogon()
+// does not prove whether or not there are Kerberos tickets available to
+// be imported. Only the call to khm_krb5_ms2mit() which actually attempts
+// to import tickets can do that. However, calling khm_krb5_ms2mit() can
+// result in a TGS_REQ being sent to the KDC and since Leash_importable()
+// is called quite often we want to avoid this if at all possible.
+// Unfortunately, we have be shown at least one case in which the primary
+// authentication package was not Kerberos and yet there were Kerberos
+// tickets available. Therefore, if IsKerberosLogon() is not TRUE we
+// must call khm_krb5_ms2mit() but we still do not want to call it in a
+// tight loop so we cache the response and assume it won't change.
+long FAR
+Leash_importable(void)
+{
+ if ( IsKerberosLogon() )
+ return TRUE;
+ else {
+ static int response = -1;
+ if (response == -1) {
+ response = khm_krb5_ms2mit(0);
+ }
+ return response;
+ }
+}
+
+long FAR
+Leash_import(void)
+{
+ if ( khm_krb5_ms2mit(1) ) {
+ int lifetime;
+ lifetime = Leash_get_default_lifetime() / 5;
+ if (hKrb4 && Leash_get_default_use_krb4())
+ Leash_convert524(0);
+#ifndef NO_AFS
+ {
+ char c;
+ char *r;
+ char *t;
+ char cell[256];
+ char realm[256];
+ int i = 0;
+ int rcA = 0;
+
+ krb5_context ctx = 0;
+ krb5_error_code code = 0;
+ krb5_ccache cc = 0;
+ krb5_principal me = 0;
+
+ if ( !pkrb5_init_context )
+ goto cleanup;
+
+ code = pkrb5_init_context(&ctx);
+ if (code) goto cleanup;
+
+ code = pkrb5_cc_default(ctx, &cc);
+ if (code) goto cleanup;
+
+ if (code = pkrb5_cc_get_principal(ctx, cc, &me))
+ goto cleanup;
+
+ for ( r=realm, t=cell, i=0; i<krb5_princ_realm(ctx, me)->length; r++,t++,i++ ) {
+ c = krb5_princ_realm(ctx, me)->data[i];
+ *r = c;
+ *t = isupper(c) ? tolower(c) : c;
+ }
+ *r = *t = '\0';
+
+ rcA = Leash_afs_klog("afs", cell, realm, lifetime);
+ if (rcA)
+ rcA = Leash_afs_klog("afs", "", realm, lifetime);
+
+ cleanup:
+ if (me)
+ pkrb5_free_principal(ctx, me);
+ if (cc)
+ pkrb5_cc_close(ctx, cc);
+ if (ctx)
+ pkrb5_free_context(ctx);
+ }
+#endif /* NO_AFS */
+ return 1;
+ }
+ return 0;
+}
+
+long
+Leash_kdestroy(void)
+{
+ int k_errno;
+
+ Leash_afs_unlog();
+ khm_krb5_destroy_identity(NULL);
+
+ if (pdest_tkt != NULL)
+ {
+ k_errno = (*pdest_tkt)();
+ if (k_errno && (k_errno != RET_TKFIL))
+ return KRBERR(k_errno);
+ }
+
+ return 0;
+}
+
+int com_addr(void)
+{
+ long ipAddr;
+ char loc_addr[ADDR_SZ];
+ CREDENTIALS cred;
+ char service[40];
+ char instance[40];
+// char addr[40];
+ char realm[40];
+ struct in_addr LocAddr;
+ int k_errno;
+
+ if (pkrb_get_cred == NULL)
+ return(KSUCCESS);
+
+ k_errno = (*pkrb_get_cred)(service,instance,realm,&cred);
+ if (k_errno)
+ return KRBERR(k_errno);
+
+
+ while(1) {
+ ipAddr = (*pLocalHostAddr)();
+ LocAddr.s_addr = ipAddr;
+ strcpy(loc_addr,inet_ntoa(LocAddr));
+ if ( strcmp(cred.address,loc_addr) != 0) {
+ Leash_kdestroy ();
+ break;
+ }
+ break;
+ } // while()
+ return 0;
+}
+
+long FAR
+not_an_API_LeashFreeTicketList(TicketList** ticketList)
+{
+ TicketList* tempList = *ticketList, *killList;
+
+ //if (tempList == NULL)
+ //return -1;
+
+ while (tempList)
+ {
+ killList = tempList;
+
+ tempList = (TicketList*)tempList->next;
+ free(killList->theTicket);
+ if (killList->tktEncType)
+ free(killList->tktEncType);
+ if (killList->keyEncType)
+ free(killList->keyEncType);
+ if (killList->addrCount) {
+ int n;
+ for ( n=0; n<killList->addrCount; n++) {
+ if (killList->addrList[n])
+ free(killList->addrList[n]);
+ }
+ }
+ if (killList->addrList)
+ free(killList->addrList);
+ if (killList->name)
+ free(killList->name);
+ if (killList->inst)
+ free(killList->inst);
+ if (killList->realm)
+ free(killList->realm);
+ free(killList);
+ }
+
+ *ticketList = NULL;
+ return 0;
+}
+
+
+long FAR Leash_klist(HWND hlist, TICKETINFO FAR *ticketinfo)
+{
+ // Don't think this function will be used anymore - ADL 5-15-99
+ // Old fucntion to put tickets in a listbox control
+ // Use function "not_an_API_LeashKRB4GetTickets()" instead!
+ char pname[ANAME_SZ];
+ char pinst[INST_SZ];
+ char prealm[REALM_SZ];
+ char buf[MAX_K_NAME_SZ+40];
+ LPSTR cp;
+ long expdate;
+ int k_errno;
+ CREDENTIALS c;
+ int newtickets = 0;
+ int open = 0;
+
+ /*
+ * Since krb_get_tf_realm will return a ticket_file error,
+ * we will call tf_init and tf_close first to filter out
+ * things like no ticket file. Otherwise, the error that
+ * the user would see would be
+ * klist: can't find realm of ticket file: No ticket file (tf_util)
+ * instead of
+ * klist: No ticket file (tf_util)
+ */
+ if (ptf_init == NULL)
+ return(KSUCCESS);
+
+ if (hlist)
+ {
+ SendMessage(hlist, WM_SETREDRAW, FALSE, 0L);
+ SendMessage(hlist, LB_RESETCONTENT, 0, 0L);
+ }
+ com_addr();
+ newtickets = NO_TICKETS;
+
+ err_context = (LPSTR)"tktf1";
+
+ /* Open ticket file */
+ if (k_errno = (*ptf_init)((*ptkt_string)(), R_TKT_FIL))
+ {
+ goto cleanup;
+ }
+ /* Close ticket file */
+ (void) (*ptf_close)();
+ /*
+ * We must find the realm of the ticket file here before calling
+ * tf_init because since the realm of the ticket file is not
+ * really stored in the principal section of the file, the
+ * routine we use must itself call tf_init and tf_close.
+ */
+ err_context = "tf realm";
+ if ((k_errno = (*pkrb_get_tf_realm)((*ptkt_string)(), prealm)) != KSUCCESS)
+ {
+ goto cleanup;
+ }
+ /* Open ticket file */
+ err_context = "tf init";
+ if (k_errno = (*ptf_init)((*ptkt_string)(), R_TKT_FIL))
+ {
+ goto cleanup;
+ }
+
+ open = 1;
+ err_context = "tf pname";
+ /* Get principal name and instance */
+ if ((k_errno = (*ptf_get_pname)(pname)) || (k_errno = (*ptf_get_pinst)(pinst)))
+ {
+ goto cleanup;
+ }
+
+ /*
+ * You may think that this is the obvious place to get the
+ * realm of the ticket file, but it can't be done here as the
+ * routine to do this must open the ticket file. This is why
+ * it was done before tf_init.
+ */
+
+ wsprintf((LPSTR)ticketinfo->principal,"%s%s%s%s%s", (LPSTR)pname,
+ (LPSTR)(pinst[0] ? "." : ""), (LPSTR)pinst,
+ (LPSTR)(prealm[0] ? "@" : ""), (LPSTR)prealm);
+ newtickets = GOOD_TICKETS;
+
+ err_context = "tf cred";
+ while ((k_errno = (*ptf_get_cred)(&c)) == KSUCCESS)
+ {
+ expdate = c.issue_date + c.lifetime * 5L * 60L;
+
+ if (!lstrcmp((LPSTR)c.service, (LPSTR)TICKET_GRANTING_TICKET) && !lstrcmp((LPSTR)c.instance, (LPSTR)prealm))
+ {
+ ticketinfo->issue_date = c.issue_date;
+ ticketinfo->lifetime = c.lifetime * 5L * 60L;
+ ticketinfo->renew_till = 0;
+ }
+
+ cp = (LPSTR)buf;
+ lstrcpy(cp, (LPSTR)short_date(&c.issue_date));
+ cp += lstrlen(cp);
+ wsprintf(cp,"\t%s\t%s%s%s%s%s",
+ (LPSTR)short_date(&expdate), (LPSTR)c.service,
+ (LPSTR)(c.instance[0] ? "." : ""),
+ (LPSTR)c.instance, (LPSTR)(c.realm[0] ? "@" : ""),
+ (LPSTR) c.realm);
+ if (hlist)
+ SendMessage(hlist, LB_ADDSTRING, 0, (LONG)(LPSTR)buf);
+ } /* WHILE */
+
+cleanup:
+
+ if (open)
+ (*ptf_close)(); /* close ticket file */
+
+ if (hlist)
+ {
+ SendMessage(hlist, WM_SETREDRAW, TRUE, 0L);
+ InvalidateRect(hlist, NULL, TRUE);
+ UpdateWindow(hlist);
+ }
+ if (k_errno == EOF)
+ k_errno = 0;
+
+ /* XXX the if statement directly below was inserted to eliminate
+ an error 20 on Leash startup. The error occurs from an error
+ number thrown from krb_get_tf_realm. We believe this change
+ does not eliminate other errors, but it may. */
+
+ if (k_errno == RET_NOTKT)
+ k_errno = 0;
+
+ ticketinfo->btickets = newtickets;
+ if (k_errno != 0)
+ return KRBERR(k_errno);
+ return 0;
+}
+
+
+
+static BOOL CALLBACK
+EnumChildProc(HWND hwnd, LPARAM lParam)
+{
+ HWND * h = (HWND *)lParam;
+ *h = hwnd;
+ return FALSE;
+}
+
+
+static HWND
+FindFirstChildWindow(HWND parent)
+{
+ HWND hFirstChild = 0;
+ EnumChildWindows(parent, EnumChildProc, (LPARAM) &hFirstChild);
+ return hFirstChild;
+}
+
+void FAR
+not_an_API_Leash_AcquireInitialTicketsIfNeeded(krb5_context context, krb5_principal desiredKrb5Principal)
+{
+ krb5_error_code err;
+ LSH_DLGINFO_EX dlginfo;
+ HGLOBAL hData;
+ HWND hLeash;
+ HWND hForeground;
+ char *desiredName = 0;
+ char *desiredRealm = 0;
+ char *p;
+ TicketList * list = NULL;
+ TICKETINFO ticketinfo;
+ krb5_context ctx;
+ char newenv[256];
+ char * env = 0;
+ DWORD dwMsLsaImport = Leash_get_default_mslsa_import();
+
+ char loginenv[16];
+ BOOL prompt;
+
+ GetEnvironmentVariable("KERBEROSLOGIN_NEVER_PROMPT", loginenv, sizeof(loginenv));
+ prompt = (GetLastError() == ERROR_ENVVAR_NOT_FOUND);
+
+ if ( !prompt || !pkrb5_init_context )
+ return;
+
+ ctx = context;
+ env = getenv("KRB5CCNAME");
+ if ( !env && context ) {
+ sprintf(newenv,"KRB5CCNAME=%s",pkrb5_cc_default_name(ctx));
+ env = (char *)putenv(newenv);
+ }
+
+ not_an_API_LeashKRB5GetTickets(&ticketinfo,&list,&ctx);
+ not_an_API_LeashFreeTicketList(&list);
+
+ if ( ticketinfo.btickets != GOOD_TICKETS &&
+ Leash_get_default_mslsa_import() && Leash_importable() ) {
+ // We have the option of importing tickets from the MSLSA
+ // but should we? Do the tickets in the MSLSA cache belong
+ // to the default realm used by Leash? If so, import.
+ int import = 0;
+
+ if ( dwMsLsaImport == 1 ) { /* always import */
+ import = 1;
+ } else if ( dwMsLsaImport == 2 ) { /* import when realms match */
+ krb5_error_code code;
+ krb5_ccache mslsa_ccache=0;
+ krb5_principal princ = 0;
+ char ms_realm[128] = "", *def_realm = 0, *r;
+ int i;
+
+ if (code = pkrb5_cc_resolve(ctx, "MSLSA:", &mslsa_ccache))
+ goto cleanup;
+
+ if (code = pkrb5_cc_get_principal(ctx, mslsa_ccache, &princ))
+ goto cleanup;
+
+ for ( r=ms_realm, i=0; i<krb5_princ_realm(ctx, princ)->length; r++, i++ ) {
+ *r = krb5_princ_realm(ctx, princ)->data[i];
+ }
+ *r = '\0';
+
+ if (code = pkrb5_get_default_realm(ctx, &def_realm))
+ goto cleanup;
+
+ import = !strcmp(def_realm, ms_realm);
+
+ cleanup:
+ if (def_realm)
+ pkrb5_free_default_realm(ctx, def_realm);
+
+ if (princ)
+ pkrb5_free_principal(ctx, princ);
+
+ if (mslsa_ccache)
+ pkrb5_cc_close(ctx, mslsa_ccache);
+ }
+
+ if ( import ) {
+ Leash_import();
+
+ not_an_API_LeashKRB5GetTickets(&ticketinfo,&list,&ctx);
+ not_an_API_LeashFreeTicketList(&list);
+ }
+ }
+
+ if ( ticketinfo.btickets != GOOD_TICKETS )
+ {
+ /* do we want a specific client principal? */
+ if (desiredKrb5Principal != NULL) {
+ err = pkrb5_unparse_name (ctx, desiredKrb5Principal, &desiredName);
+ if (!err) {
+ dlginfo.username = desiredName;
+ for (p = desiredName; *p && *p != '@'; p++);
+ if ( *p == '@' ) {
+ *p = '\0';
+ desiredRealm = dlginfo.realm = ++p;
+ }
+ }
+ }
+
+#ifdef COMMENT
+ memset(&dlginfo, 0, sizeof(LSH_DLGINFO_EX));
+ dlginfo.size = sizeof(LSH_DLGINFO_EX);
+ dlginfo.dlgtype = DLGTYPE_PASSWD;
+ dlginfo.title = "Obtain Kerberos Ticket Getting Tickets";
+ dlginfo.use_defaults = 1;
+
+ err = Leash_kinit_dlg_ex(NULL, &dlginfo);
+#else
+ /* construct a marshalling of data
+ * <title><principal><realm>
+ * then send to Leash
+ */
+
+ hData = GlobalAlloc( GHND, 4096 );
+ hForeground = GetForegroundWindow();
+ hLeash = FindWindow("LEASH.0WNDCLASS", NULL);
+ SetForegroundWindow(hLeash);
+ hLeash = FindFirstChildWindow(hLeash);
+ if ( hData && hLeash ) {
+ char * strs = GlobalLock( hData );
+ if ( strs ) {
+ strcpy(strs, "Obtain Kerberos Ticket Getting Tickets");
+ strs += strlen(strs) + 1;
+ if ( desiredName ) {
+ strcpy(strs, desiredName);
+ strs += strlen(strs) + 1;
+ if (desiredRealm) {
+ strcpy(strs, desiredRealm);
+ strs += strlen(strs) + 1;
+ }
+ } else {
+ *strs = 0;
+ strs++;
+ *strs = 0;
+ strs++;
+ }
+
+ GlobalUnlock( hData );
+ SendMessage(hLeash, 32809, 0, (LPARAM) hData);
+ }
+
+ GlobalFree( hData );
+ }
+ SetForegroundWindow(hForeground);
+#endif
+ if (desiredName != NULL)
+ pkrb5_free_unparsed_name(ctx, desiredName);
+ }
+
+ if ( !env && context )
+ putenv("KRB5CCNAME=");
+
+ if ( !context )
+ pkrb5_free_context(ctx);
+}
diff --git a/src/windows/identity/plugins/krb5/krbconfig.csv b/src/windows/identity/plugins/krb5/krbconfig.csv
new file mode 100644
index 0000000..c577eec
--- /dev/null
+++ b/src/windows/identity/plugins/krb5/krbconfig.csv
@@ -0,0 +1,34 @@
+Name,Type,Value,Description
+Krb5Cred,KC_SPACE,0,Kerberos V Credentials Provider
+ Module,KC_STRING,MITKrb5,
+ Description,KC_STRING,Kerberos V Credentials Provider,
+ Type,KC_INT32,1,
+ Flags,KC_INT32,0,
+ Parameters,KC_SPACE,0,Parameters for KrbCred
+ CreateMissingConfig,KC_INT32,0,Create missing configuration files
+ MsLsaImport,KC_INT32,2,Automatically import MSLSA credentials
+ AutoRenewTickets,KC_INT32,1,Automatically renew expiring tickets
+ DefaultLifetime,KC_INT32,36000,Default ticket lifetime
+ MaxLifetime,KC_INT32,86400,Maximum lifetime
+ MinLifetime,KC_INT32,60,Minimum lifetime
+ Forwardable,KC_INT32,1,Obtain forwardable tickets (boolean)
+ Proxiable,KC_INT32,0,Obtain proxiable tickets (boolean)
+ Addressless,KC_INT32,1,Obtain addressless tickets (boolean)
+ Renewable,KC_INT32,1,Obtain renewable tickets (boolean)
+ DefaultRenewLifetime,KC_INT32,604800,Default renewable lifetime
+ MaxRenewLifetime,KC_INT32,2592000,Maximum renewable lifetime
+ MinRenewLifetime,KC_INT32,60,Maximum renewable lifetime
+ LRURealms,KC_STRING,,
+ LRUPrincipals,KC_STRING,,
+ PromptCache,KC_SPACE,0,Cache of prompts (only per identity)
+ Name,KC_STRING,,
+ Banner,KC_STRING,,
+ PromptCount,KC_INT32,0,
+ (n),KC_SPACE,0,Parameters for each prompt
+ Prompt,KC_STRING,,
+ Type,KC_INT32,0,
+ Flags,KC_INT32,0,
+ (n),KC_ENDSPACE,0,
+ PromptCache,KC_ENDSPACE,0,
+ Parameters,KC_ENDSPACE,0,
+Krb5Cred,KC_ENDSPACE,0,
diff --git a/src/windows/identity/plugins/krb5/krbcred.h b/src/windows/identity/plugins/krb5/krbcred.h
new file mode 100644
index 0000000..08978f1
--- /dev/null
+++ b/src/windows/identity/plugins/krb5/krbcred.h
@@ -0,0 +1,182 @@
+/*
+ * Copyright (c) 2004 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#ifndef __KHIMAIRA_KRBAFSCRED_H
+#define __KHIMAIRA_KRBAFSCRED_H
+
+#include<windows.h>
+
+/* While we generally pull resources out of hResModule, the message
+ strings for all the languages are kept in the main DLL. */
+#define KHERR_HMODULE hInstance
+#define KHERR_FACILITY k5_facility
+#define KHERR_FACILITY_ID 64
+
+#include<khdefs.h>
+#include<kcreddb.h>
+#include<kmm.h>
+#include<kconfig.h>
+#include<khuidefs.h>
+#include<kherr.h>
+
+#include<krb5funcs.h>
+#include<krb5common.h>
+#include<errorfuncs.h>
+#include<dynimport.h>
+
+#include<langres.h>
+#include<datarep.h>
+#include<krb5_msgs.h>
+
+#define TYPENAME_ENCTYPE L"EncType"
+#define TYPENAME_ADDR_LIST L"AddrList"
+#define TYPENAME_KRB5_FLAGS L"Krb5Flags"
+
+#define ATTRNAME_KEY_ENCTYPE L"KeyEncType"
+#define ATTRNAME_TKT_ENCTYPE L"TktEncType"
+#define ATTRNAME_ADDR_LIST L"AddrList"
+#define ATTRNAME_KRB5_FLAGS L"Krb5Flags"
+#define ATTRNAME_KRB5_CCNAME L"Krb5CCName"
+
+void init_krb();
+void exit_krb();
+KHMEXP khm_int32 KHMAPI init_module(kmm_module h_module);
+KHMEXP khm_int32 KHMAPI exit_module(kmm_module h_module);
+
+/* globals */
+extern kmm_module h_khModule;
+extern HMODULE hResModule;
+extern HINSTANCE hInstance;
+extern const wchar_t * k5_facility;
+
+extern khm_int32 type_id_enctype;
+extern khm_int32 type_id_addr_list;
+extern khm_int32 type_id_krb5_flags;
+
+extern khm_int32 attr_id_key_enctype;
+extern khm_int32 attr_id_tkt_enctype;
+extern khm_int32 attr_id_addr_list;
+extern khm_int32 attr_id_krb5_flags;
+extern khm_int32 attr_id_krb5_ccname;
+
+/* Configuration spaces */
+#define CSNAME_KRB5CRED L"Krb5Cred"
+#define CSNAME_PARAMS L"Parameters"
+#define CSNAME_PROMPTCACHE L"PromptCache"
+
+/* plugin constants */
+#define KRB5_PLUGIN_NAME L"Krb5Cred"
+
+#define KRB5_CREDTYPE_NAME L"Krb5Cred"
+
+extern khm_handle csp_plugins;
+extern khm_handle csp_krbcred;
+extern khm_handle csp_params;
+
+extern kconf_schema schema_krbconfig[];
+
+/* other globals */
+extern khm_int32 credtype_id_krb5;
+
+extern khm_boolean krb5_initialized;
+
+extern khm_handle krb5_credset;
+
+extern khm_handle k5_sub;
+
+extern krb5_context k5_identpro_ctx;
+
+extern BOOL is_k5_identpro;
+
+/* plugin callbacks */
+khm_int32 KHMAPI k5_msg_callback(khm_int32 msg_type, khm_int32 msg_subtype, khm_ui_4 uparam, void * vparam);
+
+/* kinit fiber */
+typedef struct _fiber_job_t {
+ int command;
+
+ khui_new_creds * nc;
+ khui_new_creds_by_type * nct;
+ HWND dialog;
+
+ khm_handle identity;
+ char * principal;
+ char * password;
+ char * ccache;
+ krb5_deltat lifetime;
+ DWORD forwardable;
+ DWORD proxiable;
+ DWORD renewable;
+ krb5_deltat renew_life;
+ DWORD addressless;
+ DWORD publicIP;
+
+ int code;
+ int state;
+ int prompt_set;
+
+ BOOL null_password;
+} fiber_job;
+
+extern fiber_job g_fjob; /* global fiber job object */
+
+#define FIBER_CMD_KINIT 1
+#define FIBER_CMD_CANCEL 2
+#define FIBER_CMD_CONTINUE 3
+
+#define FIBER_STATE_NONE 0
+#define FIBER_STATE_KINIT 1
+
+void
+k5_pp_begin(khui_property_sheet * s);
+
+void
+k5_pp_end(khui_property_sheet * s);
+
+khm_int32 KHMAPI
+k5_msg_cred_dialog(khm_int32 msg_type,
+ khm_int32 msg_subtype,
+ khm_ui_4 uparam,
+ void * vparam);
+
+khm_int32 KHMAPI
+k5_msg_ident(khm_int32 msg_type,
+ khm_int32 msg_subtype,
+ khm_ui_4 uparam,
+ void * vparam);
+
+int
+k5_get_realm_from_nc(khui_new_creds * nc,
+ wchar_t * buf,
+ khm_size cch_buf);
+
+void
+k5_register_config_panels(void);
+
+void
+k5_unregister_config_panels(void);
+
+#endif
diff --git a/src/windows/identity/plugins/krb5/lang/en_us/langres.rc b/src/windows/identity/plugins/krb5/lang/en_us/langres.rc
new file mode 100644
index 0000000..087b93e
--- /dev/null
+++ b/src/windows/identity/plugins/krb5/lang/en_us/langres.rc
@@ -0,0 +1,406 @@
+// Microsoft Visual C++ generated resource script.
+//
+#include "..\..\langres.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "afxres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// English (U.S.) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+#ifdef _WIN32
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+#pragma code_page(1252)
+#endif //_WIN32
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE
+BEGIN
+ "..\\..\\langres.h\0"
+END
+
+2 TEXTINCLUDE
+BEGIN
+ "#include ""afxres.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+IDD_NC_KRB5 DIALOGEX 0, 0, 300, 166
+STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD | WS_CLIPSIBLINGS |
+ WS_CLIPCHILDREN
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg", 400, 0, 0x1
+BEGIN
+ LTEXT "Realm",IDC_STATIC,7,25,52,13
+ COMBOBOX IDC_NCK5_REALM,60,25,233,17,CBS_DROPDOWN |
+ CBS_AUTOHSCROLL | CBS_SORT | WS_VSCROLL | WS_TABSTOP
+ PUSHBUTTON "Specify &additional realms ...",IDC_NCK5_ADD_REALMS,181,
+ 43,112,16,BS_NOTIFY | WS_DISABLED
+ LTEXT "&Lifetime",IDC_STATIC,7,67,61,12
+ EDITTEXT IDC_NCK5_LIFETIME_EDIT,85,67,107,12,ES_AUTOHSCROLL
+ CONTROL "&Renewable for",IDC_NCK5_RENEWABLE,"Button",
+ BS_AUTOCHECKBOX | BS_NOTIFY | WS_TABSTOP,7,87,64,12
+ EDITTEXT IDC_NCK5_RENEW_EDIT,85,87,108,12,ES_AUTOHSCROLL
+ CONTROL "Can be &forwarded to other machines",
+ IDC_NCK5_FORWARDABLE,"Button",BS_AUTOCHECKBOX |
+ BS_NOTIFY | WS_TABSTOP,7,107,132,12
+ CONTROL "Kerberos 5 Ticket Options",IDC_STATIC,"Static",
+ SS_LEFTNOWORDWRAP | SS_SUNKEN | WS_GROUP,7,7,286,11
+END
+
+IDD_PP_KRB5C DIALOGEX 0, 0, 235, 156
+STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_DISABLED | WS_CAPTION
+CAPTION "Kerberos 5"
+FONT 8, "MS Shell Dlg", 0, 0, 0x0
+BEGIN
+ LTEXT "Name",IDC_STATIC,7,7,19,8
+ LTEXT "Valid till",IDC_STATIC,7,39,24,8
+ LTEXT "Renewable till",IDC_STATIC,7,55,45,12
+ CONTROL "Renewable",IDC_PPK5_CRENEW,"Button",BS_AUTOCHECKBOX |
+ WS_DISABLED | WS_TABSTOP,31,125,51,10
+ CONTROL "Forwardable",IDC_PPK5_CFORWARD,"Button",BS_AUTOCHECKBOX |
+ WS_DISABLED | WS_TABSTOP,91,125,56,10
+ CONTROL "Proxiable",IDC_PPK5_CPROXY,"Button",BS_AUTOCHECKBOX |
+ WS_DISABLED | WS_TABSTOP,156,125,45,10
+ LTEXT "Issued on",IDC_STATIC,7,23,32,8
+ GROUPBOX "Ticket flags",IDC_STATIC,7,108,221,41
+ LTEXT "Static",IDC_PPK5_NAME,72,7,156,12,NOT WS_GROUP,
+ WS_EX_CLIENTEDGE
+ LTEXT "Static",IDC_PPK5_ISSUE,72,23,156,12,NOT WS_GROUP,
+ WS_EX_CLIENTEDGE
+ LTEXT "Static",IDC_PPK5_VALID,72,39,156,12,NOT WS_GROUP,
+ WS_EX_CLIENTEDGE
+ LTEXT "Static",IDC_PPK5_RENEW,72,55,156,12,NOT WS_GROUP,
+ WS_EX_CLIENTEDGE
+END
+
+IDD_PP_KRB5 DIALOGEX 0, 0, 235, 156
+STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_DISABLED | WS_CAPTION
+CAPTION "Kerberos 5"
+FONT 8, "MS Shell Dlg", 0, 0, 0x0
+BEGIN
+ LTEXT "Default realm",IDC_STATIC,7,7,44,8
+ LTEXT "Default lifetime",IDC_STATIC,7,22,49,8
+ LTEXT "Minimum lifetime",IDC_STATIC,7,37,52,8
+ LTEXT "Maximum lifetime",IDC_STATIC,7,52,55,8
+ LTEXT "Renewable lifetime",IDC_STATIC,7,67,61,8
+ LTEXT "Min. Renewable lifetime",IDC_STATIC,7,82,76,8
+ LTEXT "Max. Renewable lifetime",IDC_STATIC,7,97,79,8
+ GROUPBOX "Default ticket flags",IDC_STATIC,7,113,221,36
+ CONTROL "Proxiable",IDC_CHECK2,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,160,129,45,10
+ CONTROL "Renewable",IDC_CHECK4,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,23,129,51,10
+ CONTROL "Forwardable",IDC_CHECK5,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,89,129,56,10
+ LTEXT "ATHENA.MIT.EDU",IDC_STATIC,95,7,133,11,0,
+ WS_EX_CLIENTEDGE
+ LTEXT "10 hours",IDC_STATIC,95,22,133,11,0,WS_EX_CLIENTEDGE
+ LTEXT "1 minute",IDC_STATIC,95,37,133,11,0,WS_EX_CLIENTEDGE
+ LTEXT "7 days",IDC_STATIC,95,52,133,11,0,WS_EX_CLIENTEDGE
+ LTEXT "7 days",IDC_STATIC,95,67,133,11,0,WS_EX_CLIENTEDGE
+ LTEXT "1 minute",IDC_STATIC,95,82,133,11,0,WS_EX_CLIENTEDGE
+ LTEXT "21 days",IDC_STATIC,95,97,133,11,0,WS_EX_CLIENTEDGE
+END
+
+IDD_CONFIG DIALOGEX 0, 0, 255, 182
+STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_SYSMENU
+FONT 8, "MS Shell Dlg", 400, 0, 0x1
+BEGIN
+ LTEXT "Default Realm",IDC_CFG_LBL_REALM,13,9,46,8
+ COMBOBOX IDC_CFG_DEFREALM,76,7,166,30,CBS_DROPDOWN | CBS_SORT |
+ WS_VSCROLL | WS_TABSTOP
+ PUSHBUTTON "Configure Realms ...",IDC_CFG_CFGREALMS,76,25,84,14
+ GROUPBOX "Keberos Configuration File",IDC_CFG_CFGFILEGRP,7,57,241,
+ 48
+ LTEXT "Location",IDC_CFG_LBL_CFGFILE,13,71,28,8
+ EDITTEXT IDC_CFG_CFGFILE,76,68,119,14,ES_AUTOHSCROLL
+ PUSHBUTTON "Browse...",IDC_CFG_BROWSE,198,68,44,14
+ CONTROL "Create file if missing",IDC_CFG_CREATECONFIG,"Button",
+ BS_AUTOCHECKBOX | WS_TABSTOP,76,89,80,10
+ GROUPBOX "Windows® Options",IDC_CFG_WINGRP,7,110,241,65
+ LTEXT "Hostname",IDC_CFG_LBL_HOSTNAME,13,123,33,8
+ EDITTEXT IDC_CFG_HOSTNAME,76,120,166,14,ES_AUTOHSCROLL |
+ ES_READONLY
+ LTEXT "Domain",IDC_CFG_LBL_DOMAIN,13,141,24,8
+ EDITTEXT IDC_CFG_DOMAIN,76,138,166,14,ES_AUTOHSCROLL |
+ ES_READONLY
+ LTEXT "Import tickets",IDC_LBL_IMPORT,13,158,45,8
+ COMBOBOX IDC_CFG_IMPORT,76,156,166,30,CBS_DROPDOWNLIST | CBS_SORT |
+ WS_VSCROLL | WS_TABSTOP
+END
+
+IDD_CFG_REALMS DIALOGEX 0, 0, 255, 182
+STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_SYSMENU
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg", 400, 0, 0x1
+BEGIN
+ CONTROL "",IDC_CFG_REALMS,"SysListView32",LVS_ALIGNLEFT |
+ WS_BORDER | WS_TABSTOP,7,19,81,148
+ GROUPBOX "Servers",IDC_CFG_SERVERSGRP,93,7,155,91
+ GROUPBOX "Domain/Hostname mappings",IDC_CFG_DOMAINGRP,93,101,155,
+ 74
+ CONTROL "",IDC_LIST3,"SysListView32",LVS_ALIGNLEFT | WS_BORDER |
+ WS_TABSTOP,99,19,143,72
+ CONTROL "",IDC_LIST4,"SysListView32",LVS_ALIGNLEFT | WS_BORDER |
+ WS_TABSTOP,99,111,143,56
+END
+
+IDD_CFG_IDS_TAB DIALOGEX 0, 0, 235, 151
+STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_SYSMENU
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg", 400, 0, 0x1
+BEGIN
+ LTEXT "Ticket lifetime",IDC_CFG_LBL_DEFLIFE,7,10,44,8
+ EDITTEXT IDC_CFG_DEFLIFE,91,7,137,14,ES_AUTOHSCROLL
+ LTEXT "Ticket renewable lifetime",IDC_CFG_LBL_DEFRLIFE,7,29,80,
+ 8
+ EDITTEXT IDC_CFG_DEFRLIFE,91,26,137,14,ES_AUTOHSCROLL
+ GROUPBOX "Ticket lifetime range",IDC_CFG_LIFEGRP,7,43,221,49
+ LTEXT "Minimum",IDC_STATIC,13,56,28,8
+ EDITTEXT IDC_CFG_LRNG_MIN,91,53,131,14,ES_AUTOHSCROLL
+ LTEXT "Maximum",IDC_STATIC,13,75,30,8
+ EDITTEXT IDC_CFG_LRNG_MAX,91,72,131,14,ES_AUTOHSCROLL
+ GROUPBOX "Ticket renewable lifetime range",IDC_STATIC,7,95,221,49
+ LTEXT "Minimum",IDC_STATIC,13,108,28,8
+ EDITTEXT IDC_CFG_RLRNG_MIN,91,105,131,14,ES_AUTOHSCROLL
+ LTEXT "Maximum",IDC_STATIC,13,128,30,8
+ EDITTEXT IDC_CFG_RLRNG_MAX,91,125,131,14,ES_AUTOHSCROLL
+END
+
+IDD_CFG_ID_TAB DIALOGEX 0, 0, 235, 151
+STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_SYSMENU
+FONT 8, "MS Shell Dlg", 400, 0, 0x1
+BEGIN
+ LTEXT "Ticket lifetime",IDC_CFG_LBL_DEFLIFE,7,10,44,8
+ EDITTEXT IDC_CFG_DEFLIFE,91,7,137,14,ES_AUTOHSCROLL
+ LTEXT "Ticket renewable lifetime",IDC_CFG_LBL_DEFRLIFE,7,29,80,
+ 8
+ EDITTEXT IDC_CFG_DEFRLIFE,91,26,137,14,ES_AUTOHSCROLL
+ LTEXT "Credentials cache",IDC_STATIC,7,63,58,8
+ EDITTEXT IDC_CFG_CCACHE,91,60,137,14,ES_AUTOHSCROLL
+END
+
+IDD_NC_KRB5_PASSWORD DIALOGEX 0, 0, 300, 166
+STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_SYSMENU
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg", 400, 0, 0x1
+BEGIN
+ CONTROL "Kerberos 5 Change Password Options",IDC_STATIC,"Static",
+ SS_LEFTNOWORDWRAP | SS_SUNKEN | WS_GROUP,7,7,286,11
+ LTEXT "Realm",IDC_STATIC,7,25,52,13
+ COMBOBOX IDC_NCK5_REALM,60,25,233,17,CBS_DROPDOWN |
+ CBS_AUTOHSCROLL | CBS_SORT | WS_VSCROLL | WS_TABSTOP
+ PUSHBUTTON "Specify &additional realms ...",IDC_NCK5_ADD_REALMS,181,
+ 43,112,16,BS_NOTIFY | WS_DISABLED
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// DESIGNINFO
+//
+
+#ifdef APSTUDIO_INVOKED
+GUIDELINES DESIGNINFO
+BEGIN
+ IDD_NC_KRB5, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 293
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 159
+ END
+
+ IDD_PP_KRB5C, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 228
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 149
+ END
+
+ IDD_PP_KRB5, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 228
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 149
+ END
+
+ IDD_CONFIG, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 248
+ VERTGUIDE, 13
+ VERTGUIDE, 76
+ VERTGUIDE, 242
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 175
+ END
+
+ IDD_CFG_REALMS, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 248
+ VERTGUIDE, 93
+ VERTGUIDE, 99
+ VERTGUIDE, 242
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 175
+ HORZGUIDE, 19
+ HORZGUIDE, 167
+ END
+
+ IDD_CFG_IDS_TAB, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 228
+ VERTGUIDE, 13
+ VERTGUIDE, 91
+ VERTGUIDE, 222
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 144
+ END
+
+ IDD_CFG_ID_TAB, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 228
+ VERTGUIDE, 91
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 144
+ END
+
+ IDD_NC_KRB5_PASSWORD, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 293
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 159
+ END
+END
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// String Table
+//
+
+STRINGTABLE
+BEGIN
+ IDS_UNK_ADDR_FMT "Unknown address type %d"
+ IDS_KRB5_CREDTEXT_0 "<p><a id=""SwitchPanel"" param=""Krb5Cred""><b>Krb5</b></a><tab>: Creds for realm %s</p>"
+ IDS_KRB5_CCNAME_SHORT_DESC "Krb5 CCache"
+ IDS_KEY_ENCTYPE_SHORT_DESC "Key EncType"
+ IDS_TKT_ENCTYPE_SHORT_DESC "Ticket EncType"
+ IDS_KEY_ENCTYPE_LONG_DESC "Session Key Encryption Type"
+ IDS_TKT_ENCTYPE_LONG_DESC "Ticket Encryption Type"
+ IDS_ADDR_LIST_SHORT_DESC "Addresses"
+ IDS_ADDR_LIST_LONG_DESC "Address List"
+ IDS_ETYPE_NULL "NULL"
+ IDS_ETYPE_DES_CBC_CRC "DES-CBC-CRC"
+END
+
+STRINGTABLE
+BEGIN
+ IDS_ETYPE_DES_CBC_MD4 "DES-CBC-MD4"
+ IDS_ETYPE_DES_CBC_MD5 "DES-CBC-MD5"
+ IDS_ETYPE_DES_CBC_RAW "DES-CBC-RAW"
+ IDS_ETYPE_DES3_CBC_SHA "DES3-CBC-SHA"
+ IDS_ETYPE_DES3_CBC_RAW "DES3-CBC-RAW"
+ IDS_ETYPE_DES_HMAC_SHA1 "DES-HMAC-SHA1"
+ IDS_ETYPE_DES3_CBC_SHA1 "DES3-CBC-SHA1"
+ IDS_ETYPE_AES128_CTS_HMAC_SHA1_96 "AES128_CTS-HMAC-SHA1_96"
+ IDS_ETYPE_AES256_CTS_HMAC_SHA1_96 "AES256_CTS-HMAC-SHA1_96"
+ IDS_ETYPE_ARCFOUR_HMAC "RC4-HMAC-NT"
+ IDS_ETYPE_ARCFOUR_HMAC_EXP "RC4-HMAC-NT-EXP"
+ IDS_ETYPE_UNKNOWN "(Unknown)"
+ IDS_ETYPE_LOCAL_DES3_HMAC_SHA1 "LOCAL-DES3-HMAC-SHA1"
+ IDS_ETYPE_LOCAL_RC4_MD4 "LOCAL-RC4-MD4"
+ IDS_KRB5_SHORT_DESC "Kerberos 5"
+ IDS_KRB5_LONG_DESC "Kerberos 5 tickets"
+END
+
+STRINGTABLE
+BEGIN
+ IDS_KRB4_SHORT_DESC "Kerberos 4"
+ IDS_KRB4_LONG_DESC "Kerberos 4 tickets"
+ IDS_KRB5_FLAGS_SHORT_DESC "Flags"
+ IDS_RENEW_TILL_SHORT_DESC "Renew Till"
+ IDS_RENEW_TILL_LONG_DESC "Renewable Till"
+ IDS_RENEW_FOR_SHORT_DESC "Renew for"
+ IDS_RENEW_FOR_LONG_DESC "Renewable for"
+ IDS_KRB5_CCNAME_LONG_DESC "Krb5 Primary Credentials Cache"
+ IDS_NC_USERNAME "Username"
+ IDS_NC_REALM "Realm"
+ IDS_KRB5_WARNING "Kerberos 5 Warning"
+ IDS_K5ERR_NAME_EXPIRED "<p><a id=""SwitchPanel"" param=""Krb5Cred""><b>Krb5</b></a><tab>: The selected principal name has expired.</p><p><tab> Please contact your system administrator.</p>"
+ IDS_K5ERR_KEY_EXPIRED "<p><a id=""SwitchPanel"" param=""Krb5Cred""><b>Krb5</b></a><tab>: The password for the selected identity has expired.</p><p><tab> Click <a id=""Krb5Cred:Passwd"">here</a> to change the password</p>"
+ IDS_KRB5_WARN_FMT "Kerberos 5: %s\n\n%s"
+ IDS_K5ERR_FMT "<p><a id=""SwitchPanel"" param=""Krb5Cred""><b>Krb5</b></a><tag>: %s</p>"
+ IDS_K5CFG_SHORT_DESC "Kerberos 5"
+END
+
+STRINGTABLE
+BEGIN
+ IDS_K5CFG_LONG_DESC "Kerberos 5 Configuration"
+ IDS_K5RLM_SHORT_DESC "Realms"
+ IDS_K5RLM_LONG_DESC "Kerberos Realm Configuration"
+ IDS_K5CFG_IDS_SHORT_DESC "Kerberos 5"
+ IDS_K5CFG_IDS_LONG_DESC "Kerberos 5 options for all identities"
+ IDS_K5CFG_ID_SHORT_DESC "Kerberos 5"
+ IDS_K5CFG_ID_LONG_DESC "Kerberos 5 options for this identity"
+ IDS_PLUGIN_DESC "Kerberos 5 Credentials Provider"
+ IDS_NC_PWD_BANNER "Changing Kerberos 5 Password"
+ IDS_NC_PWD_PWD "Current Password"
+ IDS_NC_PWD_NPWD "New Password"
+ IDS_NC_PWD_NPWD_AGAIN "New Password again"
+ IDS_KRB5_CREDTEXT_P0 "<p><a id=""SwitchPanel"" param=""Krb5Cred""><b>Krb5</b></a><tab>: Changing password for %s</p>"
+ IDS_K5CFG_IMPORT_OPTIONS
+ "Never\000Always\000Only when the principal name matches\000 \000"
+END
+
+#endif // English (U.S.) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/src/windows/identity/plugins/krb5/lang/krb5_msgs.mc b/src/windows/identity/plugins/krb5/lang/krb5_msgs.mc
new file mode 100644
index 0000000..22f973f
--- /dev/null
+++ b/src/windows/identity/plugins/krb5/lang/krb5_msgs.mc
@@ -0,0 +1,151 @@
+; // ** krb5_msgs.mc
+
+; /* Since .mc files can contain strings from any language, we define
+; all our messages in one file in the /lang/ directory instead of
+; language specific subdirectories. */
+
+; /* The type is set to (wchar_t *) because that's what we will be
+; feeding kherr_report() function. */
+
+; // MessageIdTypedef=LPWSTR
+
+; /* Severity values as defined in the message definition file are
+; currently ignored. */
+
+SeverityNames=(
+ Success=0x0
+)
+
+LanguageNames=(
+ English=0x409:MSG_ENU
+)
+
+OutputBase=16
+
+; /* Actual messages start here */
+
+MessageId=1
+Severity=Success
+SymbolicName=MSG_INITIAL
+Language=English
+Initial placeholder message
+.
+
+MessageId=
+SymbolicName=MSG_CTX_INITAL_CREDS
+Language=English
+Obtaining initial Krb5 credentials
+.
+
+MessageId=
+SymbolicName=MSG_CTX_RENEW_CREDS
+Language=English
+Renewing Krb5 credentials
+.
+
+MessageId=
+SymbolicName=MSG_ERR_UNKNOWN
+Language=English
+An unknown error has occurred.
+.
+
+MessageId=
+SymbolicName=MSG_ERR_PR_UNKNOWN
+Language=English
+You have entered an unknown username/instance/realm combination.
+.
+
+MessageId=
+SymbolicName=MSG_ERR_TKFIL
+Language=English
+The tickets could not be accessed from the memory location where they were stored.
+.
+
+MessageId=
+SymbolicName=MSG_ERR_S_TKFIL
+Language=English
+This may be due to a problem with the memory where your tickets are stored. Restarting your computer might be worth a try.
+.
+
+MessageId=
+SymbolicName=MSG_ERR_CLOCKSKEW
+Language=English
+Your computer's clock is out of sync with the Kerberos server.
+.
+
+MessageId=
+SymbolicName=MSG_ERR_S_CLOCKSKEW
+Language=English
+Synchronize your clock withe the Kerberos server.
+.
+
+MessageId=
+SymbolicName=MSG_ERR_KDC_CONTACT
+Language=English
+Cannot contact the Kerberos server for the requested realm.
+.
+
+MessageId=
+SymbolicName=MSG_ERR_INSECURE_PW
+Language=English
+You have entered an insecure or weak password.
+.
+
+MessageId=
+SymbolicName=MSG_ERR_NO_IDENTITY
+Language=English
+There were no identities for which to renew credentials.
+.
+
+MessageId=
+SymbolicName=MSG_CTX_PASSWD
+Language=English
+Changing Kerberos 5 Password
+.
+
+MessageId=
+SymbolicName=MSG_PWD_UNKNOWN
+Language=English
+Unknown error
+.
+
+MessageId=
+SymbolicName=MSG_PWD_NOT_SAME
+Language=English
+The new passwords are not the same.
+.
+
+MessageId=
+SymbolicName=MSG_PWD_S_NOT_SAME
+Language=English
+The new password is asked for twice to protect against a mistake when setting the new password. Both instances of the new password must be the same. Please correct this and try again.
+.
+
+MessageId=
+SymbolicName=MSG_PWD_SAME
+Language=English
+The new and the old passwords are the same.
+.
+
+MessageId=
+SymbolicName=MSG_PWD_S_SAME
+Language=English
+Please type a new password to continue.
+.
+
+MessageId=
+SymbolicName=MSG_PWD_NO_IDENTITY
+Language=English
+There are no identities selected.
+.
+
+MessageId=
+SymbolicName=MSG_PWD_S_NO_IDENTITY
+Language=English
+Please select an identity to change the password.
+.
+
+MessageId=
+SymbolicName=MSG_
+Language=English
+.
diff --git a/src/windows/identity/plugins/krb5/langres.h b/src/windows/identity/plugins/krb5/langres.h
new file mode 100644
index 0000000..87f74f5
--- /dev/null
+++ b/src/windows/identity/plugins/krb5/langres.h
@@ -0,0 +1,127 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by D:\work\khimaira\src\plugins\krb5\lang\en_us\langres.rc
+//
+#define IDS_UNK_ADDR_FMT 101
+#define IDD_NC_KRB5 102
+#define IDS_KRB5_CREDTEXT_0 102
+#define IDS_KRB5_CCNAME_SHORT_DESC 103
+#define IDS_KEY_ENCTYPE_SHORT_DESC 104
+#define IDD_CONFIG 104
+#define IDS_TKT_ENCTYPE_SHORT_DESC 105
+#define IDD_CFG_REALMS 105
+#define IDS_KEY_ENCTYPE_LONG_DESC 106
+#define IDD_CFG_IDS_TAB 106
+#define IDS_TKT_ENCTYPE_LONG_DESC 107
+#define IDD_PP_KRB5C 107
+#define IDS_ADDR_LIST_SHORT_DESC 108
+#define IDD_PP_KRB5 108
+#define IDS_ADDR_LIST_LONG_DESC 109
+#define IDD_CFG_ID_TAB 109
+#define IDS_ETYPE_NULL 110
+#define IDD_NC_KRB5_PASSWORD 110
+#define IDS_ETYPE_DES_CBC_CRC 111
+#define IDS_ETYPE_DES_CBC_MD4 112
+#define IDS_ETYPE_DES_CBC_MD5 113
+#define IDS_ETYPE_DES_CBC_RAW 114
+#define IDS_ETYPE_DES3_CBC_SHA 115
+#define IDS_ETYPE_DES3_CBC_RAW 116
+#define IDS_ETYPE_DES_HMAC_SHA1 117
+#define IDS_ETYPE_DES3_CBC_SHA1 118
+#define IDS_ETYPE_AES128_CTS_HMAC_SHA1_96 119
+#define IDS_ETYPE_AES256_CTS_HMAC_SHA1_96 120
+#define IDS_ETYPE_ARCFOUR_HMAC 121
+#define IDS_ETYPE_ARCFOUR_HMAC_EXP 122
+#define IDS_ETYPE_UNKNOWN 123
+#define IDS_ETYPE_LOCAL_DES3_HMAC_SHA1 124
+#define IDS_ETYPE_LOCAL_RC4_MD4 125
+#define IDS_KRB5_SHORT_DESC 126
+#define IDS_KRB5_LONG_DESC 127
+#define IDS_KRB4_SHORT_DESC 128
+#define IDS_KRB4_LONG_DESC 129
+#define IDS_KRB5_FLAGS_SHORT_DESC 130
+#define IDS_RENEW_TILL_SHORT_DESC 131
+#define IDS_RENEW_TILL_LONG_DESC 132
+#define IDS_RENEW_FOR_SHORT_DESC 133
+#define IDS_RENEW_FOR_LONG_DESC 134
+#define IDS_KRB5_CCNAME_LONG_DESC 135
+#define IDS_NC_USERNAME 136
+#define IDS_NC_REALM 137
+#define IDS_KRB5_WARNING 138
+#define IDS_K5ERR_NAME_EXPIRED 139
+#define IDS_K5ERR_KEY_EXPIRED 140
+#define IDS_KRB5_WARN_FMT 141
+#define IDS_K5ERR_FMT 142
+#define IDS_K5CFG_SHORT_DESC 143
+#define IDS_K5CFG_LONG_DESC 144
+#define IDS_K5RLM_SHORT_DESC 145
+#define IDS_K5RLM_LONG_DESC 146
+#define IDS_K5CFG_IDS_SHORT_DESC 147
+#define IDS_K5CFG_IDS_LONG_DESC 148
+#define IDS_K5CFG_ID_SHORT_DESC 149
+#define IDS_K5CFG_ID_LONG_DESC 150
+#define IDS_PLUGIN_DESC 151
+#define IDS_NC_PWD_BANNER 152
+#define IDS_NC_PWD_PWD 153
+#define IDS_NC_PWD_NPWD 154
+#define IDS_NC_PWD_NPWD_AGAIN 155
+#define IDS_KRB5_CREDTEXT_P0 156
+#define IDS_K5CFG_IMPORT_OPTIONS 157
+#define IDC_NCK5_RENEWABLE 1002
+#define IDC_NCK5_FORWARDABLE 1004
+#define IDC_NCK5_REALM 1005
+#define IDC_NCK5_ADD_REALMS 1006
+#define IDC_NCK5_LIFETIME_EDIT 1008
+#define IDC_NCK5_RENEW_EDIT 1009
+#define IDC_PPK5_CRENEW 1014
+#define IDC_PPK5_CFORWARD 1015
+#define IDC_PPK5_CPROXY 1016
+#define IDC_PPK5_NAME 1017
+#define IDC_PPK5_ISSUE 1018
+#define IDC_PPK5_VALID 1019
+#define IDC_PPK5_RENEW 1020
+#define IDC_CHECK2 1022
+#define IDC_CHECK4 1024
+#define IDC_PPK5_LIFETIME 1024
+#define IDC_CHECK5 1025
+#define IDC_CFG_LBL_REALM 1025
+#define IDC_CFG_DEFREALM 1026
+#define IDC_CFG_LBL_CFGFILE 1029
+#define IDC_CFG_CFGFILE 1030
+#define IDC_CFG_WINGRP 1031
+#define IDC_LBL_IMPORT 1032
+#define IDC_CFG_IMPORT 1033
+#define IDC_CFG_LBL_HOSTNAME 1034
+#define IDC_CFG_HOSTNAME 1035
+#define IDC_CFG_LBL_DOMAIN 1036
+#define IDC_CFG_DOMAIN 1037
+#define IDC_CFG_CREATECONFIG 1038
+#define IDC_CFG_BROWSE 1039
+#define IDC_CFG_CFGFILEGRP 1040
+#define IDC_CFG_CFGREALMS 1041
+#define IDC_CFG_REALMS 1044
+#define IDC_CFG_DOMAINGRP 1045
+#define IDC_CFG_SERVERSGRP 1046
+#define IDC_LIST3 1047
+#define IDC_LIST4 1048
+#define IDC_CFG_LBL_DEFLIFE 1049
+#define IDC_CFG_DEFLIFE 1050
+#define IDC_CFG_LBL_DEFRLIFE 1051
+#define IDC_CFG_DEFRLIFE 1052
+#define IDC_CFG_LIFEGRP 1053
+#define IDC_CFG_LRNG_MIN 1054
+#define IDC_CFG_LRNG_MAX 1055
+#define IDC_CFG_RLRNG_MIN 1056
+#define IDC_CFG_RLRNG_MAX 1057
+#define IDC_CFG_CCACHE 1058
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 111
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1059
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/src/windows/identity/plugins/krb5/main.c b/src/windows/identity/plugins/krb5/main.c
new file mode 100644
index 0000000..db996d9
--- /dev/null
+++ b/src/windows/identity/plugins/krb5/main.c
@@ -0,0 +1,387 @@
+/*
+ * Copyright (c) 2004 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $Id$ */
+
+#include<krbcred.h>
+#include<kherror.h>
+
+kmm_module h_khModule; /* KMM's handle to this module */
+HINSTANCE hInstance;
+HMODULE hResModule; /* HMODULE to the resource library */
+const wchar_t * k5_facility = L"Krb5";
+
+khm_int32 type_id_enctype = -1;
+khm_int32 type_id_addr_list = -1;
+khm_int32 type_id_krb5_flags = -1;
+
+BOOL type_regd_enctype = FALSE;
+BOOL type_regd_addr_list = FALSE;
+BOOL type_regd_krb5_flags = FALSE;
+
+khm_int32 attr_id_key_enctype = -1;
+khm_int32 attr_id_tkt_enctype = -1;
+khm_int32 attr_id_addr_list = -1;
+khm_int32 attr_id_krb5_flags = -1;
+khm_int32 attr_id_krb5_ccname = -1;
+
+BOOL attr_regd_key_enctype = FALSE;
+BOOL attr_regd_tkt_enctype = FALSE;
+BOOL attr_regd_addr_list = FALSE;
+BOOL attr_regd_krb5_flags = FALSE;
+BOOL attr_regd_krb5_ccname = FALSE;
+
+khm_handle csp_plugins = NULL;
+khm_handle csp_krbcred = NULL;
+khm_handle csp_params = NULL;
+
+BOOL is_k5_identpro = TRUE;
+
+kmm_module_locale locales[] = {
+ LOCALE_DEF(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US), L"krb5cred_en_us.dll", KMM_MLOC_FLAG_DEFAULT)
+};
+int n_locales = ARRAYLENGTH(locales);
+
+/* These two should not do anything */
+void init_krb() {
+}
+
+void exit_krb() {
+}
+
+/* called by the NetIDMgr module manager */
+KHMEXP khm_int32 KHMAPI init_module(kmm_module h_module) {
+ khm_int32 rv = KHM_ERROR_SUCCESS;
+ kmm_plugin_reg pi;
+ wchar_t buf[256];
+
+ h_khModule = h_module;
+
+ rv = kmm_set_locale_info(h_module, locales, n_locales);
+ if(KHM_SUCCEEDED(rv)) {
+ hResModule = kmm_get_resource_hmodule(h_module);
+ } else
+ goto _exit;
+
+ /* register the plugin */
+ ZeroMemory(&pi, sizeof(pi));
+ pi.name = KRB5_PLUGIN_NAME;
+ pi.type = KHM_PITYPE_CRED;
+ pi.icon = NULL; /*TODO: Assign icon */
+ pi.flags = KHM_PIFLAG_IDENTITY_PROVIDER;
+ pi.msg_proc = k5_msg_callback;
+ pi.description = buf;
+ LoadString(hResModule, IDS_PLUGIN_DESC,
+ buf, ARRAYLENGTH(buf));
+ kmm_provide_plugin(h_module, &pi);
+
+ if(KHM_FAILED(rv = init_imports()))
+ goto _exit;
+
+ if(KHM_FAILED(rv = init_error_funcs()))
+ goto _exit;
+
+ /* Register common data types */
+ if(KHM_FAILED(kcdb_type_get_id(TYPENAME_ENCTYPE, &type_id_enctype))) {
+ kcdb_type type;
+ kcdb_type *t32;
+
+ kcdb_type_get_info(KCDB_TYPE_INT32, &t32);
+
+ type.id = KCDB_TYPE_INVALID;
+ type.name = TYPENAME_ENCTYPE;
+ type.flags = KCDB_TYPE_FLAG_CB_FIXED;
+ type.cb_max = t32->cb_max;
+ type.cb_min = t32->cb_min;
+ type.isValid = t32->isValid;
+ type.comp = t32->comp;
+ type.dup = t32->dup;
+ type.toString = enctype_toString;
+
+ rv = kcdb_type_register(&type, &type_id_enctype);
+ kcdb_type_release_info(t32);
+
+ if(KHM_FAILED(rv))
+ goto _exit;
+ type_regd_enctype = TRUE;
+ }
+
+ if(KHM_FAILED(kcdb_type_get_id(TYPENAME_ADDR_LIST, &type_id_addr_list))) {
+ kcdb_type type;
+ kcdb_type *tdata;
+
+ kcdb_type_get_info(KCDB_TYPE_DATA, &tdata);
+
+ type.id = KCDB_TYPE_INVALID;
+ type.name = TYPENAME_ADDR_LIST;
+ type.flags = KCDB_TYPE_FLAG_CB_MIN;
+ type.cb_min = 0;
+ type.cb_max = 0;
+ type.isValid = tdata->isValid;
+ type.comp = tdata->comp;
+ type.dup = tdata->dup;
+ type.toString = addr_list_toString;
+
+ rv = kcdb_type_register(&type, &type_id_addr_list);
+ kcdb_type_release_info(tdata);
+
+ if(KHM_FAILED(rv))
+ goto _exit;
+ type_regd_addr_list = TRUE;
+ }
+
+ if(KHM_FAILED(kcdb_type_get_id(TYPENAME_KRB5_FLAGS, &type_id_krb5_flags))) {
+ kcdb_type type;
+ kcdb_type *t32;
+
+ kcdb_type_get_info(KCDB_TYPE_INT32, &t32);
+
+ type.id = KCDB_TYPE_INVALID;
+ type.name = TYPENAME_KRB5_FLAGS;
+ type.flags = KCDB_TYPE_FLAG_CB_FIXED;
+ type.cb_max = t32->cb_max;
+ type.cb_min = t32->cb_min;
+ type.isValid = t32->isValid;
+ type.comp = t32->comp;
+ type.dup = t32->dup;
+ type.toString = krb5flags_toString;
+
+ rv = kcdb_type_register(&type, &type_id_krb5_flags);
+ kcdb_type_release_info(t32);
+
+ if(KHM_FAILED(rv))
+ goto _exit;
+ type_regd_krb5_flags = TRUE;
+ }
+
+ /* Register common attributes */
+ if(KHM_FAILED(kcdb_attrib_get_id(ATTRNAME_KEY_ENCTYPE, &attr_id_key_enctype))) {
+ kcdb_attrib attrib;
+ wchar_t sbuf[KCDB_MAXCCH_SHORT_DESC];
+ wchar_t lbuf[KCDB_MAXCCH_SHORT_DESC];
+ /* although we are loading a long descriptoin, it still fits
+ in the short descriptoin buffer */
+
+ ZeroMemory(&attrib, sizeof(attrib));
+
+ attrib.name = ATTRNAME_KEY_ENCTYPE;
+ attrib.id = KCDB_ATTR_INVALID;
+ attrib.type = type_id_enctype;
+ attrib.flags = 0;
+ LoadString(hResModule, IDS_KEY_ENCTYPE_SHORT_DESC, sbuf, ARRAYLENGTH(sbuf));
+ LoadString(hResModule, IDS_KEY_ENCTYPE_LONG_DESC, lbuf, ARRAYLENGTH(lbuf));
+ attrib.short_desc = sbuf;
+ attrib.long_desc = lbuf;
+
+ rv = kcdb_attrib_register(&attrib, &attr_id_key_enctype);
+
+ if(KHM_FAILED(rv))
+ goto _exit;
+
+ attr_regd_key_enctype = TRUE;
+ }
+
+ if(KHM_FAILED(kcdb_attrib_get_id(ATTRNAME_TKT_ENCTYPE, &attr_id_tkt_enctype))) {
+ kcdb_attrib attrib;
+ wchar_t sbuf[KCDB_MAXCCH_SHORT_DESC];
+ wchar_t lbuf[KCDB_MAXCCH_SHORT_DESC];
+ /* although we are loading a long descriptoin, it still fits
+ in the short descriptoin buffer */
+
+ ZeroMemory(&attrib, sizeof(attrib));
+
+ attrib.name = ATTRNAME_TKT_ENCTYPE;
+ attrib.id = KCDB_ATTR_INVALID;
+ attrib.type = type_id_enctype;
+ attrib.flags = 0;
+ LoadString(hResModule, IDS_TKT_ENCTYPE_SHORT_DESC, sbuf, ARRAYLENGTH(sbuf));
+ LoadString(hResModule, IDS_TKT_ENCTYPE_LONG_DESC, lbuf, ARRAYLENGTH(lbuf));
+ attrib.short_desc = sbuf;
+ attrib.long_desc = lbuf;
+
+ rv = kcdb_attrib_register(&attrib, &attr_id_tkt_enctype);
+
+ if(KHM_FAILED(rv))
+ goto _exit;
+
+ attr_regd_tkt_enctype = TRUE;
+ }
+
+ if(KHM_FAILED(kcdb_attrib_get_id(ATTRNAME_ADDR_LIST, &attr_id_addr_list))) {
+ kcdb_attrib attrib;
+ wchar_t sbuf[KCDB_MAXCCH_SHORT_DESC];
+ wchar_t lbuf[KCDB_MAXCCH_SHORT_DESC];
+ /* although we are loading a long descriptoin, it still fits
+ in the short descriptoin buffer */
+
+ ZeroMemory(&attrib, sizeof(attrib));
+
+ attrib.name = ATTRNAME_ADDR_LIST;
+ attrib.id = KCDB_ATTR_INVALID;
+ attrib.type = type_id_addr_list;
+ attrib.flags = 0;
+ LoadString(hResModule, IDS_ADDR_LIST_SHORT_DESC, sbuf, ARRAYLENGTH(sbuf));
+ LoadString(hResModule, IDS_ADDR_LIST_LONG_DESC, lbuf, ARRAYLENGTH(lbuf));
+ attrib.short_desc = sbuf;
+ attrib.long_desc = lbuf;
+
+ rv = kcdb_attrib_register(&attrib, &attr_id_addr_list);
+
+ if(KHM_FAILED(rv))
+ goto _exit;
+
+ attr_regd_addr_list = TRUE;
+ }
+
+ if(KHM_FAILED(kcdb_attrib_get_id(ATTRNAME_KRB5_FLAGS, &attr_id_krb5_flags))) {
+ kcdb_attrib attrib;
+ wchar_t sbuf[KCDB_MAXCCH_SHORT_DESC];
+
+ /* although we are loading a long descriptoin, it still fits
+ in the short descriptoin buffer */
+
+ ZeroMemory(&attrib, sizeof(attrib));
+
+ attrib.name = ATTRNAME_KRB5_FLAGS;
+ attrib.id = KCDB_ATTR_INVALID;
+ attrib.type = type_id_krb5_flags;
+ attrib.flags = 0;
+ LoadString(hResModule, IDS_KRB5_FLAGS_SHORT_DESC, sbuf, ARRAYLENGTH(sbuf));
+ attrib.short_desc = sbuf;
+ attrib.long_desc = NULL;
+
+ rv = kcdb_attrib_register(&attrib, &attr_id_krb5_flags);
+
+ if(KHM_FAILED(rv))
+ goto _exit;
+
+ attr_regd_krb5_flags = TRUE;
+ }
+
+ if(KHM_FAILED(kcdb_attrib_get_id(ATTRNAME_KRB5_CCNAME, &attr_id_krb5_ccname))) {
+ kcdb_attrib attrib;
+ wchar_t sbuf[KCDB_MAXCCH_SHORT_DESC];
+ wchar_t lbuf[KCDB_MAXCCH_SHORT_DESC];
+ /* although we are loading a long descriptoin, it still fits
+ in the short descriptoin buffer */
+
+ ZeroMemory(&attrib, sizeof(attrib));
+
+ attrib.name = ATTRNAME_KRB5_CCNAME;
+ attrib.id = KCDB_ATTR_INVALID;
+ attrib.type = KCDB_TYPE_STRING;
+ attrib.flags = KCDB_ATTR_FLAG_PROPERTY;
+ LoadString(hResModule, IDS_KRB5_CCNAME_SHORT_DESC, sbuf, ARRAYLENGTH(sbuf));
+ LoadString(hResModule, IDS_KRB5_CCNAME_LONG_DESC, lbuf, ARRAYLENGTH(lbuf));
+ attrib.short_desc = sbuf;
+ attrib.long_desc = lbuf;
+
+ rv = kcdb_attrib_register(&attrib, &attr_id_krb5_ccname);
+
+ if(KHM_FAILED(rv))
+ goto _exit;
+
+ attr_regd_krb5_ccname = TRUE;
+ }
+
+ rv = kmm_get_plugins_config(0, &csp_plugins);
+ if(KHM_FAILED(rv)) goto _exit;
+
+ rv = khc_load_schema(csp_plugins, schema_krbconfig);
+ if(KHM_FAILED(rv)) goto _exit;
+
+ rv = khc_open_space(csp_plugins, CSNAME_KRB5CRED, 0, &csp_krbcred);
+ if(KHM_FAILED(rv)) goto _exit;
+
+ rv = khc_open_space(csp_krbcred, CSNAME_PARAMS, 0, &csp_params);
+ if(KHM_FAILED(rv)) goto _exit;
+
+_exit:
+ return rv;
+}
+
+/* called by the NetIDMgr module manager */
+KHMEXP khm_int32 KHMAPI exit_module(kmm_module h_module) {
+ exit_imports();
+ exit_error_funcs();
+
+ if(attr_regd_key_enctype)
+ kcdb_attrib_unregister(attr_id_key_enctype);
+ if(attr_regd_tkt_enctype)
+ kcdb_attrib_unregister(attr_id_tkt_enctype);
+ if(attr_regd_addr_list)
+ kcdb_attrib_unregister(attr_id_addr_list);
+ if(attr_regd_krb5_flags)
+ kcdb_attrib_unregister(attr_id_krb5_flags);
+ if(attr_regd_krb5_ccname)
+ kcdb_attrib_unregister(attr_id_krb5_ccname);
+
+ if(type_regd_enctype)
+ kcdb_type_unregister(type_id_enctype);
+ if(type_regd_addr_list)
+ kcdb_type_unregister(type_id_addr_list);
+ if(type_regd_krb5_flags)
+ kcdb_type_unregister(type_id_krb5_flags);
+
+ if(csp_params) {
+ khc_close_space(csp_params);
+ csp_params = NULL;
+ }
+
+ if(csp_krbcred) {
+ khc_close_space(csp_krbcred);
+ csp_krbcred = NULL;
+ }
+
+ if(csp_plugins) {
+ khc_unload_schema(csp_plugins, schema_krbconfig);
+ khc_close_space(csp_plugins);
+ csp_plugins = NULL;
+ }
+
+ return KHM_ERROR_SUCCESS; /* the return code is ignored */
+}
+
+BOOL WINAPI DllMain(
+ HINSTANCE hinstDLL,
+ DWORD fdwReason,
+ LPVOID lpvReserved
+)
+{
+ switch(fdwReason) {
+ case DLL_PROCESS_ATTACH:
+ hInstance = hinstDLL;
+ init_krb();
+ break;
+ case DLL_PROCESS_DETACH:
+ exit_krb();
+ break;
+ case DLL_THREAD_ATTACH:
+ break;
+ case DLL_THREAD_DETACH:
+ break;
+ }
+
+ return TRUE;
+}