diff options
| author | Ken Raeburn <raeburn@mit.edu> | 2007-06-20 01:19:59 +0000 |
|---|---|---|
| committer | Ken Raeburn <raeburn@mit.edu> | 2007-06-20 01:19:59 +0000 |
| commit | 78ec90d925e1f672639762e6c9fa674bf7ff0a64 (patch) | |
| tree | 3aad3df3133e6e0f2922f575b9da94630543f433 /src/windows/identity/plugins | |
| parent | d275e06d0cb0f248aa54a6f134a59f84aa563e14 (diff) | |
set svn:eol-style to native for *.[ch]
git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@19596 dc483132-0cff-0310-8789-dd5450dbe970
Diffstat (limited to 'src/windows/identity/plugins')
30 files changed, 16497 insertions, 16497 deletions
diff --git a/src/windows/identity/plugins/common/dynimport.c b/src/windows/identity/plugins/common/dynimport.c index f49987ca7..24fa1a551 100644 --- a/src/windows/identity/plugins/common/dynimport.c +++ b/src/windows/identity/plugins/common/dynimport.c @@ -1,477 +1,477 @@ -/*
-* Copyright (c) 2005 Massachusetts Institute of Technology
-* Copyright (c) 2007 Secure Endpoints Inc.
-*
-* 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<netidmgr.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_opt_set_change_password_prompt);
-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_get_type);
-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_set_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);
-DECL_FUNC_PTR(krb5_string_to_deltat);
-
-// 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_flush);
-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_get_integer);
-DECL_FUNC_PTR(profile_get_values);
-DECL_FUNC_PTR(profile_get_relation_names);
-DECL_FUNC_PTR(profile_clear_relation);
-DECL_FUNC_PTR(profile_add_relation);
-DECL_FUNC_PTR(profile_update_relation);
-DECL_FUNC_PTR(profile_release_string);
-DECL_FUNC_PTR(profile_rename_section);
-
-// 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_opt_set_change_password_prompt),
- 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_get_type),
- 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_set_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),
- MAKE_FUNC_INFO(krb5_string_to_deltat),
- 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_flush),
- 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_get_integer),
- MAKE_FUNC_INFO(profile_get_values),
- MAKE_FUNC_INFO(profile_get_relation_names),
- MAKE_FUNC_INFO(profile_clear_relation),
- MAKE_FUNC_INFO(profile_add_relation),
- MAKE_FUNC_INFO(profile_update_relation),
- MAKE_FUNC_INFO(profile_release_string),
- MAKE_FUNC_INFO(profile_rename_section),
- 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;
- int imp_rv = 1;
-
-#define CKRV(m) \
- do { \
- if(!imp_rv) { \
- _reportf(L"Can't locate all required exports from module [%S]", (m)); \
- goto _err_ret; \
- } \
- } while (FALSE)
-
-#ifndef _WIN64
- imp_rv = LoadFuncs(KRB4_DLL, k4_fi, &hKrb4, 0, 1, 0, 0);
- CKRV(KRB4_DLL);
-#endif
-
- imp_rv = LoadFuncs(KRB5_DLL, k5_fi, &hKrb5, 0, 1, 0, 0);
- CKRV(KRB5_DLL);
-
- imp_rv = LoadFuncs(COMERR_DLL, ce_fi, &hComErr, 0, 0, 1, 0);
- CKRV(COMERR_DLL);
-
- imp_rv = LoadFuncs(SERVICE_DLL, service_fi, &hService, 0, 1, 0, 0);
- CKRV(SERVICE_DLL);
-
- imp_rv = LoadFuncs(SECUR32_DLL, lsa_fi, &hSecur32, 0, 1, 1, 1);
- CKRV(SECUR32_DLL);
-
- imp_rv = LoadFuncs(KRB524_DLL, k524_fi, &hKrb524, 0, 1, 1, 1);
- CKRV(KRB524_DLL);
-
- imp_rv = LoadFuncs(PROFILE_DLL, profile_fi, &hProfile, 0, 1, 0, 0);
- CKRV(PROFILE_DLL);
-
- imp_rv = LoadFuncs(CCAPI_DLL, ccapi_fi, &hCCAPI, 0, 1, 0, 0);
- /* CCAPI_DLL is optional. No error check. */
-
- 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
- imp_rv = LoadFuncs(TOOLHELPDLL, toolhelp_fi, &hToolHelp32, 0, 1, 0, 0);
- CKRV(TOOLHELPDLL);
-
- hPsapi = 0;
- }
- else if(osvi.dwPlatformId == VER_PLATFORM_WIN32_NT)
- {
- // Windows NT
- imp_rv = LoadFuncs(PSAPIDLL, psapi_fi, &hPsapi, 0, 1, 0, 0);
- CKRV(PSAPIDLL);
-
- hToolHelp32 = 0;
- }
-
- AfsAvailable = TRUE; //afscompat_init();
-
- return KHM_ERROR_SUCCESS;
-
- _err_ret:
- return KHM_ERROR_NOT_FOUND;
-}
-
-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;
-}
+/* +* Copyright (c) 2005 Massachusetts Institute of Technology +* Copyright (c) 2007 Secure Endpoints Inc. +* +* 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<netidmgr.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_opt_set_change_password_prompt); +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_get_type); +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_set_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); +DECL_FUNC_PTR(krb5_string_to_deltat); + +// 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_flush); +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_get_integer); +DECL_FUNC_PTR(profile_get_values); +DECL_FUNC_PTR(profile_get_relation_names); +DECL_FUNC_PTR(profile_clear_relation); +DECL_FUNC_PTR(profile_add_relation); +DECL_FUNC_PTR(profile_update_relation); +DECL_FUNC_PTR(profile_release_string); +DECL_FUNC_PTR(profile_rename_section); + +// 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_opt_set_change_password_prompt), + 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_get_type), + 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_set_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), + MAKE_FUNC_INFO(krb5_string_to_deltat), + 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_flush), + 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_get_integer), + MAKE_FUNC_INFO(profile_get_values), + MAKE_FUNC_INFO(profile_get_relation_names), + MAKE_FUNC_INFO(profile_clear_relation), + MAKE_FUNC_INFO(profile_add_relation), + MAKE_FUNC_INFO(profile_update_relation), + MAKE_FUNC_INFO(profile_release_string), + MAKE_FUNC_INFO(profile_rename_section), + 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; + int imp_rv = 1; + +#define CKRV(m) \ + do { \ + if(!imp_rv) { \ + _reportf(L"Can't locate all required exports from module [%S]", (m)); \ + goto _err_ret; \ + } \ + } while (FALSE) + +#ifndef _WIN64 + imp_rv = LoadFuncs(KRB4_DLL, k4_fi, &hKrb4, 0, 1, 0, 0); + CKRV(KRB4_DLL); +#endif + + imp_rv = LoadFuncs(KRB5_DLL, k5_fi, &hKrb5, 0, 1, 0, 0); + CKRV(KRB5_DLL); + + imp_rv = LoadFuncs(COMERR_DLL, ce_fi, &hComErr, 0, 0, 1, 0); + CKRV(COMERR_DLL); + + imp_rv = LoadFuncs(SERVICE_DLL, service_fi, &hService, 0, 1, 0, 0); + CKRV(SERVICE_DLL); + + imp_rv = LoadFuncs(SECUR32_DLL, lsa_fi, &hSecur32, 0, 1, 1, 1); + CKRV(SECUR32_DLL); + + imp_rv = LoadFuncs(KRB524_DLL, k524_fi, &hKrb524, 0, 1, 1, 1); + CKRV(KRB524_DLL); + + imp_rv = LoadFuncs(PROFILE_DLL, profile_fi, &hProfile, 0, 1, 0, 0); + CKRV(PROFILE_DLL); + + imp_rv = LoadFuncs(CCAPI_DLL, ccapi_fi, &hCCAPI, 0, 1, 0, 0); + /* CCAPI_DLL is optional. No error check. */ + + 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 + imp_rv = LoadFuncs(TOOLHELPDLL, toolhelp_fi, &hToolHelp32, 0, 1, 0, 0); + CKRV(TOOLHELPDLL); + + hPsapi = 0; + } + else if(osvi.dwPlatformId == VER_PLATFORM_WIN32_NT) + { + // Windows NT + imp_rv = LoadFuncs(PSAPIDLL, psapi_fi, &hPsapi, 0, 1, 0, 0); + CKRV(PSAPIDLL); + + hToolHelp32 = 0; + } + + AfsAvailable = TRUE; //afscompat_init(); + + return KHM_ERROR_SUCCESS; + + _err_ret: + return KHM_ERROR_NOT_FOUND; +} + +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 index 7f3f598b0..850d96e5f 100644 --- a/src/windows/identity/plugins/common/dynimport.h +++ b/src/windows/identity/plugins/common/dynimport.h @@ -1,361 +1,361 @@ -/*
- * Copyright (c) 2005 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>
-
-#if _WIN32_WINNT < 0x0501
-#define KHM_SAVE_WIN32_WINNT _WIN32_WINNT
-#undef _WIN32_WINNT
-#define _WIN32_WINNT 0x0501
-#endif
-#include<ntsecapi.h>
-#ifdef KHM_SAVE_WIN32_WINNT
-#undef _WIN32_WINNT
-#define _WIN32_WINNT KHM_SAVE_WIN32_WINNT
-#undef KHM_SAVE_WIN32_WINNT
-#endif
-
-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_opt_set_change_password_prompt);
-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_get_type);
-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_set_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);
-extern DECL_FUNC_PTR(krb5_string_to_deltat);
-
-// 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_flush);
-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_get_integer);
-extern DECL_FUNC_PTR(profile_get_values);
-extern DECL_FUNC_PTR(profile_get_relation_names);
-extern DECL_FUNC_PTR(profile_clear_relation);
-extern DECL_FUNC_PTR(profile_add_relation);
-extern DECL_FUNC_PTR(profile_update_relation);
-extern DECL_FUNC_PTR(profile_release_string);
-extern DECL_FUNC_PTR(profile_rename_section);
-
-// 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
+/* + * Copyright (c) 2005 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> + +#if _WIN32_WINNT < 0x0501 +#define KHM_SAVE_WIN32_WINNT _WIN32_WINNT +#undef _WIN32_WINNT +#define _WIN32_WINNT 0x0501 +#endif +#include<ntsecapi.h> +#ifdef KHM_SAVE_WIN32_WINNT +#undef _WIN32_WINNT +#define _WIN32_WINNT KHM_SAVE_WIN32_WINNT +#undef KHM_SAVE_WIN32_WINNT +#endif + +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_opt_set_change_password_prompt); +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_get_type); +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_set_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); +extern DECL_FUNC_PTR(krb5_string_to_deltat); + +// 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_flush); +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_get_integer); +extern DECL_FUNC_PTR(profile_get_values); +extern DECL_FUNC_PTR(profile_get_relation_names); +extern DECL_FUNC_PTR(profile_clear_relation); +extern DECL_FUNC_PTR(profile_add_relation); +extern DECL_FUNC_PTR(profile_update_relation); +extern DECL_FUNC_PTR(profile_release_string); +extern DECL_FUNC_PTR(profile_rename_section); + +// 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 index 6c3958694..1278fbcfa 100644 --- a/src/windows/identity/plugins/common/krb5common.c +++ b/src/windows/identity/plugins/common/krb5common.c @@ -1,451 +1,451 @@ -/*
- * Copyright (c) 2005 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<netidmgr.h>
-#include<dynimport.h>
-#include<krb5common.h>
-#ifdef DEBUG
-#include<assert.h>
-#endif
-#include<strsafe.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 = NULL;
- int freeContextFlag = 0;
- krb5_error_code rc = 0;
- 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[MAX_PATH];
- 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))) {
- cbwccname = sizeof(wccname);
- if (KHM_FAILED
- (khm_krb5_find_ccache_for_identity(ident,
- ctx,
- wccname,
- &cbwccname))) {
-#ifdef DEBUG_LIKE_A_MADMAN
- assert(FALSE);
-#endif
- 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);
- }
-
-#ifndef FAILOVER_TO_DEFAULT_CCACHE
- rc = 1;
-#endif
- if (*cache == 0
-#ifdef FAILOVER_TO_DEFAULT_CCACHE
- && (rc = (*pkrb5_cc_default)(*ctx, cache))
-#endif
- ) {
- 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);
- *cache = NULL;
- }
- }
- return rc;
- }
- return 0;
-
-on_error:
- return khm_krb5_error(rc, functionName, freeContextFlag, ctx, cache);
-#endif //!NO_KRB5
-}
-
-#define TIMET_TOLERANCE (60*5)
-
-khm_int32 KHMAPI
-khm_get_identity_expiration_time(krb5_context ctx, krb5_ccache cc,
- khm_handle ident,
- krb5_timestamp * pexpiration)
-{
- krb5_principal principal = 0;
- char * princ_name = NULL;
- krb5_creds creds;
- krb5_error_code code;
- krb5_error_code cc_code;
- krb5_cc_cursor cur;
- krb5_timestamp now, expiration = 0;
-
- wchar_t w_ident_name[KCDB_IDENT_MAXCCH_NAME];
- char ident_name[KCDB_IDENT_MAXCCH_NAME];
- khm_size cb;
-
- khm_int32 rv = KHM_ERROR_NOT_FOUND;
-
- if (!ctx || !cc || !ident || !pexpiration)
- return KHM_ERROR_GENERAL;
-
- code = pkrb5_cc_get_principal(ctx, cc, &principal);
-
- if ( code )
- return KHM_ERROR_INVALID_PARAM;
-
- cb = sizeof(w_ident_name);
- kcdb_identity_get_name(ident, w_ident_name, &cb);
- UnicodeStrToAnsi(ident_name, sizeof(ident_name), w_ident_name);
-
- code = pkrb5_unparse_name(ctx, principal, &princ_name);
-
- /* compare principal to ident. */
-
- if ( code || !princ_name ||
- strcmp(princ_name, ident_name) ) {
- if (princ_name)
- pkrb5_free_unparsed_name(ctx, princ_name);
- pkrb5_free_principal(ctx, principal);
- return KHM_ERROR_UNKNOWN;
- }
-
- pkrb5_free_unparsed_name(ctx, princ_name);
- pkrb5_free_principal(ctx, principal);
-
- code = pkrb5_timeofday(ctx, &now);
-
- if (code)
- return KHM_ERROR_UNKNOWN;
-
- cc_code = pkrb5_cc_start_seq_get(ctx, cc, &cur);
-
- while (!(cc_code = pkrb5_cc_next_cred(ctx, cc, &cur, &creds))) {
- krb5_data * c0 = krb5_princ_name(ctx, creds.server);
- krb5_data * c1 = krb5_princ_component(ctx, creds.server, 1);
- krb5_data * r = krb5_princ_realm(ctx, creds.server);
-
- if ( c0 && c1 && r && c1->length == r->length &&
- !strncmp(c1->data,r->data,r->length) &&
- !strncmp("krbtgt",c0->data,c0->length) ) {
-
- /* we have a TGT, check for the expiration time.
- * if it is valid and renewable, use the renew time
- */
-
- if (!(creds.ticket_flags & TKT_FLG_INVALID) &&
- creds.times.starttime < (now + TIMET_TOLERANCE) &&
- (creds.times.endtime + TIMET_TOLERANCE) > now) {
- expiration = creds.times.endtime;
-
- if ((creds.ticket_flags & TKT_FLG_RENEWABLE) &&
- (creds.times.renew_till > creds.times.endtime)) {
- expiration = creds.times.renew_till;
- }
- }
- }
- }
-
- if (cc_code == KRB5_CC_END) {
- cc_code = pkrb5_cc_end_seq_get(ctx, cc, &cur);
- rv = KHM_ERROR_SUCCESS;
- *pexpiration = expiration;
- }
-
- return rv;
-}
-
-khm_int32 KHMAPI
-khm_krb5_find_ccache_for_identity(khm_handle ident, krb5_context *pctx,
- void * buffer, khm_size * pcbbuf)
-{
- krb5_context ctx = 0;
- krb5_ccache cache = 0;
- krb5_error_code code;
- apiCB * cc_ctx = 0;
- struct _infoNC ** pNCi = NULL;
- int i;
- khm_int32 t;
- wchar_t * ms = NULL;
- khm_size cb;
- krb5_timestamp expiration = 0;
- krb5_timestamp best_match_expiration = 0;
- char best_match_ccname[256] = "";
- khm_handle csp_params = NULL;
- khm_handle csp_plugins = NULL;
-
- if (!buffer || !pcbbuf)
- return KHM_ERROR_GENERAL;
-
- ctx = *pctx;
-
- if (!pcc_initialize ||
- !pcc_get_NC_info ||
- !pcc_free_NC_info ||
- !pcc_shutdown)
- goto _skip_cc_iter;
-
- 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;
-
- 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;
-
- /* need a function to check the cache for the identity
- * and determine if it has valid tickets. If it has
- * the right identity and valid tickets, store the
- * expiration time and the cache name. If it has the
- * right identity but no valid tickets, store the ccache
- * name and an expiration time of zero. if it does not
- * have the right identity don't save the name.
- *
- * Keep searching to find the best cache available.
- */
-
- if (KHM_SUCCEEDED(khm_get_identity_expiration_time(ctx, cache,
- ident,
- &expiration))) {
- if ( expiration > best_match_expiration ) {
- best_match_expiration = expiration;
- StringCbCopyA(best_match_ccname,
- sizeof(best_match_ccname),
- "API:");
- StringCbCatA(best_match_ccname,
- sizeof(best_match_ccname),
- pNCi[i]->name);
- expiration = 0;
- }
- }
-
- if(ctx != NULL && cache != NULL)
- (*pkrb5_cc_close)(ctx, cache);
- cache = 0;
- }
-
- _skip_cc_iter:
-
- if (KHM_SUCCEEDED(kmm_get_plugins_config(0, &csp_plugins))) {
- khc_open_space(csp_plugins, L"Krb5Cred\\Parameters", 0, &csp_params);
- khc_close_space(csp_plugins);
- csp_plugins = NULL;
- }
-
-#ifdef DEBUG
- if (csp_params == NULL) {
- assert(FALSE);
- }
-#endif
-
- if (csp_params &&
- KHM_SUCCEEDED(khc_read_int32(csp_params, L"MsLsaList", &t)) && t) {
- code = (*pkrb5_cc_resolve)(ctx, "MSLSA:", &cache);
- if (code == 0 && cache) {
- if (KHM_SUCCEEDED(khm_get_identity_expiration_time(ctx, cache,
- ident,
- &expiration))) {
- if ( expiration > best_match_expiration ) {
- best_match_expiration = expiration;
- StringCbCopyA(best_match_ccname, sizeof(best_match_ccname),
- "MSLSA:");
- expiration = 0;
- }
- }
- }
-
- if (ctx != NULL && cache != NULL)
- (*pkrb5_cc_close)(ctx, cache);
-
- cache = 0;
- }
-
- if (csp_params &&
- khc_read_multi_string(csp_params, L"FileCCList", NULL, &cb)
- == KHM_ERROR_TOO_LONG &&
- cb > sizeof(wchar_t) * 2) {
-
- wchar_t * t;
- char ccname[MAX_PATH + 6];
-
- ms = PMALLOC(cb);
-
-#ifdef DEBUG
- assert(ms);
-#endif
-
- khc_read_multi_string(csp_params, L"FileCCList", ms, &cb);
- for(t = ms; t && *t; t = multi_string_next(t)) {
- StringCchPrintfA(ccname, ARRAYLENGTH(ccname),
- "FILE:%S", t);
-
- code = (*pkrb5_cc_resolve)(ctx, ccname, &cache);
- if (code)
- continue;
-
- if (KHM_SUCCEEDED(khm_get_identity_expiration_time(ctx, cache,
- ident,
- &expiration))) {
- if ( expiration > best_match_expiration ) {
- best_match_expiration = expiration;
- StringCbCopyA(best_match_ccname,
- sizeof(best_match_ccname),
- ccname);
- expiration = 0;
- }
- }
-
- if (ctx != NULL && cache != NULL)
- (*pkrb5_cc_close)(ctx, cache);
- cache = 0;
- }
-
- PFREE(ms);
- }
- _exit:
- if (csp_params)
- khc_close_space(csp_params);
-
- if (pNCi)
- (*pcc_free_NC_info)(cc_ctx, &pNCi);
-
- if (cc_ctx)
- (*pcc_shutdown)(&cc_ctx);
-
- if (best_match_ccname[0]) {
-
- if (*pcbbuf = AnsiStrToUnicode((wchar_t *)buffer,
- *pcbbuf,
- best_match_ccname)) {
-
- *pcbbuf = (*pcbbuf + 1) * sizeof(wchar_t);
-
- return KHM_ERROR_SUCCESS;
- }
-
- }
-
- return KHM_ERROR_GENERAL;
-}
+/* + * Copyright (c) 2005 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<netidmgr.h> +#include<dynimport.h> +#include<krb5common.h> +#ifdef DEBUG +#include<assert.h> +#endif +#include<strsafe.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 = NULL; + int freeContextFlag = 0; + krb5_error_code rc = 0; + 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[MAX_PATH]; + 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))) { + cbwccname = sizeof(wccname); + if (KHM_FAILED + (khm_krb5_find_ccache_for_identity(ident, + ctx, + wccname, + &cbwccname))) { +#ifdef DEBUG_LIKE_A_MADMAN + assert(FALSE); +#endif + 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); + } + +#ifndef FAILOVER_TO_DEFAULT_CCACHE + rc = 1; +#endif + if (*cache == 0 +#ifdef FAILOVER_TO_DEFAULT_CCACHE + && (rc = (*pkrb5_cc_default)(*ctx, cache)) +#endif + ) { + 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); + *cache = NULL; + } + } + return rc; + } + return 0; + +on_error: + return khm_krb5_error(rc, functionName, freeContextFlag, ctx, cache); +#endif //!NO_KRB5 +} + +#define TIMET_TOLERANCE (60*5) + +khm_int32 KHMAPI +khm_get_identity_expiration_time(krb5_context ctx, krb5_ccache cc, + khm_handle ident, + krb5_timestamp * pexpiration) +{ + krb5_principal principal = 0; + char * princ_name = NULL; + krb5_creds creds; + krb5_error_code code; + krb5_error_code cc_code; + krb5_cc_cursor cur; + krb5_timestamp now, expiration = 0; + + wchar_t w_ident_name[KCDB_IDENT_MAXCCH_NAME]; + char ident_name[KCDB_IDENT_MAXCCH_NAME]; + khm_size cb; + + khm_int32 rv = KHM_ERROR_NOT_FOUND; + + if (!ctx || !cc || !ident || !pexpiration) + return KHM_ERROR_GENERAL; + + code = pkrb5_cc_get_principal(ctx, cc, &principal); + + if ( code ) + return KHM_ERROR_INVALID_PARAM; + + cb = sizeof(w_ident_name); + kcdb_identity_get_name(ident, w_ident_name, &cb); + UnicodeStrToAnsi(ident_name, sizeof(ident_name), w_ident_name); + + code = pkrb5_unparse_name(ctx, principal, &princ_name); + + /* compare principal to ident. */ + + if ( code || !princ_name || + strcmp(princ_name, ident_name) ) { + if (princ_name) + pkrb5_free_unparsed_name(ctx, princ_name); + pkrb5_free_principal(ctx, principal); + return KHM_ERROR_UNKNOWN; + } + + pkrb5_free_unparsed_name(ctx, princ_name); + pkrb5_free_principal(ctx, principal); + + code = pkrb5_timeofday(ctx, &now); + + if (code) + return KHM_ERROR_UNKNOWN; + + cc_code = pkrb5_cc_start_seq_get(ctx, cc, &cur); + + while (!(cc_code = pkrb5_cc_next_cred(ctx, cc, &cur, &creds))) { + krb5_data * c0 = krb5_princ_name(ctx, creds.server); + krb5_data * c1 = krb5_princ_component(ctx, creds.server, 1); + krb5_data * r = krb5_princ_realm(ctx, creds.server); + + if ( c0 && c1 && r && c1->length == r->length && + !strncmp(c1->data,r->data,r->length) && + !strncmp("krbtgt",c0->data,c0->length) ) { + + /* we have a TGT, check for the expiration time. + * if it is valid and renewable, use the renew time + */ + + if (!(creds.ticket_flags & TKT_FLG_INVALID) && + creds.times.starttime < (now + TIMET_TOLERANCE) && + (creds.times.endtime + TIMET_TOLERANCE) > now) { + expiration = creds.times.endtime; + + if ((creds.ticket_flags & TKT_FLG_RENEWABLE) && + (creds.times.renew_till > creds.times.endtime)) { + expiration = creds.times.renew_till; + } + } + } + } + + if (cc_code == KRB5_CC_END) { + cc_code = pkrb5_cc_end_seq_get(ctx, cc, &cur); + rv = KHM_ERROR_SUCCESS; + *pexpiration = expiration; + } + + return rv; +} + +khm_int32 KHMAPI +khm_krb5_find_ccache_for_identity(khm_handle ident, krb5_context *pctx, + void * buffer, khm_size * pcbbuf) +{ + krb5_context ctx = 0; + krb5_ccache cache = 0; + krb5_error_code code; + apiCB * cc_ctx = 0; + struct _infoNC ** pNCi = NULL; + int i; + khm_int32 t; + wchar_t * ms = NULL; + khm_size cb; + krb5_timestamp expiration = 0; + krb5_timestamp best_match_expiration = 0; + char best_match_ccname[256] = ""; + khm_handle csp_params = NULL; + khm_handle csp_plugins = NULL; + + if (!buffer || !pcbbuf) + return KHM_ERROR_GENERAL; + + ctx = *pctx; + + if (!pcc_initialize || + !pcc_get_NC_info || + !pcc_free_NC_info || + !pcc_shutdown) + goto _skip_cc_iter; + + 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; + + 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; + + /* need a function to check the cache for the identity + * and determine if it has valid tickets. If it has + * the right identity and valid tickets, store the + * expiration time and the cache name. If it has the + * right identity but no valid tickets, store the ccache + * name and an expiration time of zero. if it does not + * have the right identity don't save the name. + * + * Keep searching to find the best cache available. + */ + + if (KHM_SUCCEEDED(khm_get_identity_expiration_time(ctx, cache, + ident, + &expiration))) { + if ( expiration > best_match_expiration ) { + best_match_expiration = expiration; + StringCbCopyA(best_match_ccname, + sizeof(best_match_ccname), + "API:"); + StringCbCatA(best_match_ccname, + sizeof(best_match_ccname), + pNCi[i]->name); + expiration = 0; + } + } + + if(ctx != NULL && cache != NULL) + (*pkrb5_cc_close)(ctx, cache); + cache = 0; + } + + _skip_cc_iter: + + if (KHM_SUCCEEDED(kmm_get_plugins_config(0, &csp_plugins))) { + khc_open_space(csp_plugins, L"Krb5Cred\\Parameters", 0, &csp_params); + khc_close_space(csp_plugins); + csp_plugins = NULL; + } + +#ifdef DEBUG + if (csp_params == NULL) { + assert(FALSE); + } +#endif + + if (csp_params && + KHM_SUCCEEDED(khc_read_int32(csp_params, L"MsLsaList", &t)) && t) { + code = (*pkrb5_cc_resolve)(ctx, "MSLSA:", &cache); + if (code == 0 && cache) { + if (KHM_SUCCEEDED(khm_get_identity_expiration_time(ctx, cache, + ident, + &expiration))) { + if ( expiration > best_match_expiration ) { + best_match_expiration = expiration; + StringCbCopyA(best_match_ccname, sizeof(best_match_ccname), + "MSLSA:"); + expiration = 0; + } + } + } + + if (ctx != NULL && cache != NULL) + (*pkrb5_cc_close)(ctx, cache); + + cache = 0; + } + + if (csp_params && + khc_read_multi_string(csp_params, L"FileCCList", NULL, &cb) + == KHM_ERROR_TOO_LONG && + cb > sizeof(wchar_t) * 2) { + + wchar_t * t; + char ccname[MAX_PATH + 6]; + + ms = PMALLOC(cb); + +#ifdef DEBUG + assert(ms); +#endif + + khc_read_multi_string(csp_params, L"FileCCList", ms, &cb); + for(t = ms; t && *t; t = multi_string_next(t)) { + StringCchPrintfA(ccname, ARRAYLENGTH(ccname), + "FILE:%S", t); + + code = (*pkrb5_cc_resolve)(ctx, ccname, &cache); + if (code) + continue; + + if (KHM_SUCCEEDED(khm_get_identity_expiration_time(ctx, cache, + ident, + &expiration))) { + if ( expiration > best_match_expiration ) { + best_match_expiration = expiration; + StringCbCopyA(best_match_ccname, + sizeof(best_match_ccname), + ccname); + expiration = 0; + } + } + + if (ctx != NULL && cache != NULL) + (*pkrb5_cc_close)(ctx, cache); + cache = 0; + } + + PFREE(ms); + } + _exit: + if (csp_params) + khc_close_space(csp_params); + + if (pNCi) + (*pcc_free_NC_info)(cc_ctx, &pNCi); + + if (cc_ctx) + (*pcc_shutdown)(&cc_ctx); + + if (best_match_ccname[0]) { + + if (*pcbbuf = AnsiStrToUnicode((wchar_t *)buffer, + *pcbbuf, + best_match_ccname)) { + + *pcbbuf = (*pcbbuf + 1) * sizeof(wchar_t); + + return KHM_ERROR_SUCCESS; + } + + } + + return KHM_ERROR_GENERAL; +} diff --git a/src/windows/identity/plugins/common/krb5common.h b/src/windows/identity/plugins/common/krb5common.h index df3db93ae..29cae71ee 100644 --- a/src/windows/identity/plugins/common/krb5common.h +++ b/src/windows/identity/plugins/common/krb5common.h @@ -1,56 +1,56 @@ -/*
- * Copyright (c) 2005 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_get_error_string(krb5_error_code rc,
- wchar_t * buffer,
- khm_size cb_buffer);
-
-int khm_krb5_initialize(khm_handle ident, krb5_context *, krb5_ccache *);
-
-khm_int32 KHMAPI
-khm_krb5_find_ccache_for_identity(khm_handle ident, krb5_context *pctx,
- void * buffer, khm_size * pcbbuf);
-
-khm_int32 KHMAPI
-khm_get_identity_expiration_time(krb5_context ctx, krb5_ccache cc,
- khm_handle ident,
- krb5_timestamp * pexpiration);
-#endif /* NO_KRB5 */
-
-#endif
+/* + * Copyright (c) 2005 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_get_error_string(krb5_error_code rc, + wchar_t * buffer, + khm_size cb_buffer); + +int khm_krb5_initialize(khm_handle ident, krb5_context *, krb5_ccache *); + +khm_int32 KHMAPI +khm_krb5_find_ccache_for_identity(khm_handle ident, krb5_context *pctx, + void * buffer, khm_size * pcbbuf); + +khm_int32 KHMAPI +khm_get_identity_expiration_time(krb5_context ctx, krb5_ccache cc, + khm_handle ident, + krb5_timestamp * pexpiration); +#endif /* NO_KRB5 */ + +#endif diff --git a/src/windows/identity/plugins/krb4/errorfuncs.c b/src/windows/identity/plugins/krb4/errorfuncs.c index f1aa63d88..f436a40a7 100644 --- a/src/windows/identity/plugins/krb4/errorfuncs.c +++ b/src/windows/identity/plugins/krb4/errorfuncs.c @@ -1,226 +1,226 @@ -/*
- * Copyright (c) 2005 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<strsafe.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 = NULL;
- while (Child)
- {
- Last = Child;
- Child = GetParent (Child);
- }
- return Last;
-}
-
-
-LPSTR err_describe(LPSTR buf, size_t len, 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:
- StringCbCopyA(buf, len, 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) {
- StringCbCopyA(buf, len, 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;
- }
- StringCbPrintfA((LPSTR) cp, len - (cp-buf), (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;
-}
-
+/* + * Copyright (c) 2005 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<strsafe.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 = NULL; + while (Child) + { + Last = Child; + Child = GetParent (Child); + } + return Last; +} + + +LPSTR err_describe(LPSTR buf, size_t len, 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: + StringCbCopyA(buf, len, 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) { + StringCbCopyA(buf, len, 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; + } + StringCbPrintfA((LPSTR) cp, len - (cp-buf), (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; +} + diff --git a/src/windows/identity/plugins/krb4/errorfuncs.h b/src/windows/identity/plugins/krb4/errorfuncs.h index e339eca4f..d760c6259 100644 --- a/src/windows/identity/plugins/krb4/errorfuncs.h +++ b/src/windows/identity/plugins/krb4/errorfuncs.h @@ -1,65 +1,65 @@ -/*
- * Copyright (c) 2005 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
-
-LPSTR err_describe(LPSTR buf, size_t len, long code);
-
-
-/* */
-khm_int32 init_error_funcs();
-
-khm_int32 exit_error_funcs();
-
-
-#endif
+/* + * Copyright (c) 2005 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 + +LPSTR err_describe(LPSTR buf, size_t len, 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 index 523fbac5e..338cf7fa8 100644 --- a/src/windows/identity/plugins/krb4/krb4configdlg.c +++ b/src/windows/identity/plugins/krb4/krb4configdlg.c @@ -1,539 +1,539 @@ -/*
- * Copyright (c) 2005 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>
-#include<assert.h>
-
-typedef struct tag_k4_ids_data {
- khui_config_init_data cfg;
-
- khm_int32 get_tix;
-} k4_ids_data;
-
-static void
-k4_ids_read_params(k4_ids_data * d) {
- khm_int32 t;
-#ifdef DEBUG
- assert(csp_params);
-#endif
-
- t = 1;
- khc_read_int32(csp_params, L"Krb4NewCreds", &t);
- d->get_tix = !!t;
-}
-
-static void
-k4_ids_write_params(HWND hw, k4_ids_data * d) {
- khm_int32 nv;
- khm_boolean applied = FALSE;
-
- if (IsDlgButtonChecked(hw, IDC_CFG_GETTIX) == BST_CHECKED)
- nv = TRUE;
- else
- nv = FALSE;
-
- if (!!nv != !!d->get_tix) {
- d->get_tix = !!nv;
- khc_write_int32(csp_params, L"Krb4NewCreds", d->get_tix);
- applied = TRUE;
- }
-
- khui_cfg_set_flags_inst(&d->cfg,
- (applied)?KHUI_CNFLAG_APPLIED:0,
- KHUI_CNFLAG_APPLIED | KHUI_CNFLAG_MODIFIED);
-}
-
-static void
-k4_ids_check_mod(HWND hw, k4_ids_data * d) {
- khm_int32 nv;
-
- if (IsDlgButtonChecked(hw, IDC_CFG_GETTIX) == BST_CHECKED)
- nv = TRUE;
- else
- nv = FALSE;
-
- khui_cfg_set_flags_inst(&d->cfg,
- (!!nv != !!d->get_tix)? KHUI_CNFLAG_MODIFIED: 0,
- KHUI_CNFLAG_MODIFIED);
-}
-
-INT_PTR CALLBACK
-krb4_ids_config_proc(HWND hwnd,
- UINT uMsg,
- WPARAM wParam,
- LPARAM lParam) {
- k4_ids_data * d;
-
- switch(uMsg) {
- case WM_INITDIALOG:
- d = PMALLOC(sizeof(*d));
- ZeroMemory(d, sizeof(*d));
-
- d->cfg = *((khui_config_init_data *) lParam);
-
-#pragma warning(push)
-#pragma warning(disable: 4244)
- SetWindowLongPtr(hwnd, DWLP_USER, (LONG_PTR) d);
-#pragma warning(pop)
-
- k4_ids_read_params(d);
-
- CheckDlgButton(hwnd, IDC_CFG_GETTIX,
- (d->get_tix)? BST_CHECKED: BST_UNCHECKED);
-
- break;
-
- case WM_COMMAND:
- d = (k4_ids_data *) (LONG_PTR)
- GetWindowLongPtr(hwnd, DWLP_USER);
-
- if (HIWORD(wParam) == BN_CLICKED) {
- k4_ids_check_mod(hwnd, d);
- }
- break;
-
- case KHUI_WM_CFG_NOTIFY:
- d = (k4_ids_data *) (LONG_PTR)
- GetWindowLongPtr(hwnd, DWLP_USER);
-
- if (HIWORD(wParam) == WMCFG_APPLY) {
- k4_ids_write_params(hwnd, d);
- }
- break;
-
- case WM_DESTROY:
- d = (k4_ids_data *) (LONG_PTR)
- GetWindowLongPtr(hwnd, DWLP_USER);
-
- PFREE(d);
- break;
- }
-
- return FALSE;
-}
-
-typedef struct tag_k4_id_data {
- khui_config_init_data cfg;
- khm_int32 gettix; /* get tickets? */
- khm_boolean is_default_ident;
-} k4_id_data;
-
-void
-k4_id_read_params(k4_id_data * d) {
- wchar_t idname[KCDB_IDENT_MAXCCH_NAME];
- khm_size cb;
- khm_handle ident = NULL;
- khm_handle csp_ident = NULL;
- khm_handle csp_idk4 = NULL;
- khm_int32 flags = 0;
- khm_int32 t;
-
- khc_read_int32(csp_params, L"Krb4NewCreds", &d->gettix);
-
- *idname = 0;
- cb = sizeof(idname);
- khui_cfg_get_name(d->cfg.ctx_node, idname, &cb);
-
- kcdb_identity_create(idname, 0, &ident);
-
- if (ident == NULL) {
- d->gettix = 0;
- goto done;
- }
-
- kcdb_identity_get_flags(ident, &flags);
-
- if (!(flags & KCDB_IDENT_FLAG_DEFAULT)) {
- d->gettix = 0;
- goto done;
- }
-
- d->is_default_ident = TRUE;
-
- if (d->gettix == 0)
- goto done;
-
- if (KHM_FAILED(kcdb_identity_get_config(ident, 0, &csp_ident)))
- goto done;
-
- if (KHM_FAILED(khc_open_space(csp_ident, CSNAME_KRB4CRED,
- 0, &csp_idk4)))
- goto close_config;
-
- if (KHM_SUCCEEDED(khc_read_int32(csp_idk4, L"Krb4NewCreds", &t)) &&
- !t)
- d->gettix = 1;
-
- close_config:
- if (csp_ident)
- khc_close_space(csp_ident);
-
- if (csp_idk4)
- khc_close_space(csp_idk4);
-
- done:
- if (ident)
- kcdb_identity_release(ident);
-
- return;
-}
-
-khm_boolean
-k4_id_write_params(HWND hwnd, k4_id_data * d) {
- wchar_t idname[KCDB_IDENT_MAXCCH_NAME];
- khm_size cb_idname = sizeof(idname);
- khm_handle ident = NULL;
- khm_int32 flags = 0;
- khm_handle csp_ident = NULL;
- khm_handle csp_idk4 = NULL;
- khm_int32 gettix = 0;
- khm_boolean applied = FALSE;
-
- khui_cfg_get_name(d->cfg.ctx_node, idname, &cb_idname);
-
- kcdb_identity_create(idname, 0, &ident);
-
- if (ident == NULL)
- return FALSE;
-
- kcdb_identity_get_flags(ident, &flags);
-
- if (!(flags & KCDB_IDENT_FLAG_DEFAULT))
- goto done_apply;
-
- if (IsDlgButtonChecked(hwnd, IDC_CFG_GETTIX) == BST_CHECKED)
- gettix = TRUE;
-
- if (KHM_FAILED(kcdb_identity_get_config(ident, KHM_FLAG_CREATE,
- &csp_ident)))
- goto done_apply;
-
- if (KHM_FAILED(khc_open_space(csp_ident, CSNAME_KRB4CRED,
- KHM_FLAG_CREATE | KCONF_FLAG_WRITEIFMOD,
- &csp_idk4)))
- goto done_apply;
-
- khc_write_int32(csp_idk4, L"Krb4NewCreds", gettix);
-
- applied = TRUE;
-
- done_apply:
- if (ident)
- kcdb_identity_release(ident);
-
- if (csp_ident)
- khc_close_space(csp_ident);
-
- if (csp_idk4)
- khc_close_space(csp_idk4);
-
- return applied;
-}
-
-INT_PTR CALLBACK
-krb4_id_config_proc(HWND hwnd,
- UINT uMsg,
- WPARAM wParam,
- LPARAM lParam) {
- switch(uMsg) {
- case WM_INITDIALOG:
- {
- k4_id_data * d;
-
- d = PMALLOC(sizeof(k4_id_data));
-
- if (!d)
- break;
-
- ZeroMemory(d, sizeof(*d));
-
- d->cfg = *((khui_config_init_data *) lParam);
-
-#pragma warning(push)
-#pragma warning(disable: 4244)
- SetWindowLongPtr(hwnd, DWLP_USER, (LONG_PTR) d);
-#pragma warning(pop)
-
- k4_id_read_params(d);
-
- CheckDlgButton(hwnd, IDC_CFG_GETTIX,
- (d->gettix)?BST_CHECKED: BST_UNCHECKED);
- EnableWindow(GetDlgItem(hwnd, IDC_CFG_GETTIX),
- d->is_default_ident);
-
- }
- break;
-
- case WM_COMMAND:
- {
- k4_id_data * d;
-
- d = (k4_id_data *) (LONG_PTR)
- GetWindowLongPtr(hwnd, DWLP_USER);
-
- if (wParam == MAKEWPARAM(IDC_CFG_GETTIX,
- BN_CLICKED)) {
- int gettix = 0;
- int modified = 0;
-
- gettix = (IsDlgButtonChecked(hwnd, IDC_CFG_GETTIX) ==
- BST_CHECKED);
-
- modified = (!!gettix != !!d->gettix);
-
- khui_cfg_set_flags_inst(&d->cfg,
- ((modified)?KHUI_CNFLAG_MODIFIED: 0),
- KHUI_CNFLAG_MODIFIED);
- }
- }
- break;
-
- case KHUI_WM_CFG_NOTIFY:
- {
- k4_id_data * d;
-
- d = (k4_id_data *) (LONG_PTR)
- GetWindowLongPtr(hwnd, DWLP_USER);
-
- if (!d)
- break;
-
- if (HIWORD(wParam) == WMCFG_APPLY) {
- khm_int32 applied;
-
- applied = k4_id_write_params(hwnd, d);
-
- khui_cfg_set_flags_inst(&d->cfg,
- ((applied)? KHUI_CNFLAG_APPLIED: 0),
- (KHUI_CNFLAG_APPLIED | KHUI_CNFLAG_MODIFIED));
- }
- }
- break;
-
- case WM_DESTROY:
- {
- k4_id_data * d;
-
- d = (k4_id_data *) (LONG_PTR)
- GetWindowLongPtr(hwnd, DWLP_USER);
-
- if (!d)
- break;
-
- PFREE(d);
- }
- break;
- }
-
- return FALSE;
-}
-
-typedef struct tag_k4_config_dlg_data {
- khui_config_node node;
- char krb_path[MAX_PATH];
- char krbrealm_path[MAX_PATH];
- char tkt_string[MAX_PATH];
-} k4_config_dlg_data;
-
-INT_PTR CALLBACK
-krb4_confg_proc(HWND hwnd,
- UINT uMsg,
- WPARAM wParam,
- LPARAM lParam) {
-
- static BOOL in_init = FALSE;
- k4_config_dlg_data * d;
-
- 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);
- khm_size cbsize;
-
- d = PMALLOC(sizeof(*d));
- ZeroMemory(d, sizeof(*d));
-
-#pragma warning(push)
-#pragma warning(disable: 4244)
- SetWindowLongPtr(hwnd, DWLP_USER, (LONG_PTR) d);
-#pragma warning(pop)
-
- d->node = (khui_config_node) lParam;
-
- in_init = TRUE;
-
- // 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);
- StringCbCopyA(d->krb_path, sizeof(d->krb_path), krb_path);
- }
-
- // 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);
- StringCbCopyA(d->krbrealm_path, sizeof(d->krbrealm_path),
- krbrealm_path);
- }
-
- cbsize = sizeof(wbuf);
- if (KHM_SUCCEEDED(khc_read_string(csp_params, L"TktString",
- wbuf, &cbsize)) &&
- wbuf[0] != L'\0') {
-
- UnicodeStrToAnsi(ticketName, sizeof(ticketName), wbuf);
-
- } else {
-
- // 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);
- StringCbCopyA(d->tkt_string, sizeof(d->tkt_string),
- ticketName);
- }
-
- in_init = FALSE;
-
- }
- break;
-
- case WM_COMMAND:
- if (MAKEWPARAM(IDC_CFG_CACHE, EN_CHANGE)) {
- char tkt_string[MAX_PATH];
- wchar_t wtkt_string[MAX_PATH];
-
- if (in_init) {
- return TRUE;
- }
-
- d = (k4_config_dlg_data *) (LONG_PTR)
- GetWindowLongPtr(hwnd, DWLP_USER);
-
- if (d == NULL)
- return TRUE;
-
- tkt_string[0] = 0;
- wtkt_string[0] = 0;
-
- GetDlgItemText(hwnd, IDC_CFG_CACHE,
- wtkt_string, ARRAYLENGTH(wtkt_string));
- UnicodeStrToAnsi(tkt_string, sizeof(tkt_string),
- wtkt_string);
-
- if (_stricmp(tkt_string, d->tkt_string)) {
- khui_cfg_set_flags(d->node,
- KHUI_CNFLAG_MODIFIED,
- KHUI_CNFLAG_MODIFIED);
- } else {
- khui_cfg_set_flags(d->node,
- 0,
- KHUI_CNFLAG_MODIFIED);
- }
-
- return TRUE;
- }
- break;
-
- case KHUI_WM_CFG_NOTIFY:
- if (HIWORD(wParam) == WMCFG_APPLY) {
- wchar_t wtkt_string[MAX_PATH];
- char tkt_string[MAX_PATH];
- int t;
-
- d = (k4_config_dlg_data *) (LONG_PTR)
- GetWindowLongPtr(hwnd, DWLP_USER);
-
- if (d == NULL)
- return TRUE;
-
- t = GetDlgItemText(hwnd, IDC_CFG_CACHE,
- wtkt_string, ARRAYLENGTH(wtkt_string));
- if (t == 0)
- return TRUE;
-
- UnicodeStrToAnsi(tkt_string, sizeof(tkt_string), wtkt_string);
-
- if (_stricmp(tkt_string, d->tkt_string)) {
-
- pkrb_set_tkt_string(tkt_string);
-
- khc_write_string(csp_params, L"TktString", wtkt_string);
-
- khui_cfg_set_flags(d->node,
- KHUI_CNFLAG_APPLIED,
- KHUI_CNFLAG_APPLIED |
- KHUI_CNFLAG_MODIFIED);
- khm_krb4_list_tickets();
- } else {
- khui_cfg_set_flags(d->node,
- 0,
- KHUI_CNFLAG_MODIFIED);
- }
-
- return TRUE;
- }
- break;
-
- case WM_DESTROY:
- d = (k4_config_dlg_data *) (LONG_PTR)
- GetWindowLongPtr(hwnd, DWLP_USER);
-
- if (d) {
- PFREE(d);
- }
-
- break;
- }
- return FALSE;
-}
+/* + * Copyright (c) 2005 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> +#include<assert.h> + +typedef struct tag_k4_ids_data { + khui_config_init_data cfg; + + khm_int32 get_tix; +} k4_ids_data; + +static void +k4_ids_read_params(k4_ids_data * d) { + khm_int32 t; +#ifdef DEBUG + assert(csp_params); +#endif + + t = 1; + khc_read_int32(csp_params, L"Krb4NewCreds", &t); + d->get_tix = !!t; +} + +static void +k4_ids_write_params(HWND hw, k4_ids_data * d) { + khm_int32 nv; + khm_boolean applied = FALSE; + + if (IsDlgButtonChecked(hw, IDC_CFG_GETTIX) == BST_CHECKED) + nv = TRUE; + else + nv = FALSE; + + if (!!nv != !!d->get_tix) { + d->get_tix = !!nv; + khc_write_int32(csp_params, L"Krb4NewCreds", d->get_tix); + applied = TRUE; + } + + khui_cfg_set_flags_inst(&d->cfg, + (applied)?KHUI_CNFLAG_APPLIED:0, + KHUI_CNFLAG_APPLIED | KHUI_CNFLAG_MODIFIED); +} + +static void +k4_ids_check_mod(HWND hw, k4_ids_data * d) { + khm_int32 nv; + + if (IsDlgButtonChecked(hw, IDC_CFG_GETTIX) == BST_CHECKED) + nv = TRUE; + else + nv = FALSE; + + khui_cfg_set_flags_inst(&d->cfg, + (!!nv != !!d->get_tix)? KHUI_CNFLAG_MODIFIED: 0, + KHUI_CNFLAG_MODIFIED); +} + +INT_PTR CALLBACK +krb4_ids_config_proc(HWND hwnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam) { + k4_ids_data * d; + + switch(uMsg) { + case WM_INITDIALOG: + d = PMALLOC(sizeof(*d)); + ZeroMemory(d, sizeof(*d)); + + d->cfg = *((khui_config_init_data *) lParam); + +#pragma warning(push) +#pragma warning(disable: 4244) + SetWindowLongPtr(hwnd, DWLP_USER, (LONG_PTR) d); +#pragma warning(pop) + + k4_ids_read_params(d); + + CheckDlgButton(hwnd, IDC_CFG_GETTIX, + (d->get_tix)? BST_CHECKED: BST_UNCHECKED); + + break; + + case WM_COMMAND: + d = (k4_ids_data *) (LONG_PTR) + GetWindowLongPtr(hwnd, DWLP_USER); + + if (HIWORD(wParam) == BN_CLICKED) { + k4_ids_check_mod(hwnd, d); + } + break; + + case KHUI_WM_CFG_NOTIFY: + d = (k4_ids_data *) (LONG_PTR) + GetWindowLongPtr(hwnd, DWLP_USER); + + if (HIWORD(wParam) == WMCFG_APPLY) { + k4_ids_write_params(hwnd, d); + } + break; + + case WM_DESTROY: + d = (k4_ids_data *) (LONG_PTR) + GetWindowLongPtr(hwnd, DWLP_USER); + + PFREE(d); + break; + } + + return FALSE; +} + +typedef struct tag_k4_id_data { + khui_config_init_data cfg; + khm_int32 gettix; /* get tickets? */ + khm_boolean is_default_ident; +} k4_id_data; + +void +k4_id_read_params(k4_id_data * d) { + wchar_t idname[KCDB_IDENT_MAXCCH_NAME]; + khm_size cb; + khm_handle ident = NULL; + khm_handle csp_ident = NULL; + khm_handle csp_idk4 = NULL; + khm_int32 flags = 0; + khm_int32 t; + + khc_read_int32(csp_params, L"Krb4NewCreds", &d->gettix); + + *idname = 0; + cb = sizeof(idname); + khui_cfg_get_name(d->cfg.ctx_node, idname, &cb); + + kcdb_identity_create(idname, 0, &ident); + + if (ident == NULL) { + d->gettix = 0; + goto done; + } + + kcdb_identity_get_flags(ident, &flags); + + if (!(flags & KCDB_IDENT_FLAG_DEFAULT)) { + d->gettix = 0; + goto done; + } + + d->is_default_ident = TRUE; + + if (d->gettix == 0) + goto done; + + if (KHM_FAILED(kcdb_identity_get_config(ident, 0, &csp_ident))) + goto done; + + if (KHM_FAILED(khc_open_space(csp_ident, CSNAME_KRB4CRED, + 0, &csp_idk4))) + goto close_config; + + if (KHM_SUCCEEDED(khc_read_int32(csp_idk4, L"Krb4NewCreds", &t)) && + !t) + d->gettix = 1; + + close_config: + if (csp_ident) + khc_close_space(csp_ident); + + if (csp_idk4) + khc_close_space(csp_idk4); + + done: + if (ident) + kcdb_identity_release(ident); + + return; +} + +khm_boolean +k4_id_write_params(HWND hwnd, k4_id_data * d) { + wchar_t idname[KCDB_IDENT_MAXCCH_NAME]; + khm_size cb_idname = sizeof(idname); + khm_handle ident = NULL; + khm_int32 flags = 0; + khm_handle csp_ident = NULL; + khm_handle csp_idk4 = NULL; + khm_int32 gettix = 0; + khm_boolean applied = FALSE; + + khui_cfg_get_name(d->cfg.ctx_node, idname, &cb_idname); + + kcdb_identity_create(idname, 0, &ident); + + if (ident == NULL) + return FALSE; + + kcdb_identity_get_flags(ident, &flags); + + if (!(flags & KCDB_IDENT_FLAG_DEFAULT)) + goto done_apply; + + if (IsDlgButtonChecked(hwnd, IDC_CFG_GETTIX) == BST_CHECKED) + gettix = TRUE; + + if (KHM_FAILED(kcdb_identity_get_config(ident, KHM_FLAG_CREATE, + &csp_ident))) + goto done_apply; + + if (KHM_FAILED(khc_open_space(csp_ident, CSNAME_KRB4CRED, + KHM_FLAG_CREATE | KCONF_FLAG_WRITEIFMOD, + &csp_idk4))) + goto done_apply; + + khc_write_int32(csp_idk4, L"Krb4NewCreds", gettix); + + applied = TRUE; + + done_apply: + if (ident) + kcdb_identity_release(ident); + + if (csp_ident) + khc_close_space(csp_ident); + + if (csp_idk4) + khc_close_space(csp_idk4); + + return applied; +} + +INT_PTR CALLBACK +krb4_id_config_proc(HWND hwnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam) { + switch(uMsg) { + case WM_INITDIALOG: + { + k4_id_data * d; + + d = PMALLOC(sizeof(k4_id_data)); + + if (!d) + break; + + ZeroMemory(d, sizeof(*d)); + + d->cfg = *((khui_config_init_data *) lParam); + +#pragma warning(push) +#pragma warning(disable: 4244) + SetWindowLongPtr(hwnd, DWLP_USER, (LONG_PTR) d); +#pragma warning(pop) + + k4_id_read_params(d); + + CheckDlgButton(hwnd, IDC_CFG_GETTIX, + (d->gettix)?BST_CHECKED: BST_UNCHECKED); + EnableWindow(GetDlgItem(hwnd, IDC_CFG_GETTIX), + d->is_default_ident); + + } + break; + + case WM_COMMAND: + { + k4_id_data * d; + + d = (k4_id_data *) (LONG_PTR) + GetWindowLongPtr(hwnd, DWLP_USER); + + if (wParam == MAKEWPARAM(IDC_CFG_GETTIX, + BN_CLICKED)) { + int gettix = 0; + int modified = 0; + + gettix = (IsDlgButtonChecked(hwnd, IDC_CFG_GETTIX) == + BST_CHECKED); + + modified = (!!gettix != !!d->gettix); + + khui_cfg_set_flags_inst(&d->cfg, + ((modified)?KHUI_CNFLAG_MODIFIED: 0), + KHUI_CNFLAG_MODIFIED); + } + } + break; + + case KHUI_WM_CFG_NOTIFY: + { + k4_id_data * d; + + d = (k4_id_data *) (LONG_PTR) + GetWindowLongPtr(hwnd, DWLP_USER); + + if (!d) + break; + + if (HIWORD(wParam) == WMCFG_APPLY) { + khm_int32 applied; + + applied = k4_id_write_params(hwnd, d); + + khui_cfg_set_flags_inst(&d->cfg, + ((applied)? KHUI_CNFLAG_APPLIED: 0), + (KHUI_CNFLAG_APPLIED | KHUI_CNFLAG_MODIFIED)); + } + } + break; + + case WM_DESTROY: + { + k4_id_data * d; + + d = (k4_id_data *) (LONG_PTR) + GetWindowLongPtr(hwnd, DWLP_USER); + + if (!d) + break; + + PFREE(d); + } + break; + } + + return FALSE; +} + +typedef struct tag_k4_config_dlg_data { + khui_config_node node; + char krb_path[MAX_PATH]; + char krbrealm_path[MAX_PATH]; + char tkt_string[MAX_PATH]; +} k4_config_dlg_data; + +INT_PTR CALLBACK +krb4_confg_proc(HWND hwnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam) { + + static BOOL in_init = FALSE; + k4_config_dlg_data * d; + + 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); + khm_size cbsize; + + d = PMALLOC(sizeof(*d)); + ZeroMemory(d, sizeof(*d)); + +#pragma warning(push) +#pragma warning(disable: 4244) + SetWindowLongPtr(hwnd, DWLP_USER, (LONG_PTR) d); +#pragma warning(pop) + + d->node = (khui_config_node) lParam; + + in_init = TRUE; + + // 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); + StringCbCopyA(d->krb_path, sizeof(d->krb_path), krb_path); + } + + // 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); + StringCbCopyA(d->krbrealm_path, sizeof(d->krbrealm_path), + krbrealm_path); + } + + cbsize = sizeof(wbuf); + if (KHM_SUCCEEDED(khc_read_string(csp_params, L"TktString", + wbuf, &cbsize)) && + wbuf[0] != L'\0') { + + UnicodeStrToAnsi(ticketName, sizeof(ticketName), wbuf); + + } else { + + // 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); + StringCbCopyA(d->tkt_string, sizeof(d->tkt_string), + ticketName); + } + + in_init = FALSE; + + } + break; + + case WM_COMMAND: + if (MAKEWPARAM(IDC_CFG_CACHE, EN_CHANGE)) { + char tkt_string[MAX_PATH]; + wchar_t wtkt_string[MAX_PATH]; + + if (in_init) { + return TRUE; + } + + d = (k4_config_dlg_data *) (LONG_PTR) + GetWindowLongPtr(hwnd, DWLP_USER); + + if (d == NULL) + return TRUE; + + tkt_string[0] = 0; + wtkt_string[0] = 0; + + GetDlgItemText(hwnd, IDC_CFG_CACHE, + wtkt_string, ARRAYLENGTH(wtkt_string)); + UnicodeStrToAnsi(tkt_string, sizeof(tkt_string), + wtkt_string); + + if (_stricmp(tkt_string, d->tkt_string)) { + khui_cfg_set_flags(d->node, + KHUI_CNFLAG_MODIFIED, + KHUI_CNFLAG_MODIFIED); + } else { + khui_cfg_set_flags(d->node, + 0, + KHUI_CNFLAG_MODIFIED); + } + + return TRUE; + } + break; + + case KHUI_WM_CFG_NOTIFY: + if (HIWORD(wParam) == WMCFG_APPLY) { + wchar_t wtkt_string[MAX_PATH]; + char tkt_string[MAX_PATH]; + int t; + + d = (k4_config_dlg_data *) (LONG_PTR) + GetWindowLongPtr(hwnd, DWLP_USER); + + if (d == NULL) + return TRUE; + + t = GetDlgItemText(hwnd, IDC_CFG_CACHE, + wtkt_string, ARRAYLENGTH(wtkt_string)); + if (t == 0) + return TRUE; + + UnicodeStrToAnsi(tkt_string, sizeof(tkt_string), wtkt_string); + + if (_stricmp(tkt_string, d->tkt_string)) { + + pkrb_set_tkt_string(tkt_string); + + khc_write_string(csp_params, L"TktString", wtkt_string); + + khui_cfg_set_flags(d->node, + KHUI_CNFLAG_APPLIED, + KHUI_CNFLAG_APPLIED | + KHUI_CNFLAG_MODIFIED); + khm_krb4_list_tickets(); + } else { + khui_cfg_set_flags(d->node, + 0, + KHUI_CNFLAG_MODIFIED); + } + + return TRUE; + } + break; + + case WM_DESTROY: + d = (k4_config_dlg_data *) (LONG_PTR) + GetWindowLongPtr(hwnd, DWLP_USER); + + if (d) { + PFREE(d); + } + + break; + } + return FALSE; +} diff --git a/src/windows/identity/plugins/krb4/krb4funcs.c b/src/windows/identity/plugins/krb4/krb4funcs.c index b2b5fef4e..9e9ba42d2 100644 --- a/src/windows/identity/plugins/krb4/krb4funcs.c +++ b/src/windows/identity/plugins/krb4/krb4funcs.c @@ -1,897 +1,897 @@ -/*
-* Copyright (c) 2005 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 <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 ptktname[MAX_PATH + 5];
- char pname[ANAME_SZ];
- char pinst[INST_SZ];
- char prealm[REALM_SZ];
- wchar_t wbuf[256];
- int k_errno = 0;
- CREDENTIALS c;
- int newtickets = 0;
- int open = 0;
- khm_handle ident = NULL;
- khm_handle cred = NULL;
- time_t tt;
- FILETIME ft;
-
- kcdb_credset_flush(krb4_credset);
-
- // 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)
- goto collect;
-
- 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;
- }
-
- StringCchCopyA(ptktname, ARRAYLENGTH(ptktname), (*ptkt_string)());
-
- 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;
- }
-
- // 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));
-
- AnsiStrToUnicode(wbuf, sizeof(wbuf), ptktname);
- kcdb_cred_set_attr(cred, KCDB_ATTR_LOCATION, wbuf, KCDB_CBSIZE_AUTO);
-
- kcdb_credset_add_cred(krb4_credset, cred, -1);
-
- kcdb_cred_release(cred);
- } // while
-
- 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
-
- collect:
- kcdb_credset_collect(NULL, krb4_credset, ident, credtype_id_krb4, NULL);
-
- return k_errno;
-}
-
-#define KRB_FILE "KRB.CON"
-#define KRBREALM_FILE "KRBREALM.CON"
-#define KRB5_FILE "KRB5.INI"
-
-BOOL
-khm_krb5_get_profile_file(LPSTR confname, UINT szConfname)
-{
- char **configFile = NULL;
- if (pkrb5_get_default_config_files(&configFile))
- {
- GetWindowsDirectoryA(confname,szConfname);
- confname[szConfname-1] = '\0';
-
- StringCchCatA(confname, szConfname, "\\");
- StringCchCatA(confname, szConfname, KRB5_FILE);
-
- return FALSE;
- }
-
- *confname = 0;
-
- if (configFile)
- {
- StringCchCopyA(confname, szConfname, *configFile);
- pkrb5_free_config_files(configFile);
- }
-
- if (!*confname)
- {
- GetWindowsDirectoryA(confname,szConfname);
- confname[szConfname-1] = '\0';
-
- StringCchCatA(confname, szConfname, "\\");
- StringCchCatA(confname, szConfname, KRB5_FILE);
- }
-
- 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;
-
- if (khm_krb5_get_profile_file(krbConFile, sizeof(krbConFile))) {
- GetWindowsDirectoryA(krbConFile,sizeof(krbConFile));
- krbConFile[MAX_PATH-1] = '\0';
-
- StringCbCatA(krbConFile, sizeof(krbConFile), "\\");
- }
-
- pFind = strrchr(krbConFile, '\\');
-
- if (pFind) {
- *pFind = '\0';
-
- StringCbCatA(krbConFile, sizeof(krbConFile), "\\");
- StringCbCatA(krbConFile, sizeof(krbConFile), KRB_FILE);
- } else {
- krbConFile[0] = '\0';
- }
-
- StringCchCopyA(confname, szConfname, krbConFile);
- } else if (hKrb4) {
- unsigned int size = szConfname;
- memset(confname, '\0', szConfname);
- if (!pkrb_get_krbconf2(confname, &size)) {
- GetWindowsDirectoryA(confname,szConfname);
- confname[szConfname-1] = '\0';
- StringCchCatA(confname, szConfname, "\\");
- StringCchCatA(confname, szConfname, KRB_FILE);
- }
- }
-
- 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_krb5_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, §ions);
-
- 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 = PMALLOC(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)) &&
-#if _MSC_VER >= 1400
- !fopen_s(&file, krb_conf, "rt")
-#else
- (file = fopen(krb_conf, "rt"))
-#endif
- )
- {
- char lineBuf[256];
-
- /*TODO: compute the actual required buffer size instead of hardcoding */
- cbsize = 16384; // arbitrary
- rlist = PMALLOC(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 = PMALLOC(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;
-}
-
-static
-char *
-make_postfix(const char * base,
- const char * postfix,
- char ** rcopy)
-{
- size_t base_size;
- size_t ret_size;
- char * copy = 0;
- char * ret = 0;
- size_t t;
-
- if (FAILED(StringCbLengthA(base, STRSAFE_MAX_CCH * sizeof(char), &t)))
- goto cleanup;
-
- base_size = t + 1;
-
- if (FAILED(StringCbLengthA(postfix, STRSAFE_MAX_CCH * sizeof(char), &t)))
- goto cleanup;
-
- ret_size = base_size + t + 1;
-
- copy = malloc(base_size);
- ret = malloc(ret_size);
-
- if (!copy || !ret)
- goto cleanup;
-
- StringCbCopyNA(copy, base_size, base, base_size);
- StringCbCopyNA(ret, ret_size, base, base_size);
- StringCbCopyNA(ret + (base_size - 1), ret_size - (base_size - 1),
- postfix, ret_size - (base_size - 1));
-
- cleanup:
- if (!copy || !ret) {
- if (copy)
- free(copy);
- if (ret)
- free(ret);
- copy = ret = 0;
- }
- // INVARIANT: (ret ==> copy) && (copy ==> ret)
- *rcopy = copy;
- return ret;
-}
-
-void
-khm_krb4_set_def_tkt_string(void) {
- wchar_t wtkt_string[MAX_PATH];
- char tkt_string[MAX_PATH];
- khm_size cb;
-
- cb = sizeof(wtkt_string);
-
- if (KHM_FAILED(khc_read_string(csp_params, L"TktString",
- wtkt_string, &cb)) ||
- wtkt_string[0] == L'\0') {
-
- pkrb_set_tkt_string(0);
-
- } else {
-
- UnicodeStrToAnsi(tkt_string, sizeof(tkt_string),
- wtkt_string);
- pkrb_set_tkt_string(tkt_string);
- }
-}
-
-
-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;
-}
-
-long
-khm_krb4_changepwd(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;
-}
-
-struct tgt_filter_data {
- khm_handle identity;
- wchar_t realm[KCDB_IDENT_MAXCCH_NAME];
-};
-
-khm_int32 KHMAPI
-krb4_tgt_filter(khm_handle cred, khm_int32 flags, void * rock) {
- struct tgt_filter_data * pdata;
- wchar_t credname[KCDB_MAXCCH_NAME];
- wchar_t * t;
- khm_size cb;
- khm_int32 ctype;
-
- pdata = (struct tgt_filter_data *) rock;
- cb = sizeof(credname);
-
- if (KHM_FAILED(kcdb_cred_get_type(cred, &ctype)) ||
- ctype != credtype_id_krb4)
- return 0;
-
- if (KHM_FAILED(kcdb_cred_get_name(cred, credname, &cb)))
- return 0;
-
- if (wcsncmp(credname, L"krbtgt.", 7))
- return 0;
-
- t = wcsrchr(credname, L'@');
- if (t == NULL)
- return 0;
-
- if (wcscmp(t+1, pdata->realm))
- return 0;
-
- return 1;
-}
-
-khm_handle
-khm_krb4_find_tgt(khm_handle credset, khm_handle identity) {
- khm_handle result = NULL;
- wchar_t idname[KCDB_IDENT_MAXCCH_NAME];
- wchar_t * t;
- khm_size cb;
- struct tgt_filter_data filter_data;
-
- cb = sizeof(idname);
-
- if (KHM_FAILED(kcdb_identity_get_name(identity,
- idname,
- &cb)))
- return NULL;
-
- t = wcsrchr(idname, L'@');
- if (t == NULL)
- return NULL;
-
- StringCbCopy(filter_data.realm, sizeof(filter_data.realm),
- t + 1);
- filter_data.identity = identity;
-
- if (KHM_FAILED(kcdb_credset_find_filtered(credset,
- -1,
- krb4_tgt_filter,
- &filter_data,
- &result,
- NULL)))
- return NULL;
- else
- return result;
-}
-
-long
-khm_convert524(khm_handle identity)
-{
-#ifdef NO_KRB5
- return(0);
-#else
- 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.
- */
-
- code = khm_krb5_initialize(identity, &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;
-
- if (ctx)
- pkrb5_free_cred_contents(ctx, &increds);
-
- if (server) {
- pkrb5_free_principal(ctx, server);
- }
-
- if (me) {
- pkrb5_free_principal(ctx, me);
- }
-
- if (ctx && cc)
- pkrb5_cc_close(ctx, cc);
-
- if (ctx) {
- pkrb5_free_context(ctx);
- }
-
- return (code || icode);
-#endif /* NO_KRB5 */
-}
-
-long
-khm_krb4_kinit(char * aname,
- char * inst,
- char * realm,
- long lifetime,
- char * password) {
-
- wchar_t * functionName = NULL;
- wchar_t * err_context = NULL;
- int rc4 = 0;
- int msg = 0;
-
- if (pkname_parse == NULL) {
- goto cleanup;
- }
-
- err_context = L"getting realm";
- if (!*realm && (rc4 = (int)(*pkrb_get_lrealm)(realm, 1))) {
- functionName = L"krb_get_lrealm()";
- msg = IDS_ERR_REALM;
- goto cleanup;
- }
-
- err_context = L"checking principal";
- if ((!*aname) || (!(rc4 = (int)(*pk_isname)(aname)))) {
- functionName = L"krb_get_lrealm()";
- msg = IDS_ERR_PRINCIPAL;
- goto cleanup;
- }
-
- /* optional instance */
- if (!(rc4 = (int)(*pk_isinst)(inst))) {
- functionName = L"k_isinst()";
- msg = IDS_ERR_INVINST;
- goto cleanup;
- }
-
- if (!(rc4 = (int)(*pk_isrealm)(realm))) {
- functionName = L"k_isrealm()";
- msg = IDS_ERR_REALM;
- goto cleanup;
- }
-
- khm_krb4_set_def_tkt_string();
-
- err_context = L"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 = L"krb_get_pw_in_tkt()";
- msg = IDS_ERR_PWINTKT;
- goto cleanup;
- }
-
- return 0;
-
- cleanup:
- {
- _report_sr0(KHERR_ERROR, msg);
- _location(functionName);
- }
- return rc4;
-}
-
-
-int khm_krb4_kdestroy(void) {
- int k_errno = 0;
-
- if (pdest_tkt != NULL)
- {
- k_errno = (*pdest_tkt)();
- if (k_errno && (k_errno != RET_TKFIL))
- return KRBERR(k_errno);
- }
-
- return k_errno;
-}
+/* +* Copyright (c) 2005 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 <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 ptktname[MAX_PATH + 5]; + char pname[ANAME_SZ]; + char pinst[INST_SZ]; + char prealm[REALM_SZ]; + wchar_t wbuf[256]; + int k_errno = 0; + CREDENTIALS c; + int newtickets = 0; + int open = 0; + khm_handle ident = NULL; + khm_handle cred = NULL; + time_t tt; + FILETIME ft; + + kcdb_credset_flush(krb4_credset); + + // 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) + goto collect; + + 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; + } + + StringCchCopyA(ptktname, ARRAYLENGTH(ptktname), (*ptkt_string)()); + + 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; + } + + // 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)); + + AnsiStrToUnicode(wbuf, sizeof(wbuf), ptktname); + kcdb_cred_set_attr(cred, KCDB_ATTR_LOCATION, wbuf, KCDB_CBSIZE_AUTO); + + kcdb_credset_add_cred(krb4_credset, cred, -1); + + kcdb_cred_release(cred); + } // while + + 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 + + collect: + kcdb_credset_collect(NULL, krb4_credset, ident, credtype_id_krb4, NULL); + + return k_errno; +} + +#define KRB_FILE "KRB.CON" +#define KRBREALM_FILE "KRBREALM.CON" +#define KRB5_FILE "KRB5.INI" + +BOOL +khm_krb5_get_profile_file(LPSTR confname, UINT szConfname) +{ + char **configFile = NULL; + if (pkrb5_get_default_config_files(&configFile)) + { + GetWindowsDirectoryA(confname,szConfname); + confname[szConfname-1] = '\0'; + + StringCchCatA(confname, szConfname, "\\"); + StringCchCatA(confname, szConfname, KRB5_FILE); + + return FALSE; + } + + *confname = 0; + + if (configFile) + { + StringCchCopyA(confname, szConfname, *configFile); + pkrb5_free_config_files(configFile); + } + + if (!*confname) + { + GetWindowsDirectoryA(confname,szConfname); + confname[szConfname-1] = '\0'; + + StringCchCatA(confname, szConfname, "\\"); + StringCchCatA(confname, szConfname, KRB5_FILE); + } + + 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; + + if (khm_krb5_get_profile_file(krbConFile, sizeof(krbConFile))) { + GetWindowsDirectoryA(krbConFile,sizeof(krbConFile)); + krbConFile[MAX_PATH-1] = '\0'; + + StringCbCatA(krbConFile, sizeof(krbConFile), "\\"); + } + + pFind = strrchr(krbConFile, '\\'); + + if (pFind) { + *pFind = '\0'; + + StringCbCatA(krbConFile, sizeof(krbConFile), "\\"); + StringCbCatA(krbConFile, sizeof(krbConFile), KRB_FILE); + } else { + krbConFile[0] = '\0'; + } + + StringCchCopyA(confname, szConfname, krbConFile); + } else if (hKrb4) { + unsigned int size = szConfname; + memset(confname, '\0', szConfname); + if (!pkrb_get_krbconf2(confname, &size)) { + GetWindowsDirectoryA(confname,szConfname); + confname[szConfname-1] = '\0'; + StringCchCatA(confname, szConfname, "\\"); + StringCchCatA(confname, szConfname, KRB_FILE); + } + } + + 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_krb5_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, §ions); + + 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 = PMALLOC(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)) && +#if _MSC_VER >= 1400 + !fopen_s(&file, krb_conf, "rt") +#else + (file = fopen(krb_conf, "rt")) +#endif + ) + { + char lineBuf[256]; + + /*TODO: compute the actual required buffer size instead of hardcoding */ + cbsize = 16384; // arbitrary + rlist = PMALLOC(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 = PMALLOC(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; +} + +static +char * +make_postfix(const char * base, + const char * postfix, + char ** rcopy) +{ + size_t base_size; + size_t ret_size; + char * copy = 0; + char * ret = 0; + size_t t; + + if (FAILED(StringCbLengthA(base, STRSAFE_MAX_CCH * sizeof(char), &t))) + goto cleanup; + + base_size = t + 1; + + if (FAILED(StringCbLengthA(postfix, STRSAFE_MAX_CCH * sizeof(char), &t))) + goto cleanup; + + ret_size = base_size + t + 1; + + copy = malloc(base_size); + ret = malloc(ret_size); + + if (!copy || !ret) + goto cleanup; + + StringCbCopyNA(copy, base_size, base, base_size); + StringCbCopyNA(ret, ret_size, base, base_size); + StringCbCopyNA(ret + (base_size - 1), ret_size - (base_size - 1), + postfix, ret_size - (base_size - 1)); + + cleanup: + if (!copy || !ret) { + if (copy) + free(copy); + if (ret) + free(ret); + copy = ret = 0; + } + // INVARIANT: (ret ==> copy) && (copy ==> ret) + *rcopy = copy; + return ret; +} + +void +khm_krb4_set_def_tkt_string(void) { + wchar_t wtkt_string[MAX_PATH]; + char tkt_string[MAX_PATH]; + khm_size cb; + + cb = sizeof(wtkt_string); + + if (KHM_FAILED(khc_read_string(csp_params, L"TktString", + wtkt_string, &cb)) || + wtkt_string[0] == L'\0') { + + pkrb_set_tkt_string(0); + + } else { + + UnicodeStrToAnsi(tkt_string, sizeof(tkt_string), + wtkt_string); + pkrb_set_tkt_string(tkt_string); + } +} + + +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; +} + +long +khm_krb4_changepwd(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; +} + +struct tgt_filter_data { + khm_handle identity; + wchar_t realm[KCDB_IDENT_MAXCCH_NAME]; +}; + +khm_int32 KHMAPI +krb4_tgt_filter(khm_handle cred, khm_int32 flags, void * rock) { + struct tgt_filter_data * pdata; + wchar_t credname[KCDB_MAXCCH_NAME]; + wchar_t * t; + khm_size cb; + khm_int32 ctype; + + pdata = (struct tgt_filter_data *) rock; + cb = sizeof(credname); + + if (KHM_FAILED(kcdb_cred_get_type(cred, &ctype)) || + ctype != credtype_id_krb4) + return 0; + + if (KHM_FAILED(kcdb_cred_get_name(cred, credname, &cb))) + return 0; + + if (wcsncmp(credname, L"krbtgt.", 7)) + return 0; + + t = wcsrchr(credname, L'@'); + if (t == NULL) + return 0; + + if (wcscmp(t+1, pdata->realm)) + return 0; + + return 1; +} + +khm_handle +khm_krb4_find_tgt(khm_handle credset, khm_handle identity) { + khm_handle result = NULL; + wchar_t idname[KCDB_IDENT_MAXCCH_NAME]; + wchar_t * t; + khm_size cb; + struct tgt_filter_data filter_data; + + cb = sizeof(idname); + + if (KHM_FAILED(kcdb_identity_get_name(identity, + idname, + &cb))) + return NULL; + + t = wcsrchr(idname, L'@'); + if (t == NULL) + return NULL; + + StringCbCopy(filter_data.realm, sizeof(filter_data.realm), + t + 1); + filter_data.identity = identity; + + if (KHM_FAILED(kcdb_credset_find_filtered(credset, + -1, + krb4_tgt_filter, + &filter_data, + &result, + NULL))) + return NULL; + else + return result; +} + +long +khm_convert524(khm_handle identity) +{ +#ifdef NO_KRB5 + return(0); +#else + 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. + */ + + code = khm_krb5_initialize(identity, &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; + + if (ctx) + pkrb5_free_cred_contents(ctx, &increds); + + if (server) { + pkrb5_free_principal(ctx, server); + } + + if (me) { + pkrb5_free_principal(ctx, me); + } + + if (ctx && cc) + pkrb5_cc_close(ctx, cc); + + if (ctx) { + pkrb5_free_context(ctx); + } + + return (code || icode); +#endif /* NO_KRB5 */ +} + +long +khm_krb4_kinit(char * aname, + char * inst, + char * realm, + long lifetime, + char * password) { + + wchar_t * functionName = NULL; + wchar_t * err_context = NULL; + int rc4 = 0; + int msg = 0; + + if (pkname_parse == NULL) { + goto cleanup; + } + + err_context = L"getting realm"; + if (!*realm && (rc4 = (int)(*pkrb_get_lrealm)(realm, 1))) { + functionName = L"krb_get_lrealm()"; + msg = IDS_ERR_REALM; + goto cleanup; + } + + err_context = L"checking principal"; + if ((!*aname) || (!(rc4 = (int)(*pk_isname)(aname)))) { + functionName = L"krb_get_lrealm()"; + msg = IDS_ERR_PRINCIPAL; + goto cleanup; + } + + /* optional instance */ + if (!(rc4 = (int)(*pk_isinst)(inst))) { + functionName = L"k_isinst()"; + msg = IDS_ERR_INVINST; + goto cleanup; + } + + if (!(rc4 = (int)(*pk_isrealm)(realm))) { + functionName = L"k_isrealm()"; + msg = IDS_ERR_REALM; + goto cleanup; + } + + khm_krb4_set_def_tkt_string(); + + err_context = L"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 = L"krb_get_pw_in_tkt()"; + msg = IDS_ERR_PWINTKT; + goto cleanup; + } + + return 0; + + cleanup: + { + _report_sr0(KHERR_ERROR, msg); + _location(functionName); + } + return rc4; +} + + +int khm_krb4_kdestroy(void) { + int k_errno = 0; + + if (pdest_tkt != NULL) + { + k_errno = (*pdest_tkt)(); + if (k_errno && (k_errno != RET_TKFIL)) + return KRBERR(k_errno); + } + + return k_errno; +} diff --git a/src/windows/identity/plugins/krb4/krb4funcs.h b/src/windows/identity/plugins/krb4/krb4funcs.h index 5ec11cc63..05ed3e75d 100644 --- a/src/windows/identity/plugins/krb4/krb4funcs.h +++ b/src/windows/identity/plugins/krb4/krb4funcs.h @@ -1,132 +1,132 @@ -/*
- * Copyright (c) 2005 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>
-
-#if _WIN32_WINNT < 0x0501
-#define KHM_SAVE_WIN32_WINNT _WIN32_WINNT
-#undef _WIN32_WINNT
-#define _WIN32_WINNT 0x0501
-#endif
-#include<ntsecapi.h>
-#ifdef KHM_SAVE_WIN32_WINNT
-#undef _WIN32_WINNT
-#define _WIN32_WINNT KHM_SAVE_WIN32_WINNT
-#undef KHM_SAVE_WIN32_WINNT
-#endif
-
-#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 */
-
-
-long
-khm_convert524(khm_handle identity);
-
-long
-khm_krb4_kinit(char * aname,
- char * inst,
- char * realm,
- long lifetime,
- char * password);
-
-long
-khm_krb4_list_tickets(void);
-
-int khm_krb4_kdestroy(void);
-
-khm_handle
-khm_krb4_find_tgt(khm_handle credset,
- khm_handle identity);
-
-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
- );
-
-void
-khm_krb4_set_def_tkt_string(void);
-
-wchar_t * khm_krb5_get_default_realm(void);
-wchar_t * khm_krb5_get_realm_list(void);
-
-#endif
+/* + * Copyright (c) 2005 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> + +#if _WIN32_WINNT < 0x0501 +#define KHM_SAVE_WIN32_WINNT _WIN32_WINNT +#undef _WIN32_WINNT +#define _WIN32_WINNT 0x0501 +#endif +#include<ntsecapi.h> +#ifdef KHM_SAVE_WIN32_WINNT +#undef _WIN32_WINNT +#define _WIN32_WINNT KHM_SAVE_WIN32_WINNT +#undef KHM_SAVE_WIN32_WINNT +#endif + +#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 */ + + +long +khm_convert524(khm_handle identity); + +long +khm_krb4_kinit(char * aname, + char * inst, + char * realm, + long lifetime, + char * password); + +long +khm_krb4_list_tickets(void); + +int khm_krb4_kdestroy(void); + +khm_handle +khm_krb4_find_tgt(khm_handle credset, + khm_handle identity); + +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 + ); + +void +khm_krb4_set_def_tkt_string(void); + +wchar_t * khm_krb5_get_default_realm(void); +wchar_t * khm_krb5_get_realm_list(void); + +#endif diff --git a/src/windows/identity/plugins/krb4/krb4main.c b/src/windows/identity/plugins/krb4/krb4main.c index 57e33a8d8..7ab2d71f3 100644 --- a/src/windows/identity/plugins/krb4/krb4main.c +++ b/src/windows/identity/plugins/krb4/krb4main.c @@ -1,157 +1,157 @@ -/*
- * Copyright (c) 2005 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_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 = LoadImage(hResModule, MAKEINTRESOURCE(IDI_PLUGIN),
- IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR | LR_DEFAULTSIZE);
- 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;
-
- 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;
-}
+/* + * Copyright (c) 2005 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_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 = LoadImage(hResModule, MAKEINTRESOURCE(IDI_PLUGIN), + IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR | LR_DEFAULTSIZE); + 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; + + 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/krb4/krb4newcreds.c b/src/windows/identity/plugins/krb4/krb4newcreds.c index 54feae5b3..c2d477e0e 100644 --- a/src/windows/identity/plugins/krb4/krb4newcreds.c +++ b/src/windows/identity/plugins/krb4/krb4newcreds.c @@ -1,873 +1,873 @@ -/*
- * Copyright (c) 2005 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<utils.h>
-#include<commctrl.h>
-#include<strsafe.h>
-#include<krb5.h>
-#include<assert.h>
-
-/* method identifiers should be contiguous */
-#define K4_METHOD_AUTO 0
-#define K4_METHOD_PASSWORD 1
-#define K4_METHOD_K524 2
-
-int method_to_id[] = {
- IDC_NCK4_AUTO,
- IDC_NCK4_PWD,
- IDC_NCK4_K524
-};
-
-typedef struct tag_k4_dlg_data {
- HWND hwnd;
- khui_new_creds * nc;
- khui_new_creds_by_type * nct;
-
- khm_boolean k4_enabled;
- khm_int32 method;
- time_t lifetime;
-} k4_dlg_data;
-
-void k4_update_display(k4_dlg_data * d, BOOL update_methods) {
- CheckDlgButton(d->hwnd, IDC_NCK4_OBTAIN,
- (d->k4_enabled)?BST_CHECKED: BST_UNCHECKED);
-
- if (d->k4_enabled) {
- EnableWindow(GetDlgItem(d->hwnd, IDC_NCK4_AUTO), TRUE);
- EnableWindow(GetDlgItem(d->hwnd, IDC_NCK4_K524), TRUE);
- EnableWindow(GetDlgItem(d->hwnd, IDC_NCK4_PWD ), TRUE);
- } else {
- EnableWindow(GetDlgItem(d->hwnd, IDC_NCK4_AUTO), FALSE);
- EnableWindow(GetDlgItem(d->hwnd, IDC_NCK4_K524), FALSE);
- EnableWindow(GetDlgItem(d->hwnd, IDC_NCK4_PWD ), FALSE);
- }
-
-#ifdef DEBUG
- assert(d->method >= 0 && d->method < ARRAYLENGTH(method_to_id));
-#endif
-
- CheckRadioButton(d->hwnd, IDC_NCK4_AUTO, IDC_NCK4_PWD, method_to_id[d->method]);
-
- khui_cw_enable_type(d->nc, credtype_id_krb4, d->k4_enabled);
-}
-
-void k4_update_data(k4_dlg_data * d) {
- int i;
- khm_boolean oldstate;
-
- oldstate = d->k4_enabled;
-
- if (IsDlgButtonChecked(d->hwnd, IDC_NCK4_OBTAIN) == BST_CHECKED)
- d->k4_enabled = TRUE;
- else
- d->k4_enabled = FALSE;
-
- if ((oldstate && !d->k4_enabled) ||
- (!oldstate && d->k4_enabled)) {
-
- khui_cw_enable_type(d->nc, credtype_id_krb4, d->k4_enabled);
- }
-
- d->method = K4_METHOD_AUTO;
-
- for (i=K4_METHOD_AUTO; i<=K4_METHOD_K524; i++) {
- if (IsDlgButtonChecked(d->hwnd, method_to_id[i]) == BST_CHECKED) {
- d->method = i;
- break;
- }
- }
-}
-
-khm_boolean k4_should_identity_get_k4(khm_handle ident) {
- khm_int32 idflags = 0;
- khm_int32 t = TRUE;
- khm_handle csp_ident = NULL;
- khm_handle csp_k4 = NULL;
- khm_boolean get_k4 = TRUE;
- khm_boolean id_spec = FALSE;
-
- if (KHM_FAILED(kcdb_identity_get_flags(ident, &idflags)))
- return FALSE;
-
- if (!(idflags & KCDB_IDENT_FLAG_DEFAULT)) {
- /* we only support k4 for one identity, and that is the
- default identity. If we are trying to get tickets for a
- non-default identity, then we start off as disabled unless
- there is no default identity. */
-
- khm_handle defident = NULL;
-
- if (KHM_SUCCEEDED(kcdb_identity_get_default(&defident))) {
- kcdb_identity_release(defident);
-
- return FALSE;
- }
- }
-
- if (KHM_SUCCEEDED(kcdb_identity_get_config(ident, 0, &csp_ident))) {
- if (KHM_SUCCEEDED(khc_open_space(csp_ident, CSNAME_KRB4CRED, 0,
- &csp_k4))) {
- khm_int32 t = 0;
-
- if (KHM_SUCCEEDED(khc_read_int32(csp_k4, L"Krb4NewCreds", &t))) {
- get_k4 = !!t;
- id_spec = TRUE;
- }
-
- khc_close_space(csp_k4);
- }
- khc_close_space(csp_ident);
- }
-
- /* if there was a value specified for the identity, then that
- takes precedence. */
- if (id_spec || !get_k4)
- return get_k4;
-
- if (KHM_SUCCEEDED(khc_read_int32(csp_params, L"Krb4NewCreds", &t)) &&
- !t)
- return FALSE;
-
- return TRUE;
-}
-
-void k4_read_identity_data(k4_dlg_data * d) {
- khm_handle csp_ident = NULL;
- khm_handle csp_k4 = NULL;
-
- khm_int32 idflags = 0;
- khm_int32 t;
-
- if (KHM_SUCCEEDED(khc_read_int32(csp_params, L"Krb4NewCreds", &t)))
- d->k4_enabled = !!t;
- else
- d->k4_enabled = TRUE;
-
- if (KHM_SUCCEEDED(khc_read_int32(csp_params, L"Krb4Method", &t)))
- d->method = t;
- else
- d->method = K4_METHOD_AUTO;
-
- if (KHM_SUCCEEDED(khc_read_int32(csp_params, L"DefaultLifetime", &t)))
- d->lifetime = t;
- else
- d->lifetime = 10 * 60 * 60; /* 10 hours */
-
- if (d->nc->n_identities > 0 &&
- d->nc->identities[0]) {
-
- if (KHM_SUCCEEDED(kcdb_identity_get_config(d->nc->identities[0],
- 0,
- &csp_ident))) {
-
- khc_open_space(csp_ident, CSNAME_KRB4CRED, 0, &csp_k4);
-
- if (csp_k4) {
- if (KHM_SUCCEEDED(khc_read_int32(csp_k4, L"Krb4NewCreds", &t)))
- d->k4_enabled = !!t;
- if (KHM_SUCCEEDED(khc_read_int32(csp_k4, L"Krb4Method", &t)))
- d->method = t;
- khc_close_space(csp_k4);
- }
-
- khc_close_space(csp_ident);
- }
-
- if (d->k4_enabled) {
- d->k4_enabled = k4_should_identity_get_k4(d->nc->identities[0]);
- }
- } else {
- d->k4_enabled = FALSE;
- }
-
- if (d->method < 0 || d->method > K4_METHOD_K524)
- d->method = K4_METHOD_AUTO;
-}
-
-void k4_write_identity_data(k4_dlg_data * d) {
- khm_handle csp_ident = NULL;
- khm_handle csp_k4 = NULL;
-
- if (d->nc->n_identities > 0 &&
- d->nc->identities[0] &&
- KHM_SUCCEEDED(kcdb_identity_get_config(d->nc->identities[0],
- KHM_FLAG_CREATE,
- &csp_ident))) {
- khc_open_space(csp_ident, CSNAME_KRB4CRED,
- KHM_FLAG_CREATE | KCONF_FLAG_WRITEIFMOD,
- &csp_k4);
-
- if (csp_k4) {
- khc_write_int32(csp_k4, L"Krb4NewCreds", !!d->k4_enabled);
- khc_write_int32(csp_k4, L"Krb4Method", d->method);
-
- khc_close_space(csp_k4);
- }
-
- khc_close_space(csp_ident);
- }
-}
-
-void k4_handle_wmnc_notify(k4_dlg_data * d,
- WPARAM wParam,
- LPARAM lParam) {
- switch(HIWORD(wParam)) {
- case WMNC_UPDATE_CREDTEXT:
- {
- if (d->nct->credtext) {
- PFREE(d->nct->credtext);
- d->nct->credtext = NULL;
- }
-
- if (d->nc->n_identities > 0 &&
- d->nc->identities[0]) {
-
- khm_int32 flags = 0;
- wchar_t idname[KCDB_IDENT_MAXCCH_NAME];
- wchar_t * atsign;
- wchar_t * realm;
- khm_size cb;
-
- kcdb_identity_get_flags(d->nc->identities[0], &flags);
-
- if (!(flags & KCDB_IDENT_FLAG_VALID)) {
- break;
- }
-
- cb = sizeof(idname);
- kcdb_identity_get_name(d->nc->identities[0], idname,
- &cb);
-
- atsign = wcsrchr(idname, L'@');
-
- if (atsign == NULL || !atsign[1])
- break;
-
- realm = ++atsign;
-
- if (d->k4_enabled) {
- wchar_t wmethod[128];
- wchar_t wfmt[128];
- wchar_t wct[512];
-
- LoadString(hResModule, IDS_CT_TGTFOR,
- wfmt, ARRAYLENGTH(wfmt));
-
- if (d->method == K4_METHOD_AUTO)
- LoadString(hResModule, IDS_METHOD_AUTO, wmethod,
- ARRAYLENGTH(wmethod));
- else if (d->method == K4_METHOD_PASSWORD)
- LoadString(hResModule, IDS_METHOD_PWD, wmethod,
- ARRAYLENGTH(wmethod));
- else if (d->method == K4_METHOD_K524)
- LoadString(hResModule, IDS_METHOD_K524, wmethod,
- ARRAYLENGTH(wmethod));
- else {
- assert(FALSE);
- }
-
- StringCbPrintf(wct, sizeof(wct), wfmt, realm, wmethod);
-
- StringCbLength(wct, sizeof(wct), &cb);
- cb += sizeof(wchar_t);
-
- d->nct->credtext = PMALLOC(cb);
-
- StringCbCopy(d->nct->credtext, cb, wct);
- } else {
- wchar_t wct[256];
-
- LoadString(hResModule, IDS_CT_DISABLED,
- wct, ARRAYLENGTH(wct));
-
- StringCbLength(wct, sizeof(wct), &cb);
- cb += sizeof(wchar_t);
-
- d->nct->credtext = PMALLOC(cb);
-
- StringCbCopy(d->nct->credtext, cb, wct);
- }
- }
- /* no identities were selected. it is not the
- responsibility of krb4 to complain about this. */
- }
- break;
-
- case WMNC_IDENTITY_CHANGE:
- k4_read_identity_data(d);
- k4_update_display(d, TRUE);
- break;
-
- case WMNC_CREDTEXT_LINK:
- {
- wchar_t wid[KHUI_MAXCCH_HTLINK_FIELD];
- wchar_t * wids;
- khui_htwnd_link * l;
-
- l = (khui_htwnd_link *) lParam;
-
- StringCchCopyN(wid, ARRAYLENGTH(wid), l->id, l->id_len);
- wids = wcschr(wid, L':');
-
- if (!wids)
- break;
- else
- wids++;
-
- if (!wcscmp(wids, L"Enable")) {
- d->k4_enabled = TRUE;
-
- k4_update_display(d, TRUE);
- khui_cw_enable_type(d->nc, credtype_id_krb4, TRUE);
- }
- }
- break;
- }
-}
-
-INT_PTR CALLBACK k4_nc_dlg_proc(HWND hwnd,
- UINT uMsg,
- WPARAM wParam,
- LPARAM lParam) {
-
- k4_dlg_data * d;
-
- switch(uMsg) {
- case WM_INITDIALOG:
- {
- d = PMALLOC(sizeof(*d));
- ZeroMemory(d, sizeof(*d));
-
- d->nc = (khui_new_creds *) lParam;
- khui_cw_find_type(d->nc, credtype_id_krb4, &d->nct);
-
-#pragma warning(push)
-#pragma warning(disable: 4244)
- SetWindowLongPtr(hwnd, DWLP_USER, (LPARAM) d);
-#pragma warning(pop)
-
- d->nct->aux = (LPARAM) d;
- d->hwnd = hwnd;
-
- d->k4_enabled = TRUE;
- d->method = K4_METHOD_AUTO;
-
- k4_update_display(d, TRUE);
- }
- break;
-
- case WM_COMMAND:
- {
- if (HIWORD(wParam) == BN_CLICKED) {
- d = (k4_dlg_data *) (LONG_PTR)
- GetWindowLongPtr(hwnd, DWLP_USER);
-
- k4_update_data(d);
-
- if (LOWORD(wParam) == IDC_NCK4_OBTAIN) {
- k4_update_display(d, TRUE);
- }
-
- return TRUE;
- }
- }
- break;
-
- case KHUI_WM_NC_NOTIFY:
- {
- d = (k4_dlg_data *) (LONG_PTR)
- GetWindowLongPtr(hwnd, DWLP_USER);
- k4_handle_wmnc_notify(d, wParam, lParam);
- }
- break;
-
- case WM_DESTROY:
- {
- d = (k4_dlg_data *) (LONG_PTR)
- GetWindowLongPtr(hwnd, DWLP_USER);
-
- d->nct->aux = 0;
-
- PFREE(d);
- }
- break;
- }
-
- return FALSE;
-}
-
-khm_int32
-krb4_msg_newcred(khm_int32 msg_type, khm_int32 msg_subtype,
- khm_ui_4 uparam, void * vparam) {
-
- switch(msg_subtype) {
- case KMSG_CRED_NEW_CREDS:
- {
- khui_new_creds * nc;
- khui_new_creds_by_type * nct;
- khm_size cbsize;
- wchar_t wbuf[256];
-
- nc = (khui_new_creds *) vparam;
-
- nct = PMALLOC(sizeof(*nct));
-#ifdef DEBUG
- assert(nct);
-#endif
- ZeroMemory(nct, sizeof(*nct));
-
- nct->type = credtype_id_krb4;
- nct->ordinal = 3;
- LoadString(hResModule, IDS_NC_K4_SHORT,
- wbuf, ARRAYLENGTH(wbuf));
- StringCbLength(wbuf, sizeof(wbuf), &cbsize);
- cbsize += sizeof(wchar_t);
-
- nct->name = PMALLOC(cbsize);
- StringCbCopy(nct->name, cbsize, wbuf);
-
- nct->type_deps[nct->n_type_deps++] = credtype_id_krb5;
-
- nct->h_module = hResModule;
- nct->dlg_proc = k4_nc_dlg_proc;
- nct->dlg_template = MAKEINTRESOURCE(IDD_NC_KRB4);
-
- khui_cw_add_type(nc, nct);
- }
- break;
-
- case KMSG_CRED_RENEW_CREDS:
- {
- khui_new_creds * nc;
- khui_new_creds_by_type * nct;
- khm_size cbsize;
- wchar_t wbuf[256];
-
- nc = (khui_new_creds *) vparam;
-
- if (!nc->ctx.identity)
- break;
-
- nct = PMALLOC(sizeof(*nct));
-#ifdef DEBUG
- assert(nct);
-#endif
-
- ZeroMemory(nct, sizeof(*nct));
-
- nct->type = credtype_id_krb4;
- nct->ordinal = 3;
- LoadString(hResModule, IDS_NC_K4_SHORT,
- wbuf, ARRAYLENGTH(wbuf));
- StringCbLength(wbuf, sizeof(wbuf), &cbsize);
- cbsize += sizeof(wchar_t);
-
- nct->name = PMALLOC(cbsize);
- StringCbCopy(nct->name, cbsize, wbuf);
-
- nct->type_deps[nct->n_type_deps++] = credtype_id_krb5;
-
- khui_cw_add_type(nc, nct);
- }
- break;
-
- case KMSG_CRED_DIALOG_SETUP:
- break;
-
- case KMSG_CRED_PROCESS:
- {
- khui_new_creds * nc;
- khui_new_creds_by_type * nct = NULL;
- khm_handle ident = NULL;
- k4_dlg_data * d = NULL;
- long code = 0;
- wchar_t idname[KCDB_IDENT_MAXCCH_NAME];
- khm_size cb;
-
- nc = (khui_new_creds *) vparam;
- if (KHM_FAILED(khui_cw_find_type(nc, credtype_id_krb4, &nct)))
- break;
-
- if (nc->subtype == KMSG_CRED_NEW_CREDS ||
- nc->subtype == KMSG_CRED_RENEW_CREDS) {
- khm_int32 method;
-
- if (nc->subtype == KMSG_CRED_NEW_CREDS) {
-
- d = (k4_dlg_data *) nct->aux;
- if (!d ||
- nc->n_identities == 0 ||
- nc->identities[0] == NULL ||
- nc->result != KHUI_NC_RESULT_PROCESS) {
- khui_cw_set_response(nc, credtype_id_krb4,
- KHUI_NC_RESPONSE_SUCCESS |
- KHUI_NC_RESPONSE_EXIT);
- break;
- }
-
- if (!d->k4_enabled) {
- k4_write_identity_data(d);
- khui_cw_set_response(nc, credtype_id_krb4,
- KHUI_NC_RESPONSE_SUCCESS |
- KHUI_NC_RESPONSE_EXIT);
- break;
- }
-
- method = d->method;
- ident = nc->identities[0];
-
- cb = sizeof(idname);
- kcdb_identity_get_name(ident, idname, &cb);
- _begin_task(0);
- _report_mr2(KHERR_NONE, MSG_K4_NEW_CREDS,
- _cstr(ident), _int32(method));
- _resolve();
- _describe();
-
- } else if (nc->subtype == KMSG_CRED_RENEW_CREDS) {
-
- if ((nc->ctx.scope == KHUI_SCOPE_IDENT &&
- nc->ctx.identity != NULL) ||
-
- (nc->ctx.scope == KHUI_SCOPE_CREDTYPE &&
- nc->ctx.cred_type == credtype_id_krb4 &&
- nc->ctx.identity != NULL) ||
-
- (nc->ctx.scope == KHUI_SCOPE_CRED &&
- nc->ctx.cred_type == credtype_id_krb4 &&
- nc->ctx.identity != NULL &&
- nc->ctx.cred != NULL)) {
-
- ident = nc->ctx.identity;
-
- if (!k4_should_identity_get_k4(ident)) {
-
- _reportf(L"Kerberos 4 is not enabled for this identity. Skipping");
-
- khui_cw_set_response(nc, credtype_id_krb4,
- KHUI_NC_RESPONSE_FAILED |
- KHUI_NC_RESPONSE_EXIT);
- break;
- }
-
- } else {
-
- _reportf(L"Kerberos 4 is not within renewal scope. Skipping");
-
- khui_cw_set_response(nc, credtype_id_krb4,
- KHUI_NC_RESPONSE_FAILED |
- KHUI_NC_RESPONSE_EXIT);
- break;
- }
-
- method = K4_METHOD_K524; /* only k524 is supported
- for renewals */
-
- _begin_task(0);
- cb = sizeof(idname);
- kcdb_identity_get_name(ident, idname, &cb);
- _report_mr2(KHERR_NONE, MSG_K4_RENEW_CREDS,
- _cstr(ident), _int32(method));
- _resolve();
- _describe();
- } else {
- assert(FALSE);
- break;
- }
-
- if ((method == K4_METHOD_AUTO ||
- method == K4_METHOD_K524) &&
- khui_cw_type_succeeded(nc, credtype_id_krb5)) {
-
- khm_handle tgt;
- FILETIME ft_prev;
- FILETIME ft_new;
- khm_size cb;
-
- _report_mr0(KHERR_INFO, MSG_K4_TRY_K524);
-
- tgt = khm_krb4_find_tgt(NULL, ident);
- if (tgt) {
- cb = sizeof(ft_prev);
- if (KHM_FAILED(kcdb_cred_get_attr(tgt,
- KCDB_ATTR_EXPIRE,
- NULL,
- &ft_prev,
- &cb)))
- ZeroMemory(&ft_prev, sizeof(ft_prev));
- kcdb_cred_release(tgt);
- }
-
- code = khm_convert524(ident);
-
- _reportf(L"khm_convert524 returns code %d", code);
-
- if (code == 0) {
- khui_cw_set_response(nc, credtype_id_krb4,
- KHUI_NC_RESPONSE_SUCCESS |
- KHUI_NC_RESPONSE_EXIT);
-
- if (nc->subtype == KMSG_CRED_NEW_CREDS) {
- assert(d != NULL);
-
- k4_write_identity_data(d);
-
- } else if (nc->subtype == KMSG_CRED_RENEW_CREDS &&
- (nc->ctx.scope == KHUI_SCOPE_CREDTYPE ||
- nc->ctx.scope == KHUI_SCOPE_CRED)) {
-
- khm_krb4_list_tickets();
-
- tgt = khm_krb4_find_tgt(NULL, ident);
-
- if (tgt) {
- cb = sizeof(ft_new);
- ZeroMemory(&ft_new, sizeof(ft_new));
-
- kcdb_cred_get_attr(tgt,
- KCDB_ATTR_EXPIRE,
- NULL,
- &ft_new,
- &cb);
-
- kcdb_cred_release(tgt);
- }
-
- if (!tgt ||
- CompareFileTime(&ft_new,
- &ft_prev) <= 0) {
- /* The new TGT wasn't much of an
- improvement over what we already
- had. We should go out and try to
- renew the identity now. */
-
- khui_action_context ctx;
-
- _reportf(L"Renewal of Krb4 creds failed to get a longer TGT. Triggering identity renewal");
-
- khui_context_create(&ctx,
- KHUI_SCOPE_IDENT,
- nc->ctx.identity,
- KCDB_CREDTYPE_INVALID,
- NULL);
- khui_action_trigger(KHUI_ACTION_RENEW_CRED,
- &ctx);
-
- khui_context_release(&ctx);
- }
- }
-
- _end_task();
- break;
-
- } else if (method == K4_METHOD_K524) {
- khui_cw_set_response(nc, credtype_id_krb4,
- KHUI_NC_RESPONSE_FAILED |
- KHUI_NC_RESPONSE_EXIT);
-
- if (nc->subtype == KMSG_CRED_RENEW_CREDS &&
- (nc->ctx.scope == KHUI_SCOPE_CREDTYPE ||
- nc->ctx.scope == KHUI_SCOPE_CRED)) {
- /* We were trying to get a new Krb4 TGT
- for this identity. Sometimes this
- fails because of restrictions placed on
- K524d regarding the lifetime of the
- issued K4 TGT. In this case, we
- trigger a renewal of the identity in
- the hope that the new K5 TGT will allow
- us to successfully get a new K4 TGT
- next time over using the new K5 TGT. */
-
- khui_action_context ctx;
-
- _reportf(L"Renewal of Krb4 creds failed using k524. Triggerring identity renewal.");
-
- khui_context_create(&ctx,
- KHUI_SCOPE_IDENT,
- nc->ctx.identity,
- KCDB_CREDTYPE_INVALID,
- NULL);
-
- khui_action_trigger(KHUI_ACTION_RENEW_CRED,
- &ctx);
-
- khui_context_release(&ctx);
- }
-
- _end_task();
- break;
-
- }
- }
-
- /* only supported for new credentials */
- if (method == K4_METHOD_AUTO ||
- method == K4_METHOD_PASSWORD) {
-
- khm_size n_prompts = 0;
- khm_size idx;
- khm_size cb;
- wchar_t wpwd[KHUI_MAXCCH_PROMPT_VALUE];
- char pwd[KHUI_MAXCCH_PROMPT_VALUE];
- wchar_t widname[KCDB_IDENT_MAXCCH_NAME];
- char idname[KCDB_IDENT_MAXCCH_NAME];
-
- char * aname = NULL;
- char * inst = NULL;
- char * realm = NULL;
-
- assert(nc->subtype == KMSG_CRED_NEW_CREDS);
-
- _report_mr0(KHERR_INFO, MSG_K4_TRY_PASSWORD);
-
- code = TRUE; /* just has to be non-zero */
-
- khui_cw_get_prompt_count(nc, &n_prompts);
-
- if (n_prompts == 0)
- goto _skip_pwd;
-
- for (idx = 0; idx < n_prompts; idx++) {
- khui_new_creds_prompt * p;
-
- if (KHM_FAILED(khui_cw_get_prompt(nc, idx, &p)))
- continue;
-
- if (p->type == KHUI_NCPROMPT_TYPE_PASSWORD)
- break;
- }
-
- if (idx >= n_prompts) {
- _reportf(L"Password prompt not found");
- goto _skip_pwd;
- }
-
- khui_cw_sync_prompt_values(nc);
-
- cb = sizeof(wpwd);
- if (KHM_FAILED(khui_cw_get_prompt_value(nc, idx,
- wpwd,
- &cb))) {
- _reportf(L"Failed to obtain password value");
- goto _skip_pwd;
- }
-
- UnicodeStrToAnsi(pwd, sizeof(pwd), wpwd);
-
- cb = sizeof(widname);
- kcdb_identity_get_name(ident,
- widname,
- &cb);
-
- UnicodeStrToAnsi(idname, sizeof(idname), widname);
-
- {
- char * atsign;
-
- atsign = strchr(idname, '@');
- if (atsign == NULL) {
- _reportf(L"Identity name does not contain an '@'");
- goto _skip_pwd;
- }
-
- *atsign++ = 0;
-
- realm = atsign;
- }
-
- {
- char * slash;
-
- slash = strchr(idname, '/');
- if (slash != NULL) {
- *slash++ = 0;
- inst = slash;
- } else {
- inst = "";
- }
- }
-
- aname = idname;
-
- code = khm_krb4_kinit(aname, inst, realm,
- (long) d->lifetime, pwd);
-
- _reportf(L"khm_krb4_kinit returns code %d", code);
-
- _skip_pwd:
-
- if (code) {
- khui_cw_set_response(nc, credtype_id_krb4,
- KHUI_NC_RESPONSE_EXIT |
- KHUI_NC_RESPONSE_FAILED);
-
- } else {
- khui_cw_set_response(nc, credtype_id_krb4,
- KHUI_NC_RESPONSE_EXIT |
- KHUI_NC_RESPONSE_SUCCESS);
-
- if (nc->subtype == KMSG_CRED_NEW_CREDS) {
-
- assert(d != NULL);
- k4_write_identity_data(d);
-
- }
- }
- }
-
- _end_task();
- }
- }
- break;
-
- case KMSG_CRED_END:
- {
- khui_new_creds * nc;
- khui_new_creds_by_type * nct = NULL;
-
- nc = (khui_new_creds *) vparam;
- if (KHM_FAILED(khui_cw_find_type(nc, credtype_id_krb4, &nct)))
- break;
-
- khui_cw_del_type(nc, credtype_id_krb4);
-
- if (nct->name)
- PFREE(nct->name);
-
- if (nct->credtext)
- PFREE(nct->credtext);
-
- PFREE(nct);
- }
- break;
- }
-
- return KHM_ERROR_SUCCESS;
-}
+/* + * Copyright (c) 2005 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<utils.h> +#include<commctrl.h> +#include<strsafe.h> +#include<krb5.h> +#include<assert.h> + +/* method identifiers should be contiguous */ +#define K4_METHOD_AUTO 0 +#define K4_METHOD_PASSWORD 1 +#define K4_METHOD_K524 2 + +int method_to_id[] = { + IDC_NCK4_AUTO, + IDC_NCK4_PWD, + IDC_NCK4_K524 +}; + +typedef struct tag_k4_dlg_data { + HWND hwnd; + khui_new_creds * nc; + khui_new_creds_by_type * nct; + + khm_boolean k4_enabled; + khm_int32 method; + time_t lifetime; +} k4_dlg_data; + +void k4_update_display(k4_dlg_data * d, BOOL update_methods) { + CheckDlgButton(d->hwnd, IDC_NCK4_OBTAIN, + (d->k4_enabled)?BST_CHECKED: BST_UNCHECKED); + + if (d->k4_enabled) { + EnableWindow(GetDlgItem(d->hwnd, IDC_NCK4_AUTO), TRUE); + EnableWindow(GetDlgItem(d->hwnd, IDC_NCK4_K524), TRUE); + EnableWindow(GetDlgItem(d->hwnd, IDC_NCK4_PWD ), TRUE); + } else { + EnableWindow(GetDlgItem(d->hwnd, IDC_NCK4_AUTO), FALSE); + EnableWindow(GetDlgItem(d->hwnd, IDC_NCK4_K524), FALSE); + EnableWindow(GetDlgItem(d->hwnd, IDC_NCK4_PWD ), FALSE); + } + +#ifdef DEBUG + assert(d->method >= 0 && d->method < ARRAYLENGTH(method_to_id)); +#endif + + CheckRadioButton(d->hwnd, IDC_NCK4_AUTO, IDC_NCK4_PWD, method_to_id[d->method]); + + khui_cw_enable_type(d->nc, credtype_id_krb4, d->k4_enabled); +} + +void k4_update_data(k4_dlg_data * d) { + int i; + khm_boolean oldstate; + + oldstate = d->k4_enabled; + + if (IsDlgButtonChecked(d->hwnd, IDC_NCK4_OBTAIN) == BST_CHECKED) + d->k4_enabled = TRUE; + else + d->k4_enabled = FALSE; + + if ((oldstate && !d->k4_enabled) || + (!oldstate && d->k4_enabled)) { + + khui_cw_enable_type(d->nc, credtype_id_krb4, d->k4_enabled); + } + + d->method = K4_METHOD_AUTO; + + for (i=K4_METHOD_AUTO; i<=K4_METHOD_K524; i++) { + if (IsDlgButtonChecked(d->hwnd, method_to_id[i]) == BST_CHECKED) { + d->method = i; + break; + } + } +} + +khm_boolean k4_should_identity_get_k4(khm_handle ident) { + khm_int32 idflags = 0; + khm_int32 t = TRUE; + khm_handle csp_ident = NULL; + khm_handle csp_k4 = NULL; + khm_boolean get_k4 = TRUE; + khm_boolean id_spec = FALSE; + + if (KHM_FAILED(kcdb_identity_get_flags(ident, &idflags))) + return FALSE; + + if (!(idflags & KCDB_IDENT_FLAG_DEFAULT)) { + /* we only support k4 for one identity, and that is the + default identity. If we are trying to get tickets for a + non-default identity, then we start off as disabled unless + there is no default identity. */ + + khm_handle defident = NULL; + + if (KHM_SUCCEEDED(kcdb_identity_get_default(&defident))) { + kcdb_identity_release(defident); + + return FALSE; + } + } + + if (KHM_SUCCEEDED(kcdb_identity_get_config(ident, 0, &csp_ident))) { + if (KHM_SUCCEEDED(khc_open_space(csp_ident, CSNAME_KRB4CRED, 0, + &csp_k4))) { + khm_int32 t = 0; + + if (KHM_SUCCEEDED(khc_read_int32(csp_k4, L"Krb4NewCreds", &t))) { + get_k4 = !!t; + id_spec = TRUE; + } + + khc_close_space(csp_k4); + } + khc_close_space(csp_ident); + } + + /* if there was a value specified for the identity, then that + takes precedence. */ + if (id_spec || !get_k4) + return get_k4; + + if (KHM_SUCCEEDED(khc_read_int32(csp_params, L"Krb4NewCreds", &t)) && + !t) + return FALSE; + + return TRUE; +} + +void k4_read_identity_data(k4_dlg_data * d) { + khm_handle csp_ident = NULL; + khm_handle csp_k4 = NULL; + + khm_int32 idflags = 0; + khm_int32 t; + + if (KHM_SUCCEEDED(khc_read_int32(csp_params, L"Krb4NewCreds", &t))) + d->k4_enabled = !!t; + else + d->k4_enabled = TRUE; + + if (KHM_SUCCEEDED(khc_read_int32(csp_params, L"Krb4Method", &t))) + d->method = t; + else + d->method = K4_METHOD_AUTO; + + if (KHM_SUCCEEDED(khc_read_int32(csp_params, L"DefaultLifetime", &t))) + d->lifetime = t; + else + d->lifetime = 10 * 60 * 60; /* 10 hours */ + + if (d->nc->n_identities > 0 && + d->nc->identities[0]) { + + if (KHM_SUCCEEDED(kcdb_identity_get_config(d->nc->identities[0], + 0, + &csp_ident))) { + + khc_open_space(csp_ident, CSNAME_KRB4CRED, 0, &csp_k4); + + if (csp_k4) { + if (KHM_SUCCEEDED(khc_read_int32(csp_k4, L"Krb4NewCreds", &t))) + d->k4_enabled = !!t; + if (KHM_SUCCEEDED(khc_read_int32(csp_k4, L"Krb4Method", &t))) + d->method = t; + khc_close_space(csp_k4); + } + + khc_close_space(csp_ident); + } + + if (d->k4_enabled) { + d->k4_enabled = k4_should_identity_get_k4(d->nc->identities[0]); + } + } else { + d->k4_enabled = FALSE; + } + + if (d->method < 0 || d->method > K4_METHOD_K524) + d->method = K4_METHOD_AUTO; +} + +void k4_write_identity_data(k4_dlg_data * d) { + khm_handle csp_ident = NULL; + khm_handle csp_k4 = NULL; + + if (d->nc->n_identities > 0 && + d->nc->identities[0] && + KHM_SUCCEEDED(kcdb_identity_get_config(d->nc->identities[0], + KHM_FLAG_CREATE, + &csp_ident))) { + khc_open_space(csp_ident, CSNAME_KRB4CRED, + KHM_FLAG_CREATE | KCONF_FLAG_WRITEIFMOD, + &csp_k4); + + if (csp_k4) { + khc_write_int32(csp_k4, L"Krb4NewCreds", !!d->k4_enabled); + khc_write_int32(csp_k4, L"Krb4Method", d->method); + + khc_close_space(csp_k4); + } + + khc_close_space(csp_ident); + } +} + +void k4_handle_wmnc_notify(k4_dlg_data * d, + WPARAM wParam, + LPARAM lParam) { + switch(HIWORD(wParam)) { + case WMNC_UPDATE_CREDTEXT: + { + if (d->nct->credtext) { + PFREE(d->nct->credtext); + d->nct->credtext = NULL; + } + + if (d->nc->n_identities > 0 && + d->nc->identities[0]) { + + khm_int32 flags = 0; + wchar_t idname[KCDB_IDENT_MAXCCH_NAME]; + wchar_t * atsign; + wchar_t * realm; + khm_size cb; + + kcdb_identity_get_flags(d->nc->identities[0], &flags); + + if (!(flags & KCDB_IDENT_FLAG_VALID)) { + break; + } + + cb = sizeof(idname); + kcdb_identity_get_name(d->nc->identities[0], idname, + &cb); + + atsign = wcsrchr(idname, L'@'); + + if (atsign == NULL || !atsign[1]) + break; + + realm = ++atsign; + + if (d->k4_enabled) { + wchar_t wmethod[128]; + wchar_t wfmt[128]; + wchar_t wct[512]; + + LoadString(hResModule, IDS_CT_TGTFOR, + wfmt, ARRAYLENGTH(wfmt)); + + if (d->method == K4_METHOD_AUTO) + LoadString(hResModule, IDS_METHOD_AUTO, wmethod, + ARRAYLENGTH(wmethod)); + else if (d->method == K4_METHOD_PASSWORD) + LoadString(hResModule, IDS_METHOD_PWD, wmethod, + ARRAYLENGTH(wmethod)); + else if (d->method == K4_METHOD_K524) + LoadString(hResModule, IDS_METHOD_K524, wmethod, + ARRAYLENGTH(wmethod)); + else { + assert(FALSE); + } + + StringCbPrintf(wct, sizeof(wct), wfmt, realm, wmethod); + + StringCbLength(wct, sizeof(wct), &cb); + cb += sizeof(wchar_t); + + d->nct->credtext = PMALLOC(cb); + + StringCbCopy(d->nct->credtext, cb, wct); + } else { + wchar_t wct[256]; + + LoadString(hResModule, IDS_CT_DISABLED, + wct, ARRAYLENGTH(wct)); + + StringCbLength(wct, sizeof(wct), &cb); + cb += sizeof(wchar_t); + + d->nct->credtext = PMALLOC(cb); + + StringCbCopy(d->nct->credtext, cb, wct); + } + } + /* no identities were selected. it is not the + responsibility of krb4 to complain about this. */ + } + break; + + case WMNC_IDENTITY_CHANGE: + k4_read_identity_data(d); + k4_update_display(d, TRUE); + break; + + case WMNC_CREDTEXT_LINK: + { + wchar_t wid[KHUI_MAXCCH_HTLINK_FIELD]; + wchar_t * wids; + khui_htwnd_link * l; + + l = (khui_htwnd_link *) lParam; + + StringCchCopyN(wid, ARRAYLENGTH(wid), l->id, l->id_len); + wids = wcschr(wid, L':'); + + if (!wids) + break; + else + wids++; + + if (!wcscmp(wids, L"Enable")) { + d->k4_enabled = TRUE; + + k4_update_display(d, TRUE); + khui_cw_enable_type(d->nc, credtype_id_krb4, TRUE); + } + } + break; + } +} + +INT_PTR CALLBACK k4_nc_dlg_proc(HWND hwnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam) { + + k4_dlg_data * d; + + switch(uMsg) { + case WM_INITDIALOG: + { + d = PMALLOC(sizeof(*d)); + ZeroMemory(d, sizeof(*d)); + + d->nc = (khui_new_creds *) lParam; + khui_cw_find_type(d->nc, credtype_id_krb4, &d->nct); + +#pragma warning(push) +#pragma warning(disable: 4244) + SetWindowLongPtr(hwnd, DWLP_USER, (LPARAM) d); +#pragma warning(pop) + + d->nct->aux = (LPARAM) d; + d->hwnd = hwnd; + + d->k4_enabled = TRUE; + d->method = K4_METHOD_AUTO; + + k4_update_display(d, TRUE); + } + break; + + case WM_COMMAND: + { + if (HIWORD(wParam) == BN_CLICKED) { + d = (k4_dlg_data *) (LONG_PTR) + GetWindowLongPtr(hwnd, DWLP_USER); + + k4_update_data(d); + + if (LOWORD(wParam) == IDC_NCK4_OBTAIN) { + k4_update_display(d, TRUE); + } + + return TRUE; + } + } + break; + + case KHUI_WM_NC_NOTIFY: + { + d = (k4_dlg_data *) (LONG_PTR) + GetWindowLongPtr(hwnd, DWLP_USER); + k4_handle_wmnc_notify(d, wParam, lParam); + } + break; + + case WM_DESTROY: + { + d = (k4_dlg_data *) (LONG_PTR) + GetWindowLongPtr(hwnd, DWLP_USER); + + d->nct->aux = 0; + + PFREE(d); + } + break; + } + + return FALSE; +} + +khm_int32 +krb4_msg_newcred(khm_int32 msg_type, khm_int32 msg_subtype, + khm_ui_4 uparam, void * vparam) { + + switch(msg_subtype) { + case KMSG_CRED_NEW_CREDS: + { + khui_new_creds * nc; + khui_new_creds_by_type * nct; + khm_size cbsize; + wchar_t wbuf[256]; + + nc = (khui_new_creds *) vparam; + + nct = PMALLOC(sizeof(*nct)); +#ifdef DEBUG + assert(nct); +#endif + ZeroMemory(nct, sizeof(*nct)); + + nct->type = credtype_id_krb4; + nct->ordinal = 3; + LoadString(hResModule, IDS_NC_K4_SHORT, + wbuf, ARRAYLENGTH(wbuf)); + StringCbLength(wbuf, sizeof(wbuf), &cbsize); + cbsize += sizeof(wchar_t); + + nct->name = PMALLOC(cbsize); + StringCbCopy(nct->name, cbsize, wbuf); + + nct->type_deps[nct->n_type_deps++] = credtype_id_krb5; + + nct->h_module = hResModule; + nct->dlg_proc = k4_nc_dlg_proc; + nct->dlg_template = MAKEINTRESOURCE(IDD_NC_KRB4); + + khui_cw_add_type(nc, nct); + } + break; + + case KMSG_CRED_RENEW_CREDS: + { + khui_new_creds * nc; + khui_new_creds_by_type * nct; + khm_size cbsize; + wchar_t wbuf[256]; + + nc = (khui_new_creds *) vparam; + + if (!nc->ctx.identity) + break; + + nct = PMALLOC(sizeof(*nct)); +#ifdef DEBUG + assert(nct); +#endif + + ZeroMemory(nct, sizeof(*nct)); + + nct->type = credtype_id_krb4; + nct->ordinal = 3; + LoadString(hResModule, IDS_NC_K4_SHORT, + wbuf, ARRAYLENGTH(wbuf)); + StringCbLength(wbuf, sizeof(wbuf), &cbsize); + cbsize += sizeof(wchar_t); + + nct->name = PMALLOC(cbsize); + StringCbCopy(nct->name, cbsize, wbuf); + + nct->type_deps[nct->n_type_deps++] = credtype_id_krb5; + + khui_cw_add_type(nc, nct); + } + break; + + case KMSG_CRED_DIALOG_SETUP: + break; + + case KMSG_CRED_PROCESS: + { + khui_new_creds * nc; + khui_new_creds_by_type * nct = NULL; + khm_handle ident = NULL; + k4_dlg_data * d = NULL; + long code = 0; + wchar_t idname[KCDB_IDENT_MAXCCH_NAME]; + khm_size cb; + + nc = (khui_new_creds *) vparam; + if (KHM_FAILED(khui_cw_find_type(nc, credtype_id_krb4, &nct))) + break; + + if (nc->subtype == KMSG_CRED_NEW_CREDS || + nc->subtype == KMSG_CRED_RENEW_CREDS) { + khm_int32 method; + + if (nc->subtype == KMSG_CRED_NEW_CREDS) { + + d = (k4_dlg_data *) nct->aux; + if (!d || + nc->n_identities == 0 || + nc->identities[0] == NULL || + nc->result != KHUI_NC_RESULT_PROCESS) { + khui_cw_set_response(nc, credtype_id_krb4, + KHUI_NC_RESPONSE_SUCCESS | + KHUI_NC_RESPONSE_EXIT); + break; + } + + if (!d->k4_enabled) { + k4_write_identity_data(d); + khui_cw_set_response(nc, credtype_id_krb4, + KHUI_NC_RESPONSE_SUCCESS | + KHUI_NC_RESPONSE_EXIT); + break; + } + + method = d->method; + ident = nc->identities[0]; + + cb = sizeof(idname); + kcdb_identity_get_name(ident, idname, &cb); + _begin_task(0); + _report_mr2(KHERR_NONE, MSG_K4_NEW_CREDS, + _cstr(ident), _int32(method)); + _resolve(); + _describe(); + + } else if (nc->subtype == KMSG_CRED_RENEW_CREDS) { + + if ((nc->ctx.scope == KHUI_SCOPE_IDENT && + nc->ctx.identity != NULL) || + + (nc->ctx.scope == KHUI_SCOPE_CREDTYPE && + nc->ctx.cred_type == credtype_id_krb4 && + nc->ctx.identity != NULL) || + + (nc->ctx.scope == KHUI_SCOPE_CRED && + nc->ctx.cred_type == credtype_id_krb4 && + nc->ctx.identity != NULL && + nc->ctx.cred != NULL)) { + + ident = nc->ctx.identity; + + if (!k4_should_identity_get_k4(ident)) { + + _reportf(L"Kerberos 4 is not enabled for this identity. Skipping"); + + khui_cw_set_response(nc, credtype_id_krb4, + KHUI_NC_RESPONSE_FAILED | + KHUI_NC_RESPONSE_EXIT); + break; + } + + } else { + + _reportf(L"Kerberos 4 is not within renewal scope. Skipping"); + + khui_cw_set_response(nc, credtype_id_krb4, + KHUI_NC_RESPONSE_FAILED | + KHUI_NC_RESPONSE_EXIT); + break; + } + + method = K4_METHOD_K524; /* only k524 is supported + for renewals */ + + _begin_task(0); + cb = sizeof(idname); + kcdb_identity_get_name(ident, idname, &cb); + _report_mr2(KHERR_NONE, MSG_K4_RENEW_CREDS, + _cstr(ident), _int32(method)); + _resolve(); + _describe(); + } else { + assert(FALSE); + break; + } + + if ((method == K4_METHOD_AUTO || + method == K4_METHOD_K524) && + khui_cw_type_succeeded(nc, credtype_id_krb5)) { + + khm_handle tgt; + FILETIME ft_prev; + FILETIME ft_new; + khm_size cb; + + _report_mr0(KHERR_INFO, MSG_K4_TRY_K524); + + tgt = khm_krb4_find_tgt(NULL, ident); + if (tgt) { + cb = sizeof(ft_prev); + if (KHM_FAILED(kcdb_cred_get_attr(tgt, + KCDB_ATTR_EXPIRE, + NULL, + &ft_prev, + &cb))) + ZeroMemory(&ft_prev, sizeof(ft_prev)); + kcdb_cred_release(tgt); + } + + code = khm_convert524(ident); + + _reportf(L"khm_convert524 returns code %d", code); + + if (code == 0) { + khui_cw_set_response(nc, credtype_id_krb4, + KHUI_NC_RESPONSE_SUCCESS | + KHUI_NC_RESPONSE_EXIT); + + if (nc->subtype == KMSG_CRED_NEW_CREDS) { + assert(d != NULL); + + k4_write_identity_data(d); + + } else if (nc->subtype == KMSG_CRED_RENEW_CREDS && + (nc->ctx.scope == KHUI_SCOPE_CREDTYPE || + nc->ctx.scope == KHUI_SCOPE_CRED)) { + + khm_krb4_list_tickets(); + + tgt = khm_krb4_find_tgt(NULL, ident); + + if (tgt) { + cb = sizeof(ft_new); + ZeroMemory(&ft_new, sizeof(ft_new)); + + kcdb_cred_get_attr(tgt, + KCDB_ATTR_EXPIRE, + NULL, + &ft_new, + &cb); + + kcdb_cred_release(tgt); + } + + if (!tgt || + CompareFileTime(&ft_new, + &ft_prev) <= 0) { + /* The new TGT wasn't much of an + improvement over what we already + had. We should go out and try to + renew the identity now. */ + + khui_action_context ctx; + + _reportf(L"Renewal of Krb4 creds failed to get a longer TGT. Triggering identity renewal"); + + khui_context_create(&ctx, + KHUI_SCOPE_IDENT, + nc->ctx.identity, + KCDB_CREDTYPE_INVALID, + NULL); + khui_action_trigger(KHUI_ACTION_RENEW_CRED, + &ctx); + + khui_context_release(&ctx); + } + } + + _end_task(); + break; + + } else if (method == K4_METHOD_K524) { + khui_cw_set_response(nc, credtype_id_krb4, + KHUI_NC_RESPONSE_FAILED | + KHUI_NC_RESPONSE_EXIT); + + if (nc->subtype == KMSG_CRED_RENEW_CREDS && + (nc->ctx.scope == KHUI_SCOPE_CREDTYPE || + nc->ctx.scope == KHUI_SCOPE_CRED)) { + /* We were trying to get a new Krb4 TGT + for this identity. Sometimes this + fails because of restrictions placed on + K524d regarding the lifetime of the + issued K4 TGT. In this case, we + trigger a renewal of the identity in + the hope that the new K5 TGT will allow + us to successfully get a new K4 TGT + next time over using the new K5 TGT. */ + + khui_action_context ctx; + + _reportf(L"Renewal of Krb4 creds failed using k524. Triggerring identity renewal."); + + khui_context_create(&ctx, + KHUI_SCOPE_IDENT, + nc->ctx.identity, + KCDB_CREDTYPE_INVALID, + NULL); + + khui_action_trigger(KHUI_ACTION_RENEW_CRED, + &ctx); + + khui_context_release(&ctx); + } + + _end_task(); + break; + + } + } + + /* only supported for new credentials */ + if (method == K4_METHOD_AUTO || + method == K4_METHOD_PASSWORD) { + + khm_size n_prompts = 0; + khm_size idx; + khm_size cb; + wchar_t wpwd[KHUI_MAXCCH_PROMPT_VALUE]; + char pwd[KHUI_MAXCCH_PROMPT_VALUE]; + wchar_t widname[KCDB_IDENT_MAXCCH_NAME]; + char idname[KCDB_IDENT_MAXCCH_NAME]; + + char * aname = NULL; + char * inst = NULL; + char * realm = NULL; + + assert(nc->subtype == KMSG_CRED_NEW_CREDS); + + _report_mr0(KHERR_INFO, MSG_K4_TRY_PASSWORD); + + code = TRUE; /* just has to be non-zero */ + + khui_cw_get_prompt_count(nc, &n_prompts); + + if (n_prompts == 0) + goto _skip_pwd; + + for (idx = 0; idx < n_prompts; idx++) { + khui_new_creds_prompt * p; + + if (KHM_FAILED(khui_cw_get_prompt(nc, idx, &p))) + continue; + + if (p->type == KHUI_NCPROMPT_TYPE_PASSWORD) + break; + } + + if (idx >= n_prompts) { + _reportf(L"Password prompt not found"); + goto _skip_pwd; + } + + khui_cw_sync_prompt_values(nc); + + cb = sizeof(wpwd); + if (KHM_FAILED(khui_cw_get_prompt_value(nc, idx, + wpwd, + &cb))) { + _reportf(L"Failed to obtain password value"); + goto _skip_pwd; + } + + UnicodeStrToAnsi(pwd, sizeof(pwd), wpwd); + + cb = sizeof(widname); + kcdb_identity_get_name(ident, + widname, + &cb); + + UnicodeStrToAnsi(idname, sizeof(idname), widname); + + { + char * atsign; + + atsign = strchr(idname, '@'); + if (atsign == NULL) { + _reportf(L"Identity name does not contain an '@'"); + goto _skip_pwd; + } + + *atsign++ = 0; + + realm = atsign; + } + + { + char * slash; + + slash = strchr(idname, '/'); + if (slash != NULL) { + *slash++ = 0; + inst = slash; + } else { + inst = ""; + } + } + + aname = idname; + + code = khm_krb4_kinit(aname, inst, realm, + (long) d->lifetime, pwd); + + _reportf(L"khm_krb4_kinit returns code %d", code); + + _skip_pwd: + + if (code) { + khui_cw_set_response(nc, credtype_id_krb4, + KHUI_NC_RESPONSE_EXIT | + KHUI_NC_RESPONSE_FAILED); + + } else { + khui_cw_set_response(nc, credtype_id_krb4, + KHUI_NC_RESPONSE_EXIT | + KHUI_NC_RESPONSE_SUCCESS); + + if (nc->subtype == KMSG_CRED_NEW_CREDS) { + + assert(d != NULL); + k4_write_identity_data(d); + + } + } + } + + _end_task(); + } + } + break; + + case KMSG_CRED_END: + { + khui_new_creds * nc; + khui_new_creds_by_type * nct = NULL; + + nc = (khui_new_creds *) vparam; + if (KHM_FAILED(khui_cw_find_type(nc, credtype_id_krb4, &nct))) + break; + + khui_cw_del_type(nc, credtype_id_krb4); + + if (nct->name) + PFREE(nct->name); + + if (nct->credtext) + PFREE(nct->credtext); + + PFREE(nct); + } + break; + } + + return KHM_ERROR_SUCCESS; +} diff --git a/src/windows/identity/plugins/krb4/krb4plugin.c b/src/windows/identity/plugins/krb4/krb4plugin.c index b4edd4192..9a50249f7 100644 --- a/src/windows/identity/plugins/krb4/krb4plugin.c +++ b/src/windows/identity/plugins/krb4/krb4plugin.c @@ -1,297 +1,297 @@ -/*
- * Copyright (c) 2005 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<utils.h>
-#include<commctrl.h>
-#include<strsafe.h>
-#include<krb5.h>
-
-khm_int32 credtype_id_krb4 = KCDB_CREDTYPE_INVALID;
-khm_int32 credtype_id_krb5 = 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:
- {
-#ifdef _WIN64
- return KHM_ERROR_NOT_IMPLEMENTED;
-#else
- 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 = PMALLOC(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 = PMALLOC(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 (KHM_SUCCEEDED(rv))
- rv = kcdb_credtype_get_id(KRB5_CREDTYPE_NAME,
- &credtype_id_krb5);
-
- if(ct.short_desc)
- PFREE(ct.short_desc);
-
- if(ct.long_desc)
- PFREE(ct.long_desc);
-
- if (KHM_SUCCEEDED(rv)) {
- khui_config_node idents;
-
- ZeroMemory(®, 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, ®);
-
- khui_cfg_open(NULL, L"KhmIdentities", &idents);
-
- ZeroMemory(®, sizeof(reg));
-
- reg.name = KRB4_IDS_CONFIG_NODE_NAME;
- reg.short_desc = wshort_desc;
- reg.long_desc = wlong_desc;
- reg.h_module = hResModule;
- reg.dlg_template = MAKEINTRESOURCE(IDD_CFG_IDS_KRB4);
- reg.dlg_proc = krb4_ids_config_proc;
- reg.flags = KHUI_CNFLAG_SUBPANEL;
-
- LoadString(hResModule, IDS_CFG_KRB4_SHORT,
- wlong_desc, ARRAYLENGTH(wlong_desc));
- LoadString(hResModule, IDS_CFG_KRB4_SHORT,
- wshort_desc, ARRAYLENGTH(wshort_desc));
-
- khui_cfg_register(idents, ®);
-
- ZeroMemory(®, sizeof(reg));
-
- reg.name = KRB4_ID_CONFIG_NODE_NAME;
- reg.short_desc = wshort_desc;
- reg.long_desc = wlong_desc;
- reg.h_module = hResModule;
- reg.dlg_template = MAKEINTRESOURCE(IDD_CFG_ID_KRB4);
- reg.dlg_proc = krb4_id_config_proc;
- reg.flags = KHUI_CNFLAG_SUBPANEL | KHUI_CNFLAG_PLURAL;
-
- LoadString(hResModule, IDS_CFG_KRB4_SHORT,
- wlong_desc, ARRAYLENGTH(wlong_desc));
- LoadString(hResModule, IDS_CFG_KRB4_SHORT,
- wshort_desc, ARRAYLENGTH(wshort_desc));
-
- khui_cfg_register(idents, ®);
-
- khui_cfg_release(idents);
-
- }
-
- /* Lookup common data types */
- if(KHM_FAILED(kcdb_type_get_id(TYPENAME_ENCTYPE,
- &type_id_enctype))) {
- rv = KHM_ERROR_UNKNOWN;
- }
-
- if(KHM_FAILED(kcdb_type_get_id(TYPENAME_ADDR_LIST,
- &type_id_addr_list))) {
- rv = KHM_ERROR_UNKNOWN;
- }
-
- if(KHM_FAILED(kcdb_type_get_id(TYPENAME_KRB5_FLAGS,
- &type_id_krb5_flags))) {
- rv = KHM_ERROR_UNKNOWN;
- }
-
- /* Lookup common attributes */
- if(KHM_FAILED(kcdb_attrib_get_id(ATTRNAME_KEY_ENCTYPE,
- &attr_id_key_enctype))) {
- rv = KHM_ERROR_UNKNOWN;
- }
-
- if(KHM_FAILED(kcdb_attrib_get_id(ATTRNAME_TKT_ENCTYPE,
- &attr_id_tkt_enctype))) {
- rv = KHM_ERROR_UNKNOWN;
- }
-
- if(KHM_FAILED(kcdb_attrib_get_id(ATTRNAME_ADDR_LIST,
- &attr_id_addr_list))) {
- rv = KHM_ERROR_UNKNOWN;
- }
-
- if(KHM_FAILED(kcdb_attrib_get_id(ATTRNAME_KRB5_FLAGS,
- &attr_id_krb5_flags))) {
- rv = KHM_ERROR_UNKNOWN;
- }
-
- krb4_initialized = TRUE;
-
- khm_krb4_set_def_tkt_string();
-
- khm_krb4_list_tickets();
-#endif
- }
- break;
-
- case KMSG_SYSTEM_EXIT:
-#ifdef _WIN64
- /* See above. On 64-bit platforms, we don't support Krb4 at
- all. */
- return 0;
-#else
- if(credtype_id_krb4 >= 0)
- {
- /* basically just unregister the credential type */
- kcdb_credtype_unregister(credtype_id_krb4);
-
- kcdb_credset_delete(krb4_credset);
- }
- break;
-#endif
- }
-
- 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;
-
- case KMSG_CRED_DESTROY_CREDS:
- {
- khui_action_context * ctx;
- khm_handle credset;
- khm_size nc_root = 0;
- khm_size nc_sel = 0;
-
- ctx = (khui_action_context *) vparam;
-
- /* if all krb4 tickets are selected, then we destroy all
- of them. Otherwise, we do nothing. */
-
- kcdb_credset_create(&credset);
-
- kcdb_credset_extract(credset, ctx->credset,
- NULL, credtype_id_krb4);
- kcdb_credset_get_size(credset, &nc_sel);
-
- kcdb_credset_flush(credset);
-
- kcdb_credset_extract(credset, NULL,
- NULL, credtype_id_krb4);
- kcdb_credset_get_size(credset, &nc_root);
-
- kcdb_credset_delete(credset);
-
- if (nc_root == nc_sel) {
- khm_krb4_kdestroy();
- }
- }
- break;
-
- default:
- if (IS_CRED_ACQ_MSG(msg_subtype))
- return krb4_msg_newcred(msg_type, msg_subtype, uparam, vparam);
- }
-
- 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;
-}
+/* + * Copyright (c) 2005 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<utils.h> +#include<commctrl.h> +#include<strsafe.h> +#include<krb5.h> + +khm_int32 credtype_id_krb4 = KCDB_CREDTYPE_INVALID; +khm_int32 credtype_id_krb5 = 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: + { +#ifdef _WIN64 + return KHM_ERROR_NOT_IMPLEMENTED; +#else + 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 = PMALLOC(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 = PMALLOC(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 (KHM_SUCCEEDED(rv)) + rv = kcdb_credtype_get_id(KRB5_CREDTYPE_NAME, + &credtype_id_krb5); + + if(ct.short_desc) + PFREE(ct.short_desc); + + if(ct.long_desc) + PFREE(ct.long_desc); + + if (KHM_SUCCEEDED(rv)) { + khui_config_node idents; + + ZeroMemory(®, 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, ®); + + khui_cfg_open(NULL, L"KhmIdentities", &idents); + + ZeroMemory(®, sizeof(reg)); + + reg.name = KRB4_IDS_CONFIG_NODE_NAME; + reg.short_desc = wshort_desc; + reg.long_desc = wlong_desc; + reg.h_module = hResModule; + reg.dlg_template = MAKEINTRESOURCE(IDD_CFG_IDS_KRB4); + reg.dlg_proc = krb4_ids_config_proc; + reg.flags = KHUI_CNFLAG_SUBPANEL; + + LoadString(hResModule, IDS_CFG_KRB4_SHORT, + wlong_desc, ARRAYLENGTH(wlong_desc)); + LoadString(hResModule, IDS_CFG_KRB4_SHORT, + wshort_desc, ARRAYLENGTH(wshort_desc)); + + khui_cfg_register(idents, ®); + + ZeroMemory(®, sizeof(reg)); + + reg.name = KRB4_ID_CONFIG_NODE_NAME; + reg.short_desc = wshort_desc; + reg.long_desc = wlong_desc; + reg.h_module = hResModule; + reg.dlg_template = MAKEINTRESOURCE(IDD_CFG_ID_KRB4); + reg.dlg_proc = krb4_id_config_proc; + reg.flags = KHUI_CNFLAG_SUBPANEL | KHUI_CNFLAG_PLURAL; + + LoadString(hResModule, IDS_CFG_KRB4_SHORT, + wlong_desc, ARRAYLENGTH(wlong_desc)); + LoadString(hResModule, IDS_CFG_KRB4_SHORT, + wshort_desc, ARRAYLENGTH(wshort_desc)); + + khui_cfg_register(idents, ®); + + khui_cfg_release(idents); + + } + + /* Lookup common data types */ + if(KHM_FAILED(kcdb_type_get_id(TYPENAME_ENCTYPE, + &type_id_enctype))) { + rv = KHM_ERROR_UNKNOWN; + } + + if(KHM_FAILED(kcdb_type_get_id(TYPENAME_ADDR_LIST, + &type_id_addr_list))) { + rv = KHM_ERROR_UNKNOWN; + } + + if(KHM_FAILED(kcdb_type_get_id(TYPENAME_KRB5_FLAGS, + &type_id_krb5_flags))) { + rv = KHM_ERROR_UNKNOWN; + } + + /* Lookup common attributes */ + if(KHM_FAILED(kcdb_attrib_get_id(ATTRNAME_KEY_ENCTYPE, + &attr_id_key_enctype))) { + rv = KHM_ERROR_UNKNOWN; + } + + if(KHM_FAILED(kcdb_attrib_get_id(ATTRNAME_TKT_ENCTYPE, + &attr_id_tkt_enctype))) { + rv = KHM_ERROR_UNKNOWN; + } + + if(KHM_FAILED(kcdb_attrib_get_id(ATTRNAME_ADDR_LIST, + &attr_id_addr_list))) { + rv = KHM_ERROR_UNKNOWN; + } + + if(KHM_FAILED(kcdb_attrib_get_id(ATTRNAME_KRB5_FLAGS, + &attr_id_krb5_flags))) { + rv = KHM_ERROR_UNKNOWN; + } + + krb4_initialized = TRUE; + + khm_krb4_set_def_tkt_string(); + + khm_krb4_list_tickets(); +#endif + } + break; + + case KMSG_SYSTEM_EXIT: +#ifdef _WIN64 + /* See above. On 64-bit platforms, we don't support Krb4 at + all. */ + return 0; +#else + if(credtype_id_krb4 >= 0) + { + /* basically just unregister the credential type */ + kcdb_credtype_unregister(credtype_id_krb4); + + kcdb_credset_delete(krb4_credset); + } + break; +#endif + } + + 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; + + case KMSG_CRED_DESTROY_CREDS: + { + khui_action_context * ctx; + khm_handle credset; + khm_size nc_root = 0; + khm_size nc_sel = 0; + + ctx = (khui_action_context *) vparam; + + /* if all krb4 tickets are selected, then we destroy all + of them. Otherwise, we do nothing. */ + + kcdb_credset_create(&credset); + + kcdb_credset_extract(credset, ctx->credset, + NULL, credtype_id_krb4); + kcdb_credset_get_size(credset, &nc_sel); + + kcdb_credset_flush(credset); + + kcdb_credset_extract(credset, NULL, + NULL, credtype_id_krb4); + kcdb_credset_get_size(credset, &nc_root); + + kcdb_credset_delete(credset); + + if (nc_root == nc_sel) { + khm_krb4_kdestroy(); + } + } + break; + + default: + if (IS_CRED_ACQ_MSG(msg_subtype)) + return krb4_msg_newcred(msg_type, msg_subtype, uparam, vparam); + } + + 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/krbcred.h b/src/windows/identity/plugins/krb4/krbcred.h index 7c3b31a13..53e22c892 100644 --- a/src/windows/identity/plugins/krb4/krbcred.h +++ b/src/windows/identity/plugins/krb4/krbcred.h @@ -1,136 +1,136 @@ -/*
- * Copyright (c) 2005 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>
-
-#define KHERR_FACILITY L"Krb4Cred"
-#define KHERR_FACILITY_ID 65
-#define KHERR_HMODULE hResModule
-
-#include<netidmgr.h>
-
-#include<krb4funcs.h>
-#include<krb5common.h>
-#include<errorfuncs.h>
-#include<dynimport.h>
-
-#include<langres.h>
-#include<krb4_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_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 KRB5_CREDTYPE_NAME L"Krb5Cred"
-
-#define KRB4_CONFIG_NODE_NAME L"Krb4Config"
-
-#define KRB4_ID_CONFIG_NODE_NAME L"Krb4IdentConfig"
-#define KRB4_IDS_CONFIG_NODE_NAME L"Krb4IdentsConfig"
-
-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_int32 credtype_id_krb5;
-
-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);
-
-INT_PTR CALLBACK
-krb4_ids_config_proc(HWND hwnd,
- UINT uMsg,
- WPARAM wParam,
- LPARAM lParam);
-
-INT_PTR CALLBACK
-krb4_id_config_proc(HWND hwnd,
- UINT uMsg,
- WPARAM wParam,
- LPARAM lParam);
-
-khm_int32
-krb4_msg_newcred(khm_int32 msg_type, khm_int32 msg_subtype,
- khm_ui_4 uparam, void * vparam);
-#endif
+/* + * Copyright (c) 2005 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> + +#define KHERR_FACILITY L"Krb4Cred" +#define KHERR_FACILITY_ID 65 +#define KHERR_HMODULE hResModule + +#include<netidmgr.h> + +#include<krb4funcs.h> +#include<krb5common.h> +#include<errorfuncs.h> +#include<dynimport.h> + +#include<langres.h> +#include<krb4_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_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 KRB5_CREDTYPE_NAME L"Krb5Cred" + +#define KRB4_CONFIG_NODE_NAME L"Krb4Config" + +#define KRB4_ID_CONFIG_NODE_NAME L"Krb4IdentConfig" +#define KRB4_IDS_CONFIG_NODE_NAME L"Krb4IdentsConfig" + +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_int32 credtype_id_krb5; + +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); + +INT_PTR CALLBACK +krb4_ids_config_proc(HWND hwnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam); + +INT_PTR CALLBACK +krb4_id_config_proc(HWND hwnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam); + +khm_int32 +krb4_msg_newcred(khm_int32 msg_type, khm_int32 msg_subtype, + khm_ui_4 uparam, void * vparam); +#endif diff --git a/src/windows/identity/plugins/krb4/langres.h b/src/windows/identity/plugins/krb4/langres.h index c78ae4167..5c0e46f9a 100644 --- a/src/windows/identity/plugins/krb4/langres.h +++ b/src/windows/identity/plugins/krb4/langres.h @@ -1,49 +1,49 @@ -//{{NO_DEPENDENCIES}}
-// Microsoft Visual C++ generated include file.
-// Used by C:\work\pismere\athena\auth\krb5\src\windows\identity\plugins\krb4\lang\en_us\langres.rc
-//
-#define IDD_NC_KRB4 103
-#define IDS_PLUGIN_DESC 103
-#define IDD_CFG_KRB4 104
-#define IDS_NC_K4_SHORT 104
-#define IDS_ERR_REALM 105
-#define IDD_CFG_IDS_KRB4 105
-#define IDS_ERR_PRINCIPAL 106
-#define IDD_CFG_ID_KRB4 106
-#define IDS_ERR_INVINST 107
-#define IDI_PLUGIN 107
-#define IDS_ERR_PWINTKT 108
-#define IDS_CT_DISABLED 109
-#define IDS_CT_TGTFOR 110
-#define IDS_METHOD_AUTO 111
-#define IDS_METHOD_PWD 112
-#define IDS_METHOD_K524 113
-#define IDS_CFG_IDS_KRB4_SHORT 114
-#define IDS_KRB4_SHORT_DESC 128
-#define IDS_KRB4_LONG_DESC 129
-#define IDS_CFG_KRB4_LONG 135
-#define IDS_CFG_KRB4_SHORT 136
-#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
-#define IDC_NCK4_OBTAIN 1033
-#define IDC_NCK4_AUTO 1034
-#define IDC_NCK4_K524 1035
-#define IDC_NCK4_PWD 1036
-#define IDC_CFG_GETTIX 1037
-
-// Next default values for new objects
-//
-#ifdef APSTUDIO_INVOKED
-#ifndef APSTUDIO_READONLY_SYMBOLS
-#define _APS_NEXT_RESOURCE_VALUE 108
-#define _APS_NEXT_COMMAND_VALUE 40001
-#define _APS_NEXT_CONTROL_VALUE 1043
-#define _APS_NEXT_SYMED_VALUE 101
-#endif
-#endif
+//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by C:\work\pismere\athena\auth\krb5\src\windows\identity\plugins\krb4\lang\en_us\langres.rc +// +#define IDD_NC_KRB4 103 +#define IDS_PLUGIN_DESC 103 +#define IDD_CFG_KRB4 104 +#define IDS_NC_K4_SHORT 104 +#define IDS_ERR_REALM 105 +#define IDD_CFG_IDS_KRB4 105 +#define IDS_ERR_PRINCIPAL 106 +#define IDD_CFG_ID_KRB4 106 +#define IDS_ERR_INVINST 107 +#define IDI_PLUGIN 107 +#define IDS_ERR_PWINTKT 108 +#define IDS_CT_DISABLED 109 +#define IDS_CT_TGTFOR 110 +#define IDS_METHOD_AUTO 111 +#define IDS_METHOD_PWD 112 +#define IDS_METHOD_K524 113 +#define IDS_CFG_IDS_KRB4_SHORT 114 +#define IDS_KRB4_SHORT_DESC 128 +#define IDS_KRB4_LONG_DESC 129 +#define IDS_CFG_KRB4_LONG 135 +#define IDS_CFG_KRB4_SHORT 136 +#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 +#define IDC_NCK4_OBTAIN 1033 +#define IDC_NCK4_AUTO 1034 +#define IDC_NCK4_K524 1035 +#define IDC_NCK4_PWD 1036 +#define IDC_CFG_GETTIX 1037 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 108 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1043 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/src/windows/identity/plugins/krb5/datarep.c b/src/windows/identity/plugins/krb5/datarep.c index 92eabf4da..5c292e478 100644 --- a/src/windows/identity/plugins/krb5/datarep.c +++ b/src/windows/identity/plugins/krb5/datarep.c @@ -1,407 +1,407 @@ -/*
- * Copyright (c) 2005 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<winsock2.h>
-#include<krbcred.h>
-#include<krb5.h>
-#include<kherror.h>
-#include<strsafe.h>
-#include<assert.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_PARAM;
-
- 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_comp(const void *d1, khm_size cb_d1,
- const void *d2, khm_size cb_d2)
-{
- if (cb_d1 < cb_d2)
- return -1;
- if (cb_d1 > cb_d2)
- return 1;
- return memcmp(d1, d2, cb_d1);
-}
-
-khm_int32 KHMAPI
-addr_list_toString(const void *d, khm_size cb_d,
- wchar_t *buf, khm_size *pcb_buf,
- khm_int32 flags)
-{
- wchar_t tbuf[2048];
- wchar_t * strpos;
- khm_size cbleft;
- size_t t;
- k5_serial_address * addrs;
-
- if (cb_d == 0 || d == NULL) {
- tbuf[0] = L'\0';
- } else {
- addrs = (k5_serial_address *) d;
-
- strpos = tbuf;
- cbleft = sizeof(tbuf);
- tbuf[0] = L'\0';
-
- while (TRUE) {
- if (cb_d < sizeof(*addrs) ||
- addrs->magic != K5_SERIAL_ADDRESS_MAGIC ||
- cb_d < sizeof(*addrs) + addrs->length - sizeof(khm_int32))
- break;
-
- if (strpos != tbuf) {
- if (FAILED(StringCbCatEx(strpos, cbleft, L" ",
- &strpos, &cbleft,
- 0)))
- break;
- }
-
-#ifdef DEBUG
- assert(*strpos == L'\0');
-#endif
-
- one_addr(addrs, strpos, cbleft);
-
- t = 0;
- if (FAILED(StringCchLength(strpos,
- cbleft / sizeof(wchar_t),
- &t)))
- break;
-
- strpos += t;
- cbleft -= t * sizeof(wchar_t);
-
- t = sizeof(*addrs) + addrs->length - sizeof(khm_int32);
- addrs = (k5_serial_address *) BYTEOFFSET(addrs, t);
- cb_d -= t;
- }
- }
-
- StringCbLength(tbuf, sizeof(tbuf), &t);
-
- if (!buf || *pcb_buf < t) {
- *pcb_buf = t;
- return KHM_ERROR_TOO_LONG;
- }
-
- StringCbCopy(buf, *pcb_buf, tbuf);
- *pcb_buf = t;
-
- return KHM_ERROR_SUCCESS;
-}
-
-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 KHMAPI
-kvno_toString(const void * data, khm_size cbdata,
- wchar_t *destbuf, khm_size *pcbdestbuf,
- khm_int32 flags)
-{
- int resid = 0;
- int kvno;
- wchar_t buf[256];
- size_t cblength;
-
- if (cbdata != sizeof(khm_int32))
- return KHM_ERROR_INVALID_PARAM;
-
- kvno = *((khm_int32 *) data);
-
- StringCbPrintf(buf, sizeof(buf), L"#%d", kvno);
-
- 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
-serialize_krb5_addresses(krb5_address ** a, void * buf, size_t * pcbbuf)
-{
- k5_serial_address * addr;
- khm_size cb_req;
- khm_size t;
- khm_boolean overflow = FALSE;
-
- addr = (k5_serial_address *) buf;
- cb_req = 0;
-
- for(; *a; a++) {
- t = sizeof(k5_serial_address) + (*a)->length - sizeof(khm_int32);
- cb_req += t;
- if (cb_req < *pcbbuf) {
- addr->magic = K5_SERIAL_ADDRESS_MAGIC;
- addr->addrtype = (*a)->addrtype;
- addr->length = (*a)->length;
- memcpy(&addr->data, (*a)->contents, (*a)->length);
-
- addr = (k5_serial_address *) BYTEOFFSET(addr, t);
- } else {
- overflow = TRUE;
- }
- }
-
- *pcbbuf = cb_req;
-
- return (overflow)?KHM_ERROR_TOO_LONG: KHM_ERROR_SUCCESS;
-}
-
-void
-one_addr(k5_serial_address *a, wchar_t * buf, khm_size cbbuf)
-{
- wchar_t retstr[256];
- struct hostent *h = NULL;
- 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->data, a->length, af, &err);
- if (h) {
- StringCbPrintf(retstr, sizeof(retstr), L"%S", h->h_name);
- freehostent(h);
- }
- else
- h = gethostbyaddr(&a->data, a->length, af);
- if (h) {
- StringCbPrintf(retstr, sizeof(retstr), L"%S", h->h_name);
- }
-#endif
- if (h)
- goto _copy_string;
- }
- if (no_resolve || !h) {
-#ifdef HAVE_INET_NTOP
- char buf[46];
- const char *name = inet_ntop(a->addrtype, &a->data, buf, sizeof(buf));
- if (name) {
- StringCbPrintf(retstr, sizeof(retstr), L"%S", name);
- goto _copy_string;
- }
-#else
- if (a->addrtype == ADDRTYPE_INET) {
- khm_ui_4 addr = a->data;
- StringCbPrintf(retstr, sizeof(retstr),
- L"%d.%d.%d.%d",
- (int) (addr & 0xff),
- (int) ((addr >> 8) & 0xff),
- (int) ((addr >> 16)& 0xff),
- (int) ((addr >> 24)& 0xff));
- goto _copy_string;
- }
-#endif
- }
- }
-
- {
- wchar_t tmpfmt[128];
- LoadString(hResModule, IDS_UNK_ADDR_FMT, tmpfmt, sizeof(tmpfmt)/sizeof(wchar_t));
- StringCbPrintf(retstr, sizeof(retstr), tmpfmt, a->addrtype);
- }
-
- _copy_string:
- StringCbCopy(buf, cbbuf, retstr);
-}
-
+/* + * Copyright (c) 2005 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<winsock2.h> +#include<krbcred.h> +#include<krb5.h> +#include<kherror.h> +#include<strsafe.h> +#include<assert.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_PARAM; + + 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_comp(const void *d1, khm_size cb_d1, + const void *d2, khm_size cb_d2) +{ + if (cb_d1 < cb_d2) + return -1; + if (cb_d1 > cb_d2) + return 1; + return memcmp(d1, d2, cb_d1); +} + +khm_int32 KHMAPI +addr_list_toString(const void *d, khm_size cb_d, + wchar_t *buf, khm_size *pcb_buf, + khm_int32 flags) +{ + wchar_t tbuf[2048]; + wchar_t * strpos; + khm_size cbleft; + size_t t; + k5_serial_address * addrs; + + if (cb_d == 0 || d == NULL) { + tbuf[0] = L'\0'; + } else { + addrs = (k5_serial_address *) d; + + strpos = tbuf; + cbleft = sizeof(tbuf); + tbuf[0] = L'\0'; + + while (TRUE) { + if (cb_d < sizeof(*addrs) || + addrs->magic != K5_SERIAL_ADDRESS_MAGIC || + cb_d < sizeof(*addrs) + addrs->length - sizeof(khm_int32)) + break; + + if (strpos != tbuf) { + if (FAILED(StringCbCatEx(strpos, cbleft, L" ", + &strpos, &cbleft, + 0))) + break; + } + +#ifdef DEBUG + assert(*strpos == L'\0'); +#endif + + one_addr(addrs, strpos, cbleft); + + t = 0; + if (FAILED(StringCchLength(strpos, + cbleft / sizeof(wchar_t), + &t))) + break; + + strpos += t; + cbleft -= t * sizeof(wchar_t); + + t = sizeof(*addrs) + addrs->length - sizeof(khm_int32); + addrs = (k5_serial_address *) BYTEOFFSET(addrs, t); + cb_d -= t; + } + } + + StringCbLength(tbuf, sizeof(tbuf), &t); + + if (!buf || *pcb_buf < t) { + *pcb_buf = t; + return KHM_ERROR_TOO_LONG; + } + + StringCbCopy(buf, *pcb_buf, tbuf); + *pcb_buf = t; + + return KHM_ERROR_SUCCESS; +} + +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 KHMAPI +kvno_toString(const void * data, khm_size cbdata, + wchar_t *destbuf, khm_size *pcbdestbuf, + khm_int32 flags) +{ + int resid = 0; + int kvno; + wchar_t buf[256]; + size_t cblength; + + if (cbdata != sizeof(khm_int32)) + return KHM_ERROR_INVALID_PARAM; + + kvno = *((khm_int32 *) data); + + StringCbPrintf(buf, sizeof(buf), L"#%d", kvno); + + 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 +serialize_krb5_addresses(krb5_address ** a, void * buf, size_t * pcbbuf) +{ + k5_serial_address * addr; + khm_size cb_req; + khm_size t; + khm_boolean overflow = FALSE; + + addr = (k5_serial_address *) buf; + cb_req = 0; + + for(; *a; a++) { + t = sizeof(k5_serial_address) + (*a)->length - sizeof(khm_int32); + cb_req += t; + if (cb_req < *pcbbuf) { + addr->magic = K5_SERIAL_ADDRESS_MAGIC; + addr->addrtype = (*a)->addrtype; + addr->length = (*a)->length; + memcpy(&addr->data, (*a)->contents, (*a)->length); + + addr = (k5_serial_address *) BYTEOFFSET(addr, t); + } else { + overflow = TRUE; + } + } + + *pcbbuf = cb_req; + + return (overflow)?KHM_ERROR_TOO_LONG: KHM_ERROR_SUCCESS; +} + +void +one_addr(k5_serial_address *a, wchar_t * buf, khm_size cbbuf) +{ + wchar_t retstr[256]; + struct hostent *h = NULL; + 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->data, a->length, af, &err); + if (h) { + StringCbPrintf(retstr, sizeof(retstr), L"%S", h->h_name); + freehostent(h); + } + else + h = gethostbyaddr(&a->data, a->length, af); + if (h) { + StringCbPrintf(retstr, sizeof(retstr), L"%S", h->h_name); + } +#endif + if (h) + goto _copy_string; + } + if (no_resolve || !h) { +#ifdef HAVE_INET_NTOP + char buf[46]; + const char *name = inet_ntop(a->addrtype, &a->data, buf, sizeof(buf)); + if (name) { + StringCbPrintf(retstr, sizeof(retstr), L"%S", name); + goto _copy_string; + } +#else + if (a->addrtype == ADDRTYPE_INET) { + khm_ui_4 addr = a->data; + StringCbPrintf(retstr, sizeof(retstr), + L"%d.%d.%d.%d", + (int) (addr & 0xff), + (int) ((addr >> 8) & 0xff), + (int) ((addr >> 16)& 0xff), + (int) ((addr >> 24)& 0xff)); + goto _copy_string; + } +#endif + } + } + + { + wchar_t tmpfmt[128]; + LoadString(hResModule, IDS_UNK_ADDR_FMT, tmpfmt, sizeof(tmpfmt)/sizeof(wchar_t)); + StringCbPrintf(retstr, sizeof(retstr), tmpfmt, a->addrtype); + } + + _copy_string: + StringCbCopy(buf, cbbuf, retstr); +} + diff --git a/src/windows/identity/plugins/krb5/datarep.h b/src/windows/identity/plugins/krb5/datarep.h index 90f1923fa..d81e7b91e 100644 --- a/src/windows/identity/plugins/krb5/datarep.h +++ b/src/windows/identity/plugins/krb5/datarep.h @@ -1,76 +1,76 @@ -/*
- * Copyright (c) 2005 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
-
-typedef struct tag_k5_serial_address {
- khm_int32 magic; /* should be K5_SERIAL_ADDRESS_MAGIC */
- khm_int32 addrtype; /* Address type. We only know what to
- do with ADDRTYPE_INET and
- ADDRTYPE_INET6 */
- khm_size length; /* number of bytes of data in [data].
- This should always be greater than
- sizeof(khm_int32) */
- khm_int32 data; /* actually, &data is the beginning of
- the data buffer that is [length]
- bytes long. */
-} k5_serial_address;
-
-#define K5_SERIAL_ADDRESS_MAGIC 0x44ce832d
-
-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_comp(const void *d1, khm_size cb_d1,
- const void *d2, khm_size cb_d2);
-
-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
-kvno_toString(const void * data, khm_size cbdata,
- wchar_t *destbuf, khm_size *pcbdestbuf,
- khm_int32 flags);
-
-khm_int32 KHMAPI
-renew_for_cb(khm_handle cred, khm_int32 id, void * buffer,
- khm_size * pcbsize);
-
-khm_int32
-serialize_krb5_addresses(krb5_address ** a, void * buf, size_t * pcbbuf);
-
-void
-one_addr(k5_serial_address *a, wchar_t * buf, khm_size cbbuf);
-#endif
+/* + * Copyright (c) 2005 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 + +typedef struct tag_k5_serial_address { + khm_int32 magic; /* should be K5_SERIAL_ADDRESS_MAGIC */ + khm_int32 addrtype; /* Address type. We only know what to + do with ADDRTYPE_INET and + ADDRTYPE_INET6 */ + khm_size length; /* number of bytes of data in [data]. + This should always be greater than + sizeof(khm_int32) */ + khm_int32 data; /* actually, &data is the beginning of + the data buffer that is [length] + bytes long. */ +} k5_serial_address; + +#define K5_SERIAL_ADDRESS_MAGIC 0x44ce832d + +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_comp(const void *d1, khm_size cb_d1, + const void *d2, khm_size cb_d2); + +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 +kvno_toString(const void * data, khm_size cbdata, + wchar_t *destbuf, khm_size *pcbdestbuf, + khm_int32 flags); + +khm_int32 KHMAPI +renew_for_cb(khm_handle cred, khm_int32 id, void * buffer, + khm_size * pcbsize); + +khm_int32 +serialize_krb5_addresses(krb5_address ** a, void * buf, size_t * pcbbuf); + +void +one_addr(k5_serial_address *a, wchar_t * buf, khm_size cbbuf); +#endif diff --git a/src/windows/identity/plugins/krb5/errorfuncs.c b/src/windows/identity/plugins/krb5/errorfuncs.c index f631b3c0c..4c2d78c63 100644 --- a/src/windows/identity/plugins/krb5/errorfuncs.c +++ b/src/windows/identity/plugins/krb5/errorfuncs.c @@ -1,297 +1,297 @@ -/*
- * Copyright (c) 2005 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;
-
- if (WSABASEERR <= code && code < (WSABASEERR + 1064)) {
- /* winsock error */
- table_num = WSABASEERR;
- offset = code - WSABASEERR;
- }
-
- switch(table_num)
- {
- case krb_err_base:
- case kadm_err_base:
- case WSABASEERR:
- break;
- default:
-
- if (code == KRB5KRB_AP_ERR_BAD_INTEGRITY) {
- *suggestion = MSG_ERR_S_INTEGRITY;
- }
- *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 if (table_num == kadm_err_base) {
- 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;
- }
- } else if (table_num == WSABASEERR) {
- switch(code) {
- case WSAENETDOWN:
- msg_id = MSG_ERR_NETDOWN;
- sugg_id = MSG_ERR_S_NETRETRY;
- sugg_code = KHERR_SUGGEST_RETRY;
- break;
-
- case WSATRY_AGAIN:
- msg_id = MSG_ERR_TEMPDOWN;
- sugg_id = MSG_ERR_S_TEMPDOWN;
- sugg_code = KHERR_SUGGEST_RETRY;
- break;
-
- case WSAENETUNREACH:
- case WSAENETRESET:
- case WSAECONNABORTED:
- case WSAECONNRESET:
- case WSAETIMEDOUT:
- case WSAECONNREFUSED:
- case WSAEHOSTDOWN:
- case WSAEHOSTUNREACH:
- msg_id = MSG_ERR_NOHOST;
- sugg_id = MSG_ERR_S_NOHOST;
- sugg_code = KHERR_SUGGEST_RETRY;
- 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
+/* + * Copyright (c) 2005 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; + + if (WSABASEERR <= code && code < (WSABASEERR + 1064)) { + /* winsock error */ + table_num = WSABASEERR; + offset = code - WSABASEERR; + } + + switch(table_num) + { + case krb_err_base: + case kadm_err_base: + case WSABASEERR: + break; + default: + + if (code == KRB5KRB_AP_ERR_BAD_INTEGRITY) { + *suggestion = MSG_ERR_S_INTEGRITY; + } + *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 if (table_num == kadm_err_base) { + 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; + } + } else if (table_num == WSABASEERR) { + switch(code) { + case WSAENETDOWN: + msg_id = MSG_ERR_NETDOWN; + sugg_id = MSG_ERR_S_NETRETRY; + sugg_code = KHERR_SUGGEST_RETRY; + break; + + case WSATRY_AGAIN: + msg_id = MSG_ERR_TEMPDOWN; + sugg_id = MSG_ERR_S_TEMPDOWN; + sugg_code = KHERR_SUGGEST_RETRY; + break; + + case WSAENETUNREACH: + case WSAENETRESET: + case WSAECONNABORTED: + case WSAECONNRESET: + case WSAETIMEDOUT: + case WSAECONNREFUSED: + case WSAEHOSTDOWN: + case WSAEHOSTUNREACH: + msg_id = MSG_ERR_NOHOST; + sugg_id = MSG_ERR_S_NOHOST; + sugg_code = KHERR_SUGGEST_RETRY; + 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 index 86fc5b440..4b1d2e2b5 100644 --- a/src/windows/identity/plugins/krb5/errorfuncs.h +++ b/src/windows/identity/plugins/krb5/errorfuncs.h @@ -1,75 +1,75 @@ -/*
- * Copyright (c) 2005 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
+/* + * Copyright (c) 2005 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/krb5configcc.c b/src/windows/identity/plugins/krb5/krb5configcc.c index 5edc02b1f..b2b498e68 100644 --- a/src/windows/identity/plugins/krb5/krb5configcc.c +++ b/src/windows/identity/plugins/krb5/krb5configcc.c @@ -1,571 +1,571 @@ -/*
- * Copyright (c) 2005 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$ */
-
-#if _WIN32_WINNT < 0x501
-#undef _WIN32_WINNT
-#define _WIN32_WINNT 0x501
-#endif
-
-#include<krbcred.h>
-#include<krb5.h>
-#include<assert.h>
-#include<lm.h>
-#include<commctrl.h>
-#include<shlwapi.h>
-
-#include<strsafe.h>
-
-typedef struct tag_k5_file_cc {
- wchar_t path[MAX_PATH];
- khm_int32 flags;
-} k5_file_cc;
-
-#define K5_FCC_ALLOC_INCR 8
-
-#define K5_FCC_FLAG_EXISTS 1
-
-typedef struct tag_k5_ccc_data {
- khm_boolean inc_api;
- khm_boolean inc_mslsa;
- k5_file_cc * file_ccs;
- khm_size n_file_ccs;
- khm_size nc_file_ccs;
-} k5_ccc_data;
-
-typedef struct tag_k5_ccc_dlg_data {
- khui_config_node node;
- k5_ccc_data save;
- k5_ccc_data work;
-} k5_ccc_dlg_data;
-
-void k5_free_file_ccs(k5_ccc_data * d) {
- if (d->file_ccs)
- PFREE(d->file_ccs);
- d->n_file_ccs = 0;
- d->nc_file_ccs = 0;
-}
-
-void k5_flush_file_ccs(k5_ccc_data * d) {
- d->n_file_ccs = 0;
-}
-
-void k5_del_file_cc(k5_ccc_data * d, khm_size idx) {
- if (idx > d->n_file_ccs)
- return;
-
- if (idx < d->n_file_ccs - 1) {
- MoveMemory(&d->file_ccs[idx],
- &d->file_ccs[idx + 1],
- sizeof(d->file_ccs[0]) * (d->n_file_ccs - (idx + 1)));
- }
-
- d->n_file_ccs--;
-}
-
-void k5_add_file_cc(k5_ccc_data * d, wchar_t * path) {
- khm_size i;
- khm_size cch;
-
- if (FAILED(StringCchLength(path, MAX_PATH, &cch)) ||
- cch == 0)
- return;
-
- /* see if it's there first */
- for (i=0; i < d->n_file_ccs; i++) {
- if(!_wcsicmp(d->file_ccs[i].path, path))
- return;
- }
-
- if (d->n_file_ccs == d->nc_file_ccs) {
- k5_file_cc * f;
-
- d->nc_file_ccs = UBOUNDSS(d->n_file_ccs + 1,
- K5_FCC_ALLOC_INCR,
- K5_FCC_ALLOC_INCR);
-#ifdef DEBUG
- assert(d->nc_file_ccs > d->n_file_ccs);
-#endif
- f = PMALLOC(sizeof(*f) * d->nc_file_ccs);
- ZeroMemory(f, sizeof(*f) * d->nc_file_ccs);
-
- if (d->n_file_ccs > 0) {
-#ifdef DEBUG
- assert(d->file_ccs != NULL);
-#endif
- memcpy(f, d->file_ccs, sizeof(*f) * d->n_file_ccs);
- }
- if (d->file_ccs)
- PFREE(d->file_ccs);
- d->file_ccs = f;
- }
-
- StringCbCopy(d->file_ccs[d->n_file_ccs].path,
- sizeof(d->file_ccs[0].path),
- path);
- if(PathFileExists(path))
- d->file_ccs[d->n_file_ccs].flags = K5_FCC_FLAG_EXISTS;
- else
- d->file_ccs[d->n_file_ccs].flags = 0;
-
- d->n_file_ccs++;
-}
-
-void k5_read_file_cc_data(k5_ccc_data * d) {
- khm_int32 t;
- wchar_t * fclist = NULL;
- wchar_t * fc;
- khm_size cb;
-
-#ifdef DEBUG
- assert(csp_params);
-#endif
-
- d->inc_api = TRUE;
- t = TRUE;
- khc_read_int32(csp_params, L"MsLsaList", &t);
- d->inc_mslsa = t;
-
- if (khc_read_multi_string(csp_params, L"FileCCList", NULL, &cb)
- != KHM_ERROR_TOO_LONG ||
- cb <= sizeof(wchar_t) * 2) {
-
- k5_flush_file_ccs(d);
- } else {
- fclist = PMALLOC(cb);
-#ifdef DEBUG
- assert(fclist);
-#endif
- khc_read_multi_string(csp_params, L"FileCCList", fclist, &cb);
-
- for(fc = fclist; fc && *fc; fc = multi_string_next(fc)) {
- k5_add_file_cc(d, fc);
- }
-
- PFREE(fclist);
- }
-}
-
-void k5_write_file_cc_data(k5_ccc_data * d) {
- wchar_t * ms;
- khm_size cb;
- khm_size cbt;
- khm_int32 t;
- khm_size i;
-
-#ifdef DEBUG
- assert(csp_params);
-#endif
- if (KHM_FAILED(khc_read_int32(csp_params, L"MsLsaList", &t)) ||
- !!t != !!d->inc_mslsa) {
- khc_write_int32(csp_params, L"MsLsaList", !!d->inc_mslsa);
- }
-
- if (d->n_file_ccs > 0) {
- cb = d->n_file_ccs * MAX_PATH * sizeof(wchar_t);
- ms = PMALLOC(cb);
-#ifdef DEBUG
- assert(ms);
-#endif
- multi_string_init(ms, cb);
-
- for(i=0; i<d->n_file_ccs; i++) {
- cbt = cb;
- multi_string_append(ms, &cbt, d->file_ccs[i].path);
- }
-
- khc_write_multi_string(csp_params, L"FileCCList", ms);
-
- PFREE(ms);
- } else {
- if (khc_read_multi_string(csp_params, L"FileCCList", NULL, &cb)
- != KHM_ERROR_TOO_LONG ||
- cb != sizeof(wchar_t) * 2)
-
- khc_write_multi_string(csp_params, L"FileCCList", L"\0\0");
- }
-}
-
-void k5_copy_file_cc_data(k5_ccc_data * dest, const k5_ccc_data * src) {
- khm_size i;
-
- k5_flush_file_ccs(dest);
- dest->inc_mslsa = src->inc_mslsa;
- dest->inc_api = src->inc_api;
-
- for (i=0; i < src->n_file_ccs; i++) {
- k5_add_file_cc(dest, src->file_ccs[i].path);
- }
-}
-
-BOOL k5_ccc_get_mod(k5_ccc_dlg_data * d) {
- khm_size i, j;
-
- if (!!d->work.inc_mslsa != !!d->save.inc_mslsa ||
- !!d->work.inc_api != !!d->save.inc_api ||
- d->work.n_file_ccs != d->save.n_file_ccs)
- return TRUE;
-
- for (i=0; i < d->work.n_file_ccs; i++) {
- for (j=0; j < d->save.n_file_ccs; j++) {
- if (!_wcsicmp(d->work.file_ccs[i].path,
- d->save.file_ccs[j].path))
- break;
- }
- if (j >= d->save.n_file_ccs)
- return TRUE;
- }
-
- return FALSE;
-}
-
-void k5_ccc_update_ui(HWND hwnd, k5_ccc_dlg_data * d) {
- khm_size i;
- HWND lv;
-
- if (d->work.inc_api)
- CheckDlgButton(hwnd, IDC_CFG_INCAPI, BST_CHECKED);
- else
- CheckDlgButton(hwnd, IDC_CFG_INCAPI, BST_UNCHECKED);
- if (d->work.inc_mslsa)
- CheckDlgButton(hwnd, IDC_CFG_INCMSLSA, BST_CHECKED);
- else
- CheckDlgButton(hwnd, IDC_CFG_INCMSLSA, BST_UNCHECKED);
-
- lv = GetDlgItem(hwnd, IDC_CFG_FCLIST);
-#ifdef DEBUG
- assert(lv);
-#endif
- ListView_DeleteAllItems(lv);
-
- for (i=0; i<d->work.n_file_ccs; i++) {
- LVITEM lvi;
-
- ZeroMemory(&lvi, sizeof(lvi));
-
- lvi.mask = LVIF_PARAM | LVIF_TEXT;
- lvi.lParam = (LPARAM) i;
- lvi.pszText = d->work.file_ccs[i].path;
-
- ListView_InsertItem(lv, &lvi);
- }
-
- if (k5_ccc_get_mod(d)) {
- khui_cfg_set_flags(d->node,
- KHUI_CNFLAG_MODIFIED,
- KHUI_CNFLAG_MODIFIED);
- } else {
- khui_cfg_set_flags(d->node,
- 0,
- KHUI_CNFLAG_MODIFIED);
- }
-}
-
-void k5_ccc_update_data(HWND hwnd, k5_ccc_data * d) {
- if (IsDlgButtonChecked(hwnd, IDC_CFG_INCAPI) == BST_CHECKED)
- d->inc_api = TRUE;
- else
- d->inc_api = FALSE;
-
- if (IsDlgButtonChecked(hwnd, IDC_CFG_INCMSLSA) == BST_CHECKED)
- d->inc_mslsa = TRUE;
- else
- d->inc_mslsa = FALSE;
- /* everything else is controlled by buttons */
-}
-
-INT_PTR CALLBACK
-k5_ccconfig_dlgproc(HWND hwnd,
- UINT uMsg,
- WPARAM wParam,
- LPARAM lParam) {
-
- k5_ccc_dlg_data * d;
-
- switch(uMsg) {
- case WM_INITDIALOG:
- d = PMALLOC(sizeof(*d));
-#ifdef DEBUG
- assert(d);
-#endif
- ZeroMemory(d, sizeof(*d));
- k5_read_file_cc_data(&d->save);
- k5_copy_file_cc_data(&d->work, &d->save);
-
- d->node = (khui_config_node) lParam;
-
-#pragma warning(push)
-#pragma warning(disable: 4244)
- SetWindowLongPtr(hwnd, DWLP_USER, (LONG_PTR) d);
-#pragma warning(pop)
-
- {
- LVCOLUMN lvc;
- HWND lv;
- wchar_t buf[256];
- RECT r;
-
- lv = GetDlgItem(hwnd, IDC_CFG_FCLIST);
-#ifdef DEBUG
- assert(lv);
-#endif
- ZeroMemory(&lvc, sizeof(lvc));
- lvc.mask = LVCF_TEXT | LVCF_WIDTH;
-
- LoadString(hResModule, IDS_CFG_FCTITLE,
- buf, ARRAYLENGTH(buf));
-
- GetWindowRect(lv, &r);
-
- lvc.pszText = buf;
- lvc.cx = (r.right - r.left) * 9 / 10;
-
- ListView_InsertColumn(lv, 0, &lvc);
- }
-
- SendDlgItemMessage(hwnd, IDC_CFG_FCNAME, EM_SETLIMITTEXT,
- MAX_PATH - 1, 0);
-
- k5_ccc_update_ui(hwnd, d);
- break;
-
- case WM_COMMAND:
- d = (k5_ccc_dlg_data *) (DWORD_PTR)
- GetWindowLongPtr(hwnd, DWLP_USER);
- switch(wParam) {
- case MAKEWPARAM(IDC_CFG_ADD, BN_CLICKED):
- {
- wchar_t path[MAX_PATH];
- wchar_t cpath[MAX_PATH];
- khm_size i;
-
- GetDlgItemText(hwnd, IDC_CFG_FCNAME,
- cpath, ARRAYLENGTH(cpath));
-
- PathCanonicalize(path, cpath);
-
- if (!*path)
- return TRUE; /* nothing to add */
-
- for (i=0; i < d->work.n_file_ccs; i++) {
- if (!_wcsicmp(path, d->work.file_ccs[i].path)) {
-
- /* allow the user to correct case, as appropriate */
- StringCbCopy(d->work.file_ccs[i].path,
- sizeof(d->work.file_ccs[i].path),
- path);
- k5_ccc_update_ui(hwnd, d);
- return TRUE;
- }
- }
-
- /* not there. we need to add. but check a few things
- first */
- if (!PathFileExists(path)) {
- wchar_t title[64];
- wchar_t text[128];
-
- LoadString(hResModule, IDS_CFG_FCN_WARNING,
- title, ARRAYLENGTH(title));
-
- LoadString(hResModule, IDS_CFG_FCN_W_NOTFOUND,
- text, ARRAYLENGTH(text));
-#if _WIN32_WINNT >= 0x501
- if (IS_COMMCTL6())
- {
- EDITBALLOONTIP bt;
-
- bt.cbStruct = sizeof(bt);
- bt.pszTitle = title;
- bt.pszText = text;
- bt.ttiIcon = TTI_WARNING;
-
- SendDlgItemMessage(hwnd, IDC_CFG_FCNAME,
- EM_SHOWBALLOONTIP,
- 0,
- (LPARAM) &bt);
- } else {
-#endif
- MessageBox(hwnd, text, title, MB_OK | MB_ICONWARNING);
-#if _WIN32_WINNT >= 0x501
- }
-#endif
- } else if (PathIsRelative(path)) {
- wchar_t title[64];
- wchar_t text[128];
-
- LoadString(hResModule, IDS_CFG_FCN_WARNING,
- title, ARRAYLENGTH(title));
- LoadString(hResModule, IDS_CFG_FCN_W_RELATIVE,
- text, ARRAYLENGTH(text));
-
-#if _WIN32_WINNT >= 0x501
- if (IS_COMMCTL6())
- {
- EDITBALLOONTIP bt;
-
- bt.cbStruct = sizeof(bt);
- bt.pszTitle = title;
- bt.pszText = text;
- bt.ttiIcon = TTI_WARNING;
-
- SendDlgItemMessage(hwnd, IDC_CFG_FCNAME,
- EM_SHOWBALLOONTIP,
- 0,
- (LPARAM) &bt);
- } else {
-#endif
- MessageBox(hwnd, text, title, MB_OK | MB_ICONWARNING);
-#if _WIN32_WINNT >= 0x501
- }
-#endif
- }
-
- k5_add_file_cc(&d->work, path);
-
- k5_ccc_update_ui(hwnd, d);
- }
- return TRUE;
-
- case MAKEWPARAM(IDC_CFG_BROWSE, BN_CLICKED):
- {
- OPENFILENAME ofn;
- wchar_t path[MAX_PATH * 8];
- wchar_t title[128];
-
- ZeroMemory(&ofn, sizeof(ofn));
- ZeroMemory(path, sizeof(path));
-
- GetDlgItemText(hwnd, IDC_CFG_FCNAME,
- path, ARRAYLENGTH(path));
-
- /* don't pass in invalid paths */
- if (!PathFileExists(path))
- *path = 0;
-
- ofn.lStructSize = sizeof(ofn);
- ofn.hwndOwner = hwnd;
- ofn.lpstrFilter = L"All files\0*.*\0\0";
- ofn.nFilterIndex = 1;
- ofn.lpstrFile = path;
- ofn.nMaxFile = ARRAYLENGTH(path);
- ofn.lpstrTitle = title;
-
- LoadString(hResModule, IDS_CFG_FCOPENTITLE,
- title, ARRAYLENGTH(title));
-
- ofn.Flags = OFN_ALLOWMULTISELECT |
- OFN_DONTADDTORECENT |
- OFN_FORCESHOWHIDDEN |
- OFN_EXPLORER;
-
- if (GetOpenFileName(&ofn)) {
- wchar_t * p;
- wchar_t spath[MAX_PATH];
-
- p = multi_string_next(path);
- if (p) {
- /* multi select */
- for(;p && *p; p = multi_string_next(p)) {
- StringCbCopy(spath, sizeof(spath), path);
- PathAppend(spath, p);
-
- k5_add_file_cc(&d->work, spath);
- }
- } else {
- /* single select */
- k5_add_file_cc(&d->work, path);
- }
- k5_ccc_update_ui(hwnd, d);
- }
- }
- return TRUE;
-
- case MAKEWPARAM(IDC_CFG_REMOVE, BN_CLICKED):
- {
- khm_size i;
- int lv_idx;
- HWND lv;
- wchar_t buf[MAX_PATH];
-
- lv = GetDlgItem(hwnd, IDC_CFG_FCLIST);
-#ifdef DEBUG
- assert(lv);
-#endif
-
- lv_idx = -1;
- while((lv_idx = ListView_GetNextItem(lv, lv_idx,
- LVNI_SELECTED)) != -1) {
- ListView_GetItemText(lv, lv_idx, 0, buf, ARRAYLENGTH(buf));
- for (i=0; i < d->work.n_file_ccs; i++) {
- if (!_wcsicmp(buf, d->work.file_ccs[i].path)) {
- k5_del_file_cc(&d->work, i);
- break;
- }
- }
- }
-
- k5_ccc_update_ui(hwnd, d);
- }
- return TRUE;
-
- case MAKEWPARAM(IDC_CFG_INCAPI, BN_CLICKED):
- case MAKEWPARAM(IDC_CFG_INCMSLSA, BN_CLICKED):
- k5_ccc_update_data(hwnd, &d->work);
- k5_ccc_update_ui(hwnd, d);
- return TRUE;
- }
- break;
-
- case WM_DESTROY:
- d = (k5_ccc_dlg_data *) (DWORD_PTR)
- GetWindowLongPtr(hwnd, DWLP_USER);
-
- k5_free_file_ccs(&d->work);
- k5_free_file_ccs(&d->save);
- PFREE(d);
- return TRUE;
-
- case KHUI_WM_CFG_NOTIFY:
- d = (k5_ccc_dlg_data *) (DWORD_PTR)
- GetWindowLongPtr(hwnd, DWLP_USER);
-
- switch(HIWORD(wParam)) {
- case WMCFG_APPLY:
- if (k5_ccc_get_mod(d)) {
- k5_write_file_cc_data(&d->work);
- k5_copy_file_cc_data(&d->save, &d->work);
- khui_cfg_set_flags(d->node,
- KHUI_CNFLAG_APPLIED,
- KHUI_CNFLAG_APPLIED);
- k5_ccc_update_ui(hwnd, d);
-
- kmq_post_sub_msg(k5_sub, KMSG_CRED, KMSG_CRED_REFRESH, 0, 0);
- }
- break;
- }
- }
- return FALSE;
-}
+/* + * Copyright (c) 2005 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$ */ + +#if _WIN32_WINNT < 0x501 +#undef _WIN32_WINNT +#define _WIN32_WINNT 0x501 +#endif + +#include<krbcred.h> +#include<krb5.h> +#include<assert.h> +#include<lm.h> +#include<commctrl.h> +#include<shlwapi.h> + +#include<strsafe.h> + +typedef struct tag_k5_file_cc { + wchar_t path[MAX_PATH]; + khm_int32 flags; +} k5_file_cc; + +#define K5_FCC_ALLOC_INCR 8 + +#define K5_FCC_FLAG_EXISTS 1 + +typedef struct tag_k5_ccc_data { + khm_boolean inc_api; + khm_boolean inc_mslsa; + k5_file_cc * file_ccs; + khm_size n_file_ccs; + khm_size nc_file_ccs; +} k5_ccc_data; + +typedef struct tag_k5_ccc_dlg_data { + khui_config_node node; + k5_ccc_data save; + k5_ccc_data work; +} k5_ccc_dlg_data; + +void k5_free_file_ccs(k5_ccc_data * d) { + if (d->file_ccs) + PFREE(d->file_ccs); + d->n_file_ccs = 0; + d->nc_file_ccs = 0; +} + +void k5_flush_file_ccs(k5_ccc_data * d) { + d->n_file_ccs = 0; +} + +void k5_del_file_cc(k5_ccc_data * d, khm_size idx) { + if (idx > d->n_file_ccs) + return; + + if (idx < d->n_file_ccs - 1) { + MoveMemory(&d->file_ccs[idx], + &d->file_ccs[idx + 1], + sizeof(d->file_ccs[0]) * (d->n_file_ccs - (idx + 1))); + } + + d->n_file_ccs--; +} + +void k5_add_file_cc(k5_ccc_data * d, wchar_t * path) { + khm_size i; + khm_size cch; + + if (FAILED(StringCchLength(path, MAX_PATH, &cch)) || + cch == 0) + return; + + /* see if it's there first */ + for (i=0; i < d->n_file_ccs; i++) { + if(!_wcsicmp(d->file_ccs[i].path, path)) + return; + } + + if (d->n_file_ccs == d->nc_file_ccs) { + k5_file_cc * f; + + d->nc_file_ccs = UBOUNDSS(d->n_file_ccs + 1, + K5_FCC_ALLOC_INCR, + K5_FCC_ALLOC_INCR); +#ifdef DEBUG + assert(d->nc_file_ccs > d->n_file_ccs); +#endif + f = PMALLOC(sizeof(*f) * d->nc_file_ccs); + ZeroMemory(f, sizeof(*f) * d->nc_file_ccs); + + if (d->n_file_ccs > 0) { +#ifdef DEBUG + assert(d->file_ccs != NULL); +#endif + memcpy(f, d->file_ccs, sizeof(*f) * d->n_file_ccs); + } + if (d->file_ccs) + PFREE(d->file_ccs); + d->file_ccs = f; + } + + StringCbCopy(d->file_ccs[d->n_file_ccs].path, + sizeof(d->file_ccs[0].path), + path); + if(PathFileExists(path)) + d->file_ccs[d->n_file_ccs].flags = K5_FCC_FLAG_EXISTS; + else + d->file_ccs[d->n_file_ccs].flags = 0; + + d->n_file_ccs++; +} + +void k5_read_file_cc_data(k5_ccc_data * d) { + khm_int32 t; + wchar_t * fclist = NULL; + wchar_t * fc; + khm_size cb; + +#ifdef DEBUG + assert(csp_params); +#endif + + d->inc_api = TRUE; + t = TRUE; + khc_read_int32(csp_params, L"MsLsaList", &t); + d->inc_mslsa = t; + + if (khc_read_multi_string(csp_params, L"FileCCList", NULL, &cb) + != KHM_ERROR_TOO_LONG || + cb <= sizeof(wchar_t) * 2) { + + k5_flush_file_ccs(d); + } else { + fclist = PMALLOC(cb); +#ifdef DEBUG + assert(fclist); +#endif + khc_read_multi_string(csp_params, L"FileCCList", fclist, &cb); + + for(fc = fclist; fc && *fc; fc = multi_string_next(fc)) { + k5_add_file_cc(d, fc); + } + + PFREE(fclist); + } +} + +void k5_write_file_cc_data(k5_ccc_data * d) { + wchar_t * ms; + khm_size cb; + khm_size cbt; + khm_int32 t; + khm_size i; + +#ifdef DEBUG + assert(csp_params); +#endif + if (KHM_FAILED(khc_read_int32(csp_params, L"MsLsaList", &t)) || + !!t != !!d->inc_mslsa) { + khc_write_int32(csp_params, L"MsLsaList", !!d->inc_mslsa); + } + + if (d->n_file_ccs > 0) { + cb = d->n_file_ccs * MAX_PATH * sizeof(wchar_t); + ms = PMALLOC(cb); +#ifdef DEBUG + assert(ms); +#endif + multi_string_init(ms, cb); + + for(i=0; i<d->n_file_ccs; i++) { + cbt = cb; + multi_string_append(ms, &cbt, d->file_ccs[i].path); + } + + khc_write_multi_string(csp_params, L"FileCCList", ms); + + PFREE(ms); + } else { + if (khc_read_multi_string(csp_params, L"FileCCList", NULL, &cb) + != KHM_ERROR_TOO_LONG || + cb != sizeof(wchar_t) * 2) + + khc_write_multi_string(csp_params, L"FileCCList", L"\0\0"); + } +} + +void k5_copy_file_cc_data(k5_ccc_data * dest, const k5_ccc_data * src) { + khm_size i; + + k5_flush_file_ccs(dest); + dest->inc_mslsa = src->inc_mslsa; + dest->inc_api = src->inc_api; + + for (i=0; i < src->n_file_ccs; i++) { + k5_add_file_cc(dest, src->file_ccs[i].path); + } +} + +BOOL k5_ccc_get_mod(k5_ccc_dlg_data * d) { + khm_size i, j; + + if (!!d->work.inc_mslsa != !!d->save.inc_mslsa || + !!d->work.inc_api != !!d->save.inc_api || + d->work.n_file_ccs != d->save.n_file_ccs) + return TRUE; + + for (i=0; i < d->work.n_file_ccs; i++) { + for (j=0; j < d->save.n_file_ccs; j++) { + if (!_wcsicmp(d->work.file_ccs[i].path, + d->save.file_ccs[j].path)) + break; + } + if (j >= d->save.n_file_ccs) + return TRUE; + } + + return FALSE; +} + +void k5_ccc_update_ui(HWND hwnd, k5_ccc_dlg_data * d) { + khm_size i; + HWND lv; + + if (d->work.inc_api) + CheckDlgButton(hwnd, IDC_CFG_INCAPI, BST_CHECKED); + else + CheckDlgButton(hwnd, IDC_CFG_INCAPI, BST_UNCHECKED); + if (d->work.inc_mslsa) + CheckDlgButton(hwnd, IDC_CFG_INCMSLSA, BST_CHECKED); + else + CheckDlgButton(hwnd, IDC_CFG_INCMSLSA, BST_UNCHECKED); + + lv = GetDlgItem(hwnd, IDC_CFG_FCLIST); +#ifdef DEBUG + assert(lv); +#endif + ListView_DeleteAllItems(lv); + + for (i=0; i<d->work.n_file_ccs; i++) { + LVITEM lvi; + + ZeroMemory(&lvi, sizeof(lvi)); + + lvi.mask = LVIF_PARAM | LVIF_TEXT; + lvi.lParam = (LPARAM) i; + lvi.pszText = d->work.file_ccs[i].path; + + ListView_InsertItem(lv, &lvi); + } + + if (k5_ccc_get_mod(d)) { + khui_cfg_set_flags(d->node, + KHUI_CNFLAG_MODIFIED, + KHUI_CNFLAG_MODIFIED); + } else { + khui_cfg_set_flags(d->node, + 0, + KHUI_CNFLAG_MODIFIED); + } +} + +void k5_ccc_update_data(HWND hwnd, k5_ccc_data * d) { + if (IsDlgButtonChecked(hwnd, IDC_CFG_INCAPI) == BST_CHECKED) + d->inc_api = TRUE; + else + d->inc_api = FALSE; + + if (IsDlgButtonChecked(hwnd, IDC_CFG_INCMSLSA) == BST_CHECKED) + d->inc_mslsa = TRUE; + else + d->inc_mslsa = FALSE; + /* everything else is controlled by buttons */ +} + +INT_PTR CALLBACK +k5_ccconfig_dlgproc(HWND hwnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam) { + + k5_ccc_dlg_data * d; + + switch(uMsg) { + case WM_INITDIALOG: + d = PMALLOC(sizeof(*d)); +#ifdef DEBUG + assert(d); +#endif + ZeroMemory(d, sizeof(*d)); + k5_read_file_cc_data(&d->save); + k5_copy_file_cc_data(&d->work, &d->save); + + d->node = (khui_config_node) lParam; + +#pragma warning(push) +#pragma warning(disable: 4244) + SetWindowLongPtr(hwnd, DWLP_USER, (LONG_PTR) d); +#pragma warning(pop) + + { + LVCOLUMN lvc; + HWND lv; + wchar_t buf[256]; + RECT r; + + lv = GetDlgItem(hwnd, IDC_CFG_FCLIST); +#ifdef DEBUG + assert(lv); +#endif + ZeroMemory(&lvc, sizeof(lvc)); + lvc.mask = LVCF_TEXT | LVCF_WIDTH; + + LoadString(hResModule, IDS_CFG_FCTITLE, + buf, ARRAYLENGTH(buf)); + + GetWindowRect(lv, &r); + + lvc.pszText = buf; + lvc.cx = (r.right - r.left) * 9 / 10; + + ListView_InsertColumn(lv, 0, &lvc); + } + + SendDlgItemMessage(hwnd, IDC_CFG_FCNAME, EM_SETLIMITTEXT, + MAX_PATH - 1, 0); + + k5_ccc_update_ui(hwnd, d); + break; + + case WM_COMMAND: + d = (k5_ccc_dlg_data *) (DWORD_PTR) + GetWindowLongPtr(hwnd, DWLP_USER); + switch(wParam) { + case MAKEWPARAM(IDC_CFG_ADD, BN_CLICKED): + { + wchar_t path[MAX_PATH]; + wchar_t cpath[MAX_PATH]; + khm_size i; + + GetDlgItemText(hwnd, IDC_CFG_FCNAME, + cpath, ARRAYLENGTH(cpath)); + + PathCanonicalize(path, cpath); + + if (!*path) + return TRUE; /* nothing to add */ + + for (i=0; i < d->work.n_file_ccs; i++) { + if (!_wcsicmp(path, d->work.file_ccs[i].path)) { + + /* allow the user to correct case, as appropriate */ + StringCbCopy(d->work.file_ccs[i].path, + sizeof(d->work.file_ccs[i].path), + path); + k5_ccc_update_ui(hwnd, d); + return TRUE; + } + } + + /* not there. we need to add. but check a few things + first */ + if (!PathFileExists(path)) { + wchar_t title[64]; + wchar_t text[128]; + + LoadString(hResModule, IDS_CFG_FCN_WARNING, + title, ARRAYLENGTH(title)); + + LoadString(hResModule, IDS_CFG_FCN_W_NOTFOUND, + text, ARRAYLENGTH(text)); +#if _WIN32_WINNT >= 0x501 + if (IS_COMMCTL6()) + { + EDITBALLOONTIP bt; + + bt.cbStruct = sizeof(bt); + bt.pszTitle = title; + bt.pszText = text; + bt.ttiIcon = TTI_WARNING; + + SendDlgItemMessage(hwnd, IDC_CFG_FCNAME, + EM_SHOWBALLOONTIP, + 0, + (LPARAM) &bt); + } else { +#endif + MessageBox(hwnd, text, title, MB_OK | MB_ICONWARNING); +#if _WIN32_WINNT >= 0x501 + } +#endif + } else if (PathIsRelative(path)) { + wchar_t title[64]; + wchar_t text[128]; + + LoadString(hResModule, IDS_CFG_FCN_WARNING, + title, ARRAYLENGTH(title)); + LoadString(hResModule, IDS_CFG_FCN_W_RELATIVE, + text, ARRAYLENGTH(text)); + +#if _WIN32_WINNT >= 0x501 + if (IS_COMMCTL6()) + { + EDITBALLOONTIP bt; + + bt.cbStruct = sizeof(bt); + bt.pszTitle = title; + bt.pszText = text; + bt.ttiIcon = TTI_WARNING; + + SendDlgItemMessage(hwnd, IDC_CFG_FCNAME, + EM_SHOWBALLOONTIP, + 0, + (LPARAM) &bt); + } else { +#endif + MessageBox(hwnd, text, title, MB_OK | MB_ICONWARNING); +#if _WIN32_WINNT >= 0x501 + } +#endif + } + + k5_add_file_cc(&d->work, path); + + k5_ccc_update_ui(hwnd, d); + } + return TRUE; + + case MAKEWPARAM(IDC_CFG_BROWSE, BN_CLICKED): + { + OPENFILENAME ofn; + wchar_t path[MAX_PATH * 8]; + wchar_t title[128]; + + ZeroMemory(&ofn, sizeof(ofn)); + ZeroMemory(path, sizeof(path)); + + GetDlgItemText(hwnd, IDC_CFG_FCNAME, + path, ARRAYLENGTH(path)); + + /* don't pass in invalid paths */ + if (!PathFileExists(path)) + *path = 0; + + ofn.lStructSize = sizeof(ofn); + ofn.hwndOwner = hwnd; + ofn.lpstrFilter = L"All files\0*.*\0\0"; + ofn.nFilterIndex = 1; + ofn.lpstrFile = path; + ofn.nMaxFile = ARRAYLENGTH(path); + ofn.lpstrTitle = title; + + LoadString(hResModule, IDS_CFG_FCOPENTITLE, + title, ARRAYLENGTH(title)); + + ofn.Flags = OFN_ALLOWMULTISELECT | + OFN_DONTADDTORECENT | + OFN_FORCESHOWHIDDEN | + OFN_EXPLORER; + + if (GetOpenFileName(&ofn)) { + wchar_t * p; + wchar_t spath[MAX_PATH]; + + p = multi_string_next(path); + if (p) { + /* multi select */ + for(;p && *p; p = multi_string_next(p)) { + StringCbCopy(spath, sizeof(spath), path); + PathAppend(spath, p); + + k5_add_file_cc(&d->work, spath); + } + } else { + /* single select */ + k5_add_file_cc(&d->work, path); + } + k5_ccc_update_ui(hwnd, d); + } + } + return TRUE; + + case MAKEWPARAM(IDC_CFG_REMOVE, BN_CLICKED): + { + khm_size i; + int lv_idx; + HWND lv; + wchar_t buf[MAX_PATH]; + + lv = GetDlgItem(hwnd, IDC_CFG_FCLIST); +#ifdef DEBUG + assert(lv); +#endif + + lv_idx = -1; + while((lv_idx = ListView_GetNextItem(lv, lv_idx, + LVNI_SELECTED)) != -1) { + ListView_GetItemText(lv, lv_idx, 0, buf, ARRAYLENGTH(buf)); + for (i=0; i < d->work.n_file_ccs; i++) { + if (!_wcsicmp(buf, d->work.file_ccs[i].path)) { + k5_del_file_cc(&d->work, i); + break; + } + } + } + + k5_ccc_update_ui(hwnd, d); + } + return TRUE; + + case MAKEWPARAM(IDC_CFG_INCAPI, BN_CLICKED): + case MAKEWPARAM(IDC_CFG_INCMSLSA, BN_CLICKED): + k5_ccc_update_data(hwnd, &d->work); + k5_ccc_update_ui(hwnd, d); + return TRUE; + } + break; + + case WM_DESTROY: + d = (k5_ccc_dlg_data *) (DWORD_PTR) + GetWindowLongPtr(hwnd, DWLP_USER); + + k5_free_file_ccs(&d->work); + k5_free_file_ccs(&d->save); + PFREE(d); + return TRUE; + + case KHUI_WM_CFG_NOTIFY: + d = (k5_ccc_dlg_data *) (DWORD_PTR) + GetWindowLongPtr(hwnd, DWLP_USER); + + switch(HIWORD(wParam)) { + case WMCFG_APPLY: + if (k5_ccc_get_mod(d)) { + k5_write_file_cc_data(&d->work); + k5_copy_file_cc_data(&d->save, &d->work); + khui_cfg_set_flags(d->node, + KHUI_CNFLAG_APPLIED, + KHUI_CNFLAG_APPLIED); + k5_ccc_update_ui(hwnd, d); + + kmq_post_sub_msg(k5_sub, KMSG_CRED, KMSG_CRED_REFRESH, 0, 0); + } + break; + } + } + return FALSE; +} diff --git a/src/windows/identity/plugins/krb5/krb5configid.c b/src/windows/identity/plugins/krb5/krb5configid.c index e09281906..b5af1c2b2 100644 --- a/src/windows/identity/plugins/krb5/krb5configid.c +++ b/src/windows/identity/plugins/krb5/krb5configid.c @@ -1,355 +1,355 @@ -/*
- * Copyright (c) 2005 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>
-#include<commctrl.h>
-#include<shlwapi.h>
-
-#include<strsafe.h>
-
-typedef struct tag_k5_id_dlg_data {
- khui_config_init_data cfg;
-
- khm_handle ident;
-
- khui_tracker tc_life;
- khui_tracker tc_renew;
-
- wchar_t ccache[KRB5_MAXCCH_CCNAME];
-
- khm_boolean renewable;
- khm_boolean forwardable;
- khm_boolean proxiable;
- khm_boolean addressless;
-
- DWORD public_ip;
-
- time_t life;
- time_t renew_life;
-} k5_id_dlg_data;
-
-static void
-k5_id_read_params(k5_id_dlg_data * d) {
-
- wchar_t idname[KCDB_IDENT_MAXCCH_NAME];
- khm_size cb;
- khm_int32 rv;
- khm_int32 t;
- khm_handle csp_ident;
- khm_handle csp_idroot = NULL;
-
- cb = sizeof(idname);
- rv = khui_cfg_get_name(d->cfg.ctx_node, idname, &cb);
-#ifdef DEBUG
- assert(KHM_SUCCEEDED(rv));
-#endif
-
- rv = kcdb_identity_create(idname, 0, &d->ident);
-#ifdef DEBUG
- assert(KHM_SUCCEEDED(rv));
-#endif
-
- rv = kcdb_identity_get_config(d->ident, 0, &csp_idroot);
- if (KHM_SUCCEEDED(rv) &&
- KHM_SUCCEEDED(khc_open_space(csp_idroot, CSNAME_KRB5CRED, 0,
- &csp_ident))) {
- khc_shadow_space(csp_ident, csp_params);
- } else {
- csp_ident = csp_params;
- }
-
- if (csp_idroot)
- khc_close_space(csp_idroot);
-
- rv = khc_read_int32(csp_ident, L"DefaultLifetime", &t);
- if (KHM_SUCCEEDED(rv))
- d->life = t;
- else
- d->life = 36000;
-
- rv = khc_read_int32(csp_ident, L"DefaultRenewLifetime", &t);
- if (KHM_SUCCEEDED(rv))
- d->renew_life = t;
- else
- d->renew_life = 604800;
-
- rv = khc_read_int32(csp_ident, L"Renewable", &t);
- if (KHM_SUCCEEDED(rv))
- d->renewable = !!t;
- else
- d->renewable = TRUE;
-
- rv = khc_read_int32(csp_ident, L"Forwardable", &t);
- if (KHM_SUCCEEDED(rv))
- d->forwardable = !!t;
- else
- d->forwardable = FALSE;
-
- rv = khc_read_int32(csp_ident, L"Proxiable", &t);
- if (KHM_SUCCEEDED(rv))
- d->proxiable = !!t;
- else
- d->proxiable = FALSE;
-
- rv = khc_read_int32(csp_ident, L"Addressless", &t);
- if (KHM_SUCCEEDED(rv))
- d->addressless = !!t;
- else
- d->addressless = TRUE;
-
- rv = khc_read_int32(csp_ident, L"PublicIP", &t);
- if (KHM_SUCCEEDED(rv))
- d->public_ip = (khm_ui_4) t;
- else
- d->public_ip = 0;
-
- cb = sizeof(d->ccache);
- rv = khc_read_string(csp_ident, L"DefaultCCName", d->ccache, &cb);
- if (KHM_FAILED(rv) || cb <= sizeof(wchar_t)) {
- cb = sizeof(d->ccache);
- if (KHM_FAILED(kcdb_identity_get_attr(d->ident, attr_id_krb5_ccname,
- NULL, d->ccache, &cb)))
- ZeroMemory(d->ccache, sizeof(d->ccache));
- }
-
- 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;
-
- if (csp_ident != csp_params)
- khc_close_space(csp_ident);
-}
-
-static khm_boolean
-k5_id_is_mod(HWND hw, k5_id_dlg_data * d) {
- wchar_t ccache[KRB5_MAXCCH_CCNAME];
- DWORD dwaddress = 0;
-
- GetDlgItemText(hw, IDC_CFG_CCACHE, ccache, ARRAYLENGTH(ccache));
-
- SendDlgItemMessage(hw, IDC_CFG_PUBLICIP, IPM_GETADDRESS,
- 0, (LPARAM) &dwaddress);
-
- if (_wcsicmp(ccache, d->ccache) ||
-
- d->tc_renew.current != d->renew_life ||
-
- d->tc_life.current != d->life ||
-
- (IsDlgButtonChecked(hw, IDC_CFG_RENEW) == BST_CHECKED) != d->renewable ||
-
- (IsDlgButtonChecked(hw, IDC_CFG_FORWARD) == BST_CHECKED) != d->forwardable ||
-
- (IsDlgButtonChecked(hw, IDC_CFG_ADDRESSLESS) == BST_CHECKED)
- != d->addressless ||
-
- dwaddress != d->public_ip)
-
- return TRUE;
-
- return FALSE;
-}
-
-static void
-k5_id_check_mod(HWND hw, k5_id_dlg_data * d) {
- BOOL modified = k5_id_is_mod(hw, d);
-
- khui_cfg_set_flags_inst(&d->cfg,
- (modified)?KHUI_CNFLAG_MODIFIED:0,
- KHUI_CNFLAG_MODIFIED);
-}
-
-static void
-k5_id_write_params(HWND hw, k5_id_dlg_data * d) {
-
- khm_handle csp_idroot = NULL;
- khm_handle csp_ident = NULL;
- wchar_t ccache[KRB5_MAXCCH_CCNAME];
- khm_size cb;
- khm_int32 rv;
- khm_boolean b;
- DWORD dwaddress = 0;
-
- if (!k5_id_is_mod(hw, d))
- return;
-
- rv = kcdb_identity_get_config(d->ident, KHM_FLAG_CREATE, &csp_idroot);
- if (KHM_SUCCEEDED(rv)) {
- khc_open_space(csp_idroot, CSNAME_KRB5CRED,
- KHM_FLAG_CREATE,
- &csp_ident);
- }
-
- if (csp_idroot)
- khc_close_space(csp_idroot);
-
- if (!csp_ident)
- return;
-
- if (d->life != d->tc_life.current) {
- d->life = d->tc_life.current;
- khc_write_int32(csp_ident, L"DefaultLifetime", (khm_int32) d->life);
- }
-
- if (d->renew_life != d->tc_renew.current) {
- d->renew_life = d->tc_renew.current;
- khc_write_int32(csp_ident, L"DefaultRenewLifetime", (khm_int32) d->renew_life);
- }
-
- b = (IsDlgButtonChecked(hw, IDC_CFG_RENEW) == BST_CHECKED);
- if (b != d->renewable) {
- d->renewable = b;
- khc_write_int32(csp_ident, L"Renewable", (khm_int32) b);
- }
-
- b = (IsDlgButtonChecked(hw, IDC_CFG_FORWARD) == BST_CHECKED);
- if (b != d->forwardable) {
- d->forwardable = b;
- khc_write_int32(csp_ident, L"Forwardable", (khm_int32) b);
- }
-
- b = (IsDlgButtonChecked(hw, IDC_CFG_ADDRESSLESS) == BST_CHECKED);
- if (b != d->addressless) {
- d->addressless = b;
- khc_write_int32(csp_ident, L"Addressless", (khm_int32) b);
- }
-
- SendDlgItemMessage(hw, IDC_CFG_PUBLICIP, IPM_GETADDRESS,
- 0, (LPARAM) &dwaddress);
-
- if (dwaddress != d->public_ip) {
- d->public_ip = dwaddress;
- khc_write_int32(csp_ident, L"PublicIP", (khm_int32) dwaddress);
- }
-
- GetDlgItemText(hw, IDC_CFG_CCACHE, ccache, ARRAYLENGTH(ccache));
-
- if (SUCCEEDED(StringCbLength(ccache, sizeof(ccache), &cb)) &&
- _wcsicmp(ccache, d->ccache)) {
- khc_write_string(csp_ident, L"DefaultCCName", ccache);
- StringCbCopy(d->ccache, sizeof(d->ccache), ccache);
- } else {
- khc_remove_value(csp_ident, L"DefaultCCName", KCONF_FLAG_USER);
- }
-
- if (csp_ident)
- khc_close_space(csp_ident);
-
- khui_cfg_set_flags_inst(&d->cfg,
- KHUI_CNFLAG_APPLIED,
- KHUI_CNFLAG_APPLIED | KHUI_CNFLAG_MODIFIED);
-}
-
-INT_PTR CALLBACK
-k5_id_tab_dlgproc(HWND hwnd,
- UINT uMsg,
- WPARAM wParam,
- LPARAM lParam) {
-
- k5_id_dlg_data * d;
-
- switch(uMsg) {
- case WM_INITDIALOG:
- d = PMALLOC(sizeof(*d));
-#ifdef DEBUG
- assert(d);
-#endif
- ZeroMemory(d, sizeof(*d));
-
- d->cfg = *((khui_config_init_data *) lParam);
-
-#pragma warning(push)
-#pragma warning(disable: 4244)
- SetWindowLongPtr(hwnd, DWLP_USER, (LONG_PTR) d);
-#pragma warning(pop)
-
- k5_id_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_refresh(&d->tc_life);
- khui_tracker_refresh(&d->tc_renew);
-
- SetDlgItemText(hwnd, IDC_CFG_CCACHE, d->ccache);
-
- CheckDlgButton(hwnd, IDC_CFG_RENEW,
- (d->renewable? BST_CHECKED: BST_UNCHECKED));
-
- CheckDlgButton(hwnd, IDC_CFG_FORWARD,
- (d->forwardable? BST_CHECKED: BST_UNCHECKED));
-
- CheckDlgButton(hwnd, IDC_CFG_ADDRESSLESS,
- (d->addressless? BST_CHECKED: BST_UNCHECKED));
-
- SendDlgItemMessage(hwnd, IDC_CFG_PUBLICIP,
- IPM_SETADDRESS,
- 0, (LPARAM) d->public_ip);
- break;
-
- case WM_COMMAND:
- d = (k5_id_dlg_data *) (LONG_PTR)
- GetWindowLongPtr(hwnd, DWLP_USER);
-
- if (HIWORD(wParam) == EN_CHANGE ||
- HIWORD(wParam) == BN_CLICKED)
- k5_id_check_mod(hwnd, d);
- break;
-
- case KHUI_WM_CFG_NOTIFY:
- d = (k5_id_dlg_data *) (LONG_PTR)
- GetWindowLongPtr(hwnd, DWLP_USER);
-
- if (HIWORD(wParam) == WMCFG_APPLY) {
- k5_id_write_params(hwnd, d);
- }
- break;
-
- case WM_DESTROY:
- d = (k5_id_dlg_data *) (LONG_PTR)
- GetWindowLongPtr(hwnd, DWLP_USER);
-
- khui_tracker_kill_controls(&d->tc_life);
- khui_tracker_kill_controls(&d->tc_renew);
-
- if (d->ident)
- kcdb_identity_release(d->ident);
-
- PFREE(d);
- break;
- }
- return FALSE;
-}
+/* + * Copyright (c) 2005 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> +#include<commctrl.h> +#include<shlwapi.h> + +#include<strsafe.h> + +typedef struct tag_k5_id_dlg_data { + khui_config_init_data cfg; + + khm_handle ident; + + khui_tracker tc_life; + khui_tracker tc_renew; + + wchar_t ccache[KRB5_MAXCCH_CCNAME]; + + khm_boolean renewable; + khm_boolean forwardable; + khm_boolean proxiable; + khm_boolean addressless; + + DWORD public_ip; + + time_t life; + time_t renew_life; +} k5_id_dlg_data; + +static void +k5_id_read_params(k5_id_dlg_data * d) { + + wchar_t idname[KCDB_IDENT_MAXCCH_NAME]; + khm_size cb; + khm_int32 rv; + khm_int32 t; + khm_handle csp_ident; + khm_handle csp_idroot = NULL; + + cb = sizeof(idname); + rv = khui_cfg_get_name(d->cfg.ctx_node, idname, &cb); +#ifdef DEBUG + assert(KHM_SUCCEEDED(rv)); +#endif + + rv = kcdb_identity_create(idname, 0, &d->ident); +#ifdef DEBUG + assert(KHM_SUCCEEDED(rv)); +#endif + + rv = kcdb_identity_get_config(d->ident, 0, &csp_idroot); + if (KHM_SUCCEEDED(rv) && + KHM_SUCCEEDED(khc_open_space(csp_idroot, CSNAME_KRB5CRED, 0, + &csp_ident))) { + khc_shadow_space(csp_ident, csp_params); + } else { + csp_ident = csp_params; + } + + if (csp_idroot) + khc_close_space(csp_idroot); + + rv = khc_read_int32(csp_ident, L"DefaultLifetime", &t); + if (KHM_SUCCEEDED(rv)) + d->life = t; + else + d->life = 36000; + + rv = khc_read_int32(csp_ident, L"DefaultRenewLifetime", &t); + if (KHM_SUCCEEDED(rv)) + d->renew_life = t; + else + d->renew_life = 604800; + + rv = khc_read_int32(csp_ident, L"Renewable", &t); + if (KHM_SUCCEEDED(rv)) + d->renewable = !!t; + else + d->renewable = TRUE; + + rv = khc_read_int32(csp_ident, L"Forwardable", &t); + if (KHM_SUCCEEDED(rv)) + d->forwardable = !!t; + else + d->forwardable = FALSE; + + rv = khc_read_int32(csp_ident, L"Proxiable", &t); + if (KHM_SUCCEEDED(rv)) + d->proxiable = !!t; + else + d->proxiable = FALSE; + + rv = khc_read_int32(csp_ident, L"Addressless", &t); + if (KHM_SUCCEEDED(rv)) + d->addressless = !!t; + else + d->addressless = TRUE; + + rv = khc_read_int32(csp_ident, L"PublicIP", &t); + if (KHM_SUCCEEDED(rv)) + d->public_ip = (khm_ui_4) t; + else + d->public_ip = 0; + + cb = sizeof(d->ccache); + rv = khc_read_string(csp_ident, L"DefaultCCName", d->ccache, &cb); + if (KHM_FAILED(rv) || cb <= sizeof(wchar_t)) { + cb = sizeof(d->ccache); + if (KHM_FAILED(kcdb_identity_get_attr(d->ident, attr_id_krb5_ccname, + NULL, d->ccache, &cb))) + ZeroMemory(d->ccache, sizeof(d->ccache)); + } + + 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; + + if (csp_ident != csp_params) + khc_close_space(csp_ident); +} + +static khm_boolean +k5_id_is_mod(HWND hw, k5_id_dlg_data * d) { + wchar_t ccache[KRB5_MAXCCH_CCNAME]; + DWORD dwaddress = 0; + + GetDlgItemText(hw, IDC_CFG_CCACHE, ccache, ARRAYLENGTH(ccache)); + + SendDlgItemMessage(hw, IDC_CFG_PUBLICIP, IPM_GETADDRESS, + 0, (LPARAM) &dwaddress); + + if (_wcsicmp(ccache, d->ccache) || + + d->tc_renew.current != d->renew_life || + + d->tc_life.current != d->life || + + (IsDlgButtonChecked(hw, IDC_CFG_RENEW) == BST_CHECKED) != d->renewable || + + (IsDlgButtonChecked(hw, IDC_CFG_FORWARD) == BST_CHECKED) != d->forwardable || + + (IsDlgButtonChecked(hw, IDC_CFG_ADDRESSLESS) == BST_CHECKED) + != d->addressless || + + dwaddress != d->public_ip) + + return TRUE; + + return FALSE; +} + +static void +k5_id_check_mod(HWND hw, k5_id_dlg_data * d) { + BOOL modified = k5_id_is_mod(hw, d); + + khui_cfg_set_flags_inst(&d->cfg, + (modified)?KHUI_CNFLAG_MODIFIED:0, + KHUI_CNFLAG_MODIFIED); +} + +static void +k5_id_write_params(HWND hw, k5_id_dlg_data * d) { + + khm_handle csp_idroot = NULL; + khm_handle csp_ident = NULL; + wchar_t ccache[KRB5_MAXCCH_CCNAME]; + khm_size cb; + khm_int32 rv; + khm_boolean b; + DWORD dwaddress = 0; + + if (!k5_id_is_mod(hw, d)) + return; + + rv = kcdb_identity_get_config(d->ident, KHM_FLAG_CREATE, &csp_idroot); + if (KHM_SUCCEEDED(rv)) { + khc_open_space(csp_idroot, CSNAME_KRB5CRED, + KHM_FLAG_CREATE, + &csp_ident); + } + + if (csp_idroot) + khc_close_space(csp_idroot); + + if (!csp_ident) + return; + + if (d->life != d->tc_life.current) { + d->life = d->tc_life.current; + khc_write_int32(csp_ident, L"DefaultLifetime", (khm_int32) d->life); + } + + if (d->renew_life != d->tc_renew.current) { + d->renew_life = d->tc_renew.current; + khc_write_int32(csp_ident, L"DefaultRenewLifetime", (khm_int32) d->renew_life); + } + + b = (IsDlgButtonChecked(hw, IDC_CFG_RENEW) == BST_CHECKED); + if (b != d->renewable) { + d->renewable = b; + khc_write_int32(csp_ident, L"Renewable", (khm_int32) b); + } + + b = (IsDlgButtonChecked(hw, IDC_CFG_FORWARD) == BST_CHECKED); + if (b != d->forwardable) { + d->forwardable = b; + khc_write_int32(csp_ident, L"Forwardable", (khm_int32) b); + } + + b = (IsDlgButtonChecked(hw, IDC_CFG_ADDRESSLESS) == BST_CHECKED); + if (b != d->addressless) { + d->addressless = b; + khc_write_int32(csp_ident, L"Addressless", (khm_int32) b); + } + + SendDlgItemMessage(hw, IDC_CFG_PUBLICIP, IPM_GETADDRESS, + 0, (LPARAM) &dwaddress); + + if (dwaddress != d->public_ip) { + d->public_ip = dwaddress; + khc_write_int32(csp_ident, L"PublicIP", (khm_int32) dwaddress); + } + + GetDlgItemText(hw, IDC_CFG_CCACHE, ccache, ARRAYLENGTH(ccache)); + + if (SUCCEEDED(StringCbLength(ccache, sizeof(ccache), &cb)) && + _wcsicmp(ccache, d->ccache)) { + khc_write_string(csp_ident, L"DefaultCCName", ccache); + StringCbCopy(d->ccache, sizeof(d->ccache), ccache); + } else { + khc_remove_value(csp_ident, L"DefaultCCName", KCONF_FLAG_USER); + } + + if (csp_ident) + khc_close_space(csp_ident); + + khui_cfg_set_flags_inst(&d->cfg, + KHUI_CNFLAG_APPLIED, + KHUI_CNFLAG_APPLIED | KHUI_CNFLAG_MODIFIED); +} + +INT_PTR CALLBACK +k5_id_tab_dlgproc(HWND hwnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam) { + + k5_id_dlg_data * d; + + switch(uMsg) { + case WM_INITDIALOG: + d = PMALLOC(sizeof(*d)); +#ifdef DEBUG + assert(d); +#endif + ZeroMemory(d, sizeof(*d)); + + d->cfg = *((khui_config_init_data *) lParam); + +#pragma warning(push) +#pragma warning(disable: 4244) + SetWindowLongPtr(hwnd, DWLP_USER, (LONG_PTR) d); +#pragma warning(pop) + + k5_id_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_refresh(&d->tc_life); + khui_tracker_refresh(&d->tc_renew); + + SetDlgItemText(hwnd, IDC_CFG_CCACHE, d->ccache); + + CheckDlgButton(hwnd, IDC_CFG_RENEW, + (d->renewable? BST_CHECKED: BST_UNCHECKED)); + + CheckDlgButton(hwnd, IDC_CFG_FORWARD, + (d->forwardable? BST_CHECKED: BST_UNCHECKED)); + + CheckDlgButton(hwnd, IDC_CFG_ADDRESSLESS, + (d->addressless? BST_CHECKED: BST_UNCHECKED)); + + SendDlgItemMessage(hwnd, IDC_CFG_PUBLICIP, + IPM_SETADDRESS, + 0, (LPARAM) d->public_ip); + break; + + case WM_COMMAND: + d = (k5_id_dlg_data *) (LONG_PTR) + GetWindowLongPtr(hwnd, DWLP_USER); + + if (HIWORD(wParam) == EN_CHANGE || + HIWORD(wParam) == BN_CLICKED) + k5_id_check_mod(hwnd, d); + break; + + case KHUI_WM_CFG_NOTIFY: + d = (k5_id_dlg_data *) (LONG_PTR) + GetWindowLongPtr(hwnd, DWLP_USER); + + if (HIWORD(wParam) == WMCFG_APPLY) { + k5_id_write_params(hwnd, d); + } + break; + + case WM_DESTROY: + d = (k5_id_dlg_data *) (LONG_PTR) + GetWindowLongPtr(hwnd, DWLP_USER); + + khui_tracker_kill_controls(&d->tc_life); + khui_tracker_kill_controls(&d->tc_renew); + + if (d->ident) + kcdb_identity_release(d->ident); + + PFREE(d); + break; + } + return FALSE; +} diff --git a/src/windows/identity/plugins/krb5/krb5configids.c b/src/windows/identity/plugins/krb5/krb5configids.c index 5f4729253..8d6afd473 100644 --- a/src/windows/identity/plugins/krb5/krb5configids.c +++ b/src/windows/identity/plugins/krb5/krb5configids.c @@ -1,270 +1,270 @@ -/*
- * Copyright (c) 2005 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>
-#include<commctrl.h>
-#include<shlwapi.h>
-
-typedef struct tag_k5_ids_opts {
- khm_int32 renewable;
- khm_int32 forwardable;
- khm_int32 addressless;
-} k5_ids_opts;
-
-typedef struct tag_k5_ids_dlg_data {
- khui_config_init_data cfg;
-
- 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_opts opt;
- k5_ids_opts opt_saved;
-
-} k5_ids_dlg_data;
-
-static khm_boolean
-k5_ids_is_mod(k5_ids_dlg_data * d) {
- if (d->life != d->tc_life.current ||
- d->renew_life != d->tc_renew.current ||
- d->life_max != d->tc_life_max.current ||
- d->life_min != d->tc_life_min.current ||
- d->renew_max != d->tc_renew_max.current ||
- d->renew_min != d->tc_renew_min.current ||
- !!d->opt.renewable != !!d->opt_saved.renewable ||
- !!d->opt.forwardable != !!d->opt_saved.forwardable ||
- !!d->opt.addressless != !!d->opt_saved.addressless)
- return TRUE;
- return FALSE;
-}
-
-static void
-k5_ids_check_mod(k5_ids_dlg_data * d) {
- BOOL modified = k5_ids_is_mod(d);
-
- khui_cfg_set_flags_inst(&d->cfg,
- (modified)?KHUI_CNFLAG_MODIFIED:0,
- KHUI_CNFLAG_MODIFIED);
-}
-
-static void
-k5_ids_write_params(k5_ids_dlg_data * d) {
-
- khm_int32 rv;
-
-#ifdef DEBUG
- assert(csp_params);
-#endif
-
- if (!k5_ids_is_mod(d))
- return;
-
-#define WRITEPARAM(po,pn,vn) \
- if (po != pn) { \
- po = pn; \
- rv = khc_write_int32(csp_params, vn, (khm_int32) po); \
- assert(KHM_SUCCEEDED(rv)); \
- }
-
- WRITEPARAM(d->life,d->tc_life.current, L"DefaultLifetime");
- WRITEPARAM(d->renew_life,d->tc_renew.current, L"DefaultRenewLifetime");
- WRITEPARAM(d->life_max,d->tc_life_max.current, L"MaxLifetime");
- WRITEPARAM(d->life_min,d->tc_life_min.current, L"MinLifetime");
- WRITEPARAM(d->renew_max,d->tc_renew_max.current, L"MaxRenewLifetime");
- WRITEPARAM(d->renew_min,d->tc_renew_min.current, L"MinRenewLifetime");
- WRITEPARAM(d->opt_saved.renewable, d->opt.renewable, L"Renewable");
- WRITEPARAM(d->opt_saved.forwardable, d->opt.forwardable, L"Forwardable");
- WRITEPARAM(d->opt_saved.addressless, d->opt.addressless, L"Addressless");
-
-#undef WRITEPARAM
-
- khui_cfg_set_flags_inst(&d->cfg,
- KHUI_CNFLAG_APPLIED,
- KHUI_CNFLAG_APPLIED | KHUI_CNFLAG_MODIFIED);
-}
-
-static void
-k5_ids_read_params(k5_ids_dlg_data * d) {
- k5_params p;
-
- khm_krb5_get_identity_params(NULL, &p);
-
- d->life = p.lifetime;
- d->life_max = p.lifetime_max;
- d->life_min = p.lifetime_min;
-
- d->renew_life = p.renew_life;
- d->renew_max = p.renew_life_max;
- d->renew_min = p.renew_life_min;
-
- d->opt_saved.forwardable = p.forwardable;
- d->opt_saved.renewable = p.renewable;
- d->opt_saved.addressless = p.addressless;
-
- d->opt = d->opt_saved;
-
- 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 = PMALLOC(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)
-
- d->cfg = *((khui_config_init_data *) lParam);
-
- 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);
-
- CheckDlgButton(hwnd, IDC_CFG_RENEW, (d->opt.renewable ? BST_CHECKED: BST_UNCHECKED));
- CheckDlgButton(hwnd, IDC_CFG_FORWARD, (d->opt.forwardable ? BST_CHECKED: BST_UNCHECKED));
- CheckDlgButton(hwnd, IDC_CFG_ADDRESSLESS, (d->opt.addressless ? BST_CHECKED: BST_UNCHECKED));
- break;
-
- case WM_COMMAND:
- d = (k5_ids_dlg_data *) (LONG_PTR)
- GetWindowLongPtr(hwnd, DWLP_USER);
-
- if (HIWORD(wParam) == EN_CHANGE) {
- k5_ids_check_mod(d);
- } else if (HIWORD(wParam) == BN_CLICKED) {
- switch (LOWORD(wParam)) {
- case IDC_CFG_RENEW:
- d->opt.renewable = (IsDlgButtonChecked(hwnd, IDC_CFG_RENEW) == BST_CHECKED);
- break;
-
- case IDC_CFG_FORWARD:
- d->opt.forwardable = (IsDlgButtonChecked(hwnd, IDC_CFG_FORWARD) == BST_CHECKED);
- break;
-
- case IDC_CFG_ADDRESSLESS:
- d->opt.addressless = (IsDlgButtonChecked(hwnd, IDC_CFG_ADDRESSLESS) == BST_CHECKED);
- break;
- }
-
- k5_ids_check_mod(d);
- }
- break;
-
- case KHUI_WM_CFG_NOTIFY:
- d = (k5_ids_dlg_data *) (LONG_PTR)
- GetWindowLongPtr(hwnd, DWLP_USER);
- if (HIWORD(wParam) == WMCFG_APPLY) {
- k5_ids_write_params(d);
- }
- 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);
-
- PFREE(d);
- break;
- }
- return FALSE;
-}
-
-
+/* + * Copyright (c) 2005 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> +#include<commctrl.h> +#include<shlwapi.h> + +typedef struct tag_k5_ids_opts { + khm_int32 renewable; + khm_int32 forwardable; + khm_int32 addressless; +} k5_ids_opts; + +typedef struct tag_k5_ids_dlg_data { + khui_config_init_data cfg; + + 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_opts opt; + k5_ids_opts opt_saved; + +} k5_ids_dlg_data; + +static khm_boolean +k5_ids_is_mod(k5_ids_dlg_data * d) { + if (d->life != d->tc_life.current || + d->renew_life != d->tc_renew.current || + d->life_max != d->tc_life_max.current || + d->life_min != d->tc_life_min.current || + d->renew_max != d->tc_renew_max.current || + d->renew_min != d->tc_renew_min.current || + !!d->opt.renewable != !!d->opt_saved.renewable || + !!d->opt.forwardable != !!d->opt_saved.forwardable || + !!d->opt.addressless != !!d->opt_saved.addressless) + return TRUE; + return FALSE; +} + +static void +k5_ids_check_mod(k5_ids_dlg_data * d) { + BOOL modified = k5_ids_is_mod(d); + + khui_cfg_set_flags_inst(&d->cfg, + (modified)?KHUI_CNFLAG_MODIFIED:0, + KHUI_CNFLAG_MODIFIED); +} + +static void +k5_ids_write_params(k5_ids_dlg_data * d) { + + khm_int32 rv; + +#ifdef DEBUG + assert(csp_params); +#endif + + if (!k5_ids_is_mod(d)) + return; + +#define WRITEPARAM(po,pn,vn) \ + if (po != pn) { \ + po = pn; \ + rv = khc_write_int32(csp_params, vn, (khm_int32) po); \ + assert(KHM_SUCCEEDED(rv)); \ + } + + WRITEPARAM(d->life,d->tc_life.current, L"DefaultLifetime"); + WRITEPARAM(d->renew_life,d->tc_renew.current, L"DefaultRenewLifetime"); + WRITEPARAM(d->life_max,d->tc_life_max.current, L"MaxLifetime"); + WRITEPARAM(d->life_min,d->tc_life_min.current, L"MinLifetime"); + WRITEPARAM(d->renew_max,d->tc_renew_max.current, L"MaxRenewLifetime"); + WRITEPARAM(d->renew_min,d->tc_renew_min.current, L"MinRenewLifetime"); + WRITEPARAM(d->opt_saved.renewable, d->opt.renewable, L"Renewable"); + WRITEPARAM(d->opt_saved.forwardable, d->opt.forwardable, L"Forwardable"); + WRITEPARAM(d->opt_saved.addressless, d->opt.addressless, L"Addressless"); + +#undef WRITEPARAM + + khui_cfg_set_flags_inst(&d->cfg, + KHUI_CNFLAG_APPLIED, + KHUI_CNFLAG_APPLIED | KHUI_CNFLAG_MODIFIED); +} + +static void +k5_ids_read_params(k5_ids_dlg_data * d) { + k5_params p; + + khm_krb5_get_identity_params(NULL, &p); + + d->life = p.lifetime; + d->life_max = p.lifetime_max; + d->life_min = p.lifetime_min; + + d->renew_life = p.renew_life; + d->renew_max = p.renew_life_max; + d->renew_min = p.renew_life_min; + + d->opt_saved.forwardable = p.forwardable; + d->opt_saved.renewable = p.renewable; + d->opt_saved.addressless = p.addressless; + + d->opt = d->opt_saved; + + 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 = PMALLOC(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) + + d->cfg = *((khui_config_init_data *) lParam); + + 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); + + CheckDlgButton(hwnd, IDC_CFG_RENEW, (d->opt.renewable ? BST_CHECKED: BST_UNCHECKED)); + CheckDlgButton(hwnd, IDC_CFG_FORWARD, (d->opt.forwardable ? BST_CHECKED: BST_UNCHECKED)); + CheckDlgButton(hwnd, IDC_CFG_ADDRESSLESS, (d->opt.addressless ? BST_CHECKED: BST_UNCHECKED)); + break; + + case WM_COMMAND: + d = (k5_ids_dlg_data *) (LONG_PTR) + GetWindowLongPtr(hwnd, DWLP_USER); + + if (HIWORD(wParam) == EN_CHANGE) { + k5_ids_check_mod(d); + } else if (HIWORD(wParam) == BN_CLICKED) { + switch (LOWORD(wParam)) { + case IDC_CFG_RENEW: + d->opt.renewable = (IsDlgButtonChecked(hwnd, IDC_CFG_RENEW) == BST_CHECKED); + break; + + case IDC_CFG_FORWARD: + d->opt.forwardable = (IsDlgButtonChecked(hwnd, IDC_CFG_FORWARD) == BST_CHECKED); + break; + + case IDC_CFG_ADDRESSLESS: + d->opt.addressless = (IsDlgButtonChecked(hwnd, IDC_CFG_ADDRESSLESS) == BST_CHECKED); + break; + } + + k5_ids_check_mod(d); + } + break; + + case KHUI_WM_CFG_NOTIFY: + d = (k5_ids_dlg_data *) (LONG_PTR) + GetWindowLongPtr(hwnd, DWLP_USER); + if (HIWORD(wParam) == WMCFG_APPLY) { + k5_ids_write_params(d); + } + 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); + + PFREE(d); + break; + } + return FALSE; +} + + diff --git a/src/windows/identity/plugins/krb5/krb5funcs.c b/src/windows/identity/plugins/krb5/krb5funcs.c index e66e755a7..6f657e851 100644 --- a/src/windows/identity/plugins/krb5/krb5funcs.c +++ b/src/windows/identity/plugins/krb5/krb5funcs.c @@ -1,3487 +1,3487 @@ -/*
-* Copyright (c) 2005 Massachusetts Institute of Technology
-* Copyright (c) 2006,2007 Secure Endpoints Inc.
-*
-* 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 <string.h>
-#include <time.h>
-#include <stdlib.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 *) PMALLOC(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));
- PFREE(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
-
-/* we use these structures to keep track of identities that we find
- while going through the API, FILE and MSLSA caches and enumerating
- credentials. The only identities we want to keep track of are the
- ones that have an initial ticket. We collect information for each
- of the identities we find that we have initial tickets for and
- then set the properties for the identities at once. */
-
-typedef struct tag_ident_data {
- khm_handle ident; /* handle to the identity */
- khm_int32 count; /* number of initial tickets we have
- found for this identity. */
- wchar_t ccname[MAX_PATH];
- FILETIME ft_issue;
- FILETIME ft_expire;
- FILETIME ft_renewexpire;
- khm_int32 krb5_flags;
-} ident_data;
-
-typedef struct tag_identlist {
- ident_data * list;
- khm_size n_list;
- khm_size nc_list;
-} identlist;
-
-#define IDLIST_ALLOC_INCR 8
-
-static void
-tc_prep_idlist(identlist * idlist) {
- khm_int32 rv;
- khm_size cb_ids = 0;
- khm_size n_ids = 0;
- khm_size i;
- wchar_t * ids = NULL;
- wchar_t *thisid;
-
- idlist->list = NULL;
- idlist->n_list = 0;
- idlist->nc_list = 0;
-
- do {
-
- if (ids) {
- PFREE(ids);
- ids = NULL;
- }
-
- rv = kcdb_identity_enum(KCDB_IDENT_FLAG_ACTIVE,
- KCDB_IDENT_FLAG_ACTIVE,
- NULL,
- &cb_ids,
- &n_ids);
-
- if (rv != KHM_ERROR_TOO_LONG)
- break; /* something else is wrong */
-
- if (n_ids == 0 || cb_ids == 0)
- break; /* no identities to process */
-
-#ifdef DEBUG
- assert(cb_ids > 0);
-#endif
-
- ids = PMALLOC(cb_ids);
-#ifdef DEBUG
- assert(ids != NULL);
-#endif
- if (ids == NULL)
- break;
-
- rv = kcdb_identity_enum(KCDB_IDENT_FLAG_ACTIVE,
- KCDB_IDENT_FLAG_ACTIVE,
- ids,
- &cb_ids,
- &n_ids);
-
- if (KHM_SUCCEEDED(rv))
- break;
-
- } while (TRUE);
-
- if (ids == NULL)
- return;
-
- if (KHM_FAILED(rv) || n_ids == 0) {
- if (ids)
- PFREE(ids);
- return;
- }
-
- idlist->nc_list = UBOUNDSS(n_ids, IDLIST_ALLOC_INCR, IDLIST_ALLOC_INCR);
-
- idlist->list = PCALLOC(idlist->nc_list, sizeof(idlist->list[0]));
-
- for (i = 0, thisid = ids;
- thisid && thisid[0];
- thisid = multi_string_next(thisid)) {
-
- khm_handle ident;
-
- rv = kcdb_identity_create(thisid, 0, &ident);
-
- if (KHM_FAILED(rv))
- continue;
-
- idlist->list[i].ident = ident;
- idlist->list[i].count = 0;
-
- i++;
- }
-
- idlist->n_list = i;
-
- PFREE(ids);
-}
-
-static ident_data *
-tc_add_ident_to_list(identlist * idlist, khm_handle ident) {
- khm_size i;
- ident_data * d;
-
- for (i=0; i < idlist->n_list; i++) {
- if (kcdb_identity_is_equal(ident, idlist->list[i].ident))
- break;
- }
-
- if (i < idlist->n_list) {
- /* we already have this identity on our list. Increment the
- count */
- idlist->list[i].count++;
- return &idlist->list[i];
- }
-
- /* it wasn't in our list. Add it */
-
- if (idlist->n_list + 1 > idlist->nc_list) {
- idlist->nc_list = UBOUNDSS(idlist->n_list + 1,
- IDLIST_ALLOC_INCR,
- IDLIST_ALLOC_INCR);
-#ifdef DEBUG
- assert(idlist->n_list + 1 <= idlist->nc_list);
-#endif
- idlist->list = PREALLOC(idlist->list,
- sizeof(idlist->list[0]) * idlist->nc_list);
-#ifdef DEBUG
- assert(idlist->list);
-#endif
- ZeroMemory(&idlist->list[idlist->n_list],
- sizeof(idlist->list[0]) *
- (idlist->nc_list - idlist->n_list));
- }
-
- d = &idlist->list[idlist->n_list];
-
- ZeroMemory(d, sizeof(*d));
-
- d->ident = ident;
- d->count = 1;
-
- idlist->n_list++;
-
- kcdb_identity_hold(ident);
-
- return d;
-}
-
-static void
-tc_set_ident_data(identlist * idlist) {
- khm_size i;
- wchar_t k5idtype[KCDB_MAXCCH_NAME];
-
- k5idtype[0] = L'\0';
- LoadString(hResModule, IDS_KRB5_NC_NAME,
- k5idtype, ARRAYLENGTH(k5idtype));
-
- for (i=0; i < idlist->n_list; i++) {
-#ifdef DEBUG
- assert(idlist->list[i].ident);
-#endif
-
- if (idlist->list[i].count > 0) {
- khm_int32 t;
-
- t = credtype_id_krb5;
- kcdb_identity_set_attr(idlist->list[i].ident,
- KCDB_ATTR_TYPE,
- &t,
- sizeof(t));
-
- /* We need to manually add the type name if we want the
- name to show up in the property list for the identity.
- The type name is only automatically calculated for
- credentials. */
- kcdb_identity_set_attr(idlist->list[i].ident,
- KCDB_ATTR_TYPE_NAME,
- k5idtype,
- KCDB_CBSIZE_AUTO);
-
- kcdb_identity_set_attr(idlist->list[i].ident,
- attr_id_krb5_ccname,
- idlist->list[i].ccname,
- KCDB_CBSIZE_AUTO);
-
- kcdb_identity_set_attr(idlist->list[i].ident,
- KCDB_ATTR_EXPIRE,
- &idlist->list[i].ft_expire,
- sizeof(idlist->list[i].ft_expire));
-
- kcdb_identity_set_attr(idlist->list[i].ident,
- KCDB_ATTR_ISSUE,
- &idlist->list[i].ft_issue,
- sizeof(idlist->list[i].ft_issue));
-
- kcdb_identity_set_attr(idlist->list[i].ident,
- attr_id_krb5_flags,
- &idlist->list[i].krb5_flags,
- sizeof(idlist->list[i].krb5_flags));
-
- if (idlist->list[i].ft_renewexpire.dwLowDateTime == 0 &&
- idlist->list[i].ft_renewexpire.dwHighDateTime == 0) {
- kcdb_identity_set_attr(idlist->list[i].ident,
- KCDB_ATTR_RENEW_EXPIRE,
- NULL, 0);
- } else {
- kcdb_identity_set_attr(idlist->list[i].ident,
- KCDB_ATTR_RENEW_EXPIRE,
- &idlist->list[i].ft_renewexpire,
- sizeof(idlist->list[i].ft_renewexpire));
- }
-
- } else {
- /* We didn't see any TGTs for this identity. We have to
- remove all the Krb5 supplied properties. */
-
- khm_int32 t;
- khm_size cb;
-
- cb = sizeof(t);
- if (KHM_SUCCEEDED(kcdb_identity_get_attr(idlist->list[i].ident,
- KCDB_ATTR_TYPE, NULL,
- &t,
- &cb)) &&
- t == credtype_id_krb5) {
-
- /* disown this and remove all our properties. the
- system will GC this identity if nobody claims it.*/
-
- kcdb_identity_set_attr(idlist->list[i].ident,
- KCDB_ATTR_TYPE, NULL, 0);
- kcdb_identity_set_attr(idlist->list[i].ident,
- KCDB_ATTR_TYPE_NAME, NULL, 0);
- kcdb_identity_set_attr(idlist->list[i].ident,
- attr_id_krb5_ccname, NULL, 0);
- kcdb_identity_set_attr(idlist->list[i].ident,
- KCDB_ATTR_EXPIRE, NULL, 0);
- kcdb_identity_set_attr(idlist->list[i].ident,
- KCDB_ATTR_ISSUE, NULL, 0);
- kcdb_identity_set_attr(idlist->list[i].ident,
- attr_id_krb5_flags, NULL, 0);
- kcdb_identity_set_attr(idlist->list[i].ident,
- KCDB_ATTR_RENEW_EXPIRE, NULL, 0);
- } else {
- /* otherwise, this identity doesn't belong to us. We
- should leave it as is. */
- }
- }
- }
-}
-
-static void
-tc_free_idlist(identlist * idlist) {
- khm_size i;
-
- for (i=0; i < idlist->n_list; i++) {
- if (idlist->list[i].ident != NULL) {
- kcdb_identity_release(idlist->list[i].ident);
- idlist->list[i].ident = NULL;
- }
- }
-
- if (idlist->list)
- PFREE(idlist->list);
- idlist->list = NULL;
- idlist->n_list = 0;
- idlist->nc_list = 0;
-}
-
-#ifndef ENCTYPE_LOCAL_RC4_MD4
-#define ENCTYPE_LOCAL_RC4_MD4 0xFFFFFF80
-#endif
-
-#define MAX_ADDRS 256
-
-static long get_tickets_from_cache(krb5_context ctx,
- krb5_ccache cache,
- identlist * idlist)
-{
- krb5_error_code code;
- krb5_principal KRBv5Principal;
- krb5_flags flags = 0;
- krb5_cc_cursor KRBv5Cursor;
- krb5_creds KRBv5Credentials;
- krb5_ticket *tkt=NULL;
- char *ClientName = NULL;
- char *PrincipalName = NULL;
- wchar_t wbuf[256]; /* temporary conversion buffer */
- wchar_t wcc_name[KRB5_MAXCCH_CCNAME]; /* credential cache name */
- char *sServerName = NULL;
- khm_handle ident = NULL;
- khm_handle cred = NULL;
- time_t tt;
- FILETIME ft, eft;
- khm_int32 ti;
-
-#ifdef KRB5_TC_NOTICKET
- flags = KRB5_TC_NOTICKET;
-#else
- flags = 0;
-#endif
-
- {
- const char * cc_name;
- const char * cc_type;
-
- cc_name = (*pkrb5_cc_get_name)(ctx, cache);
- if(cc_name) {
- cc_type = (*pkrb5_cc_get_type)(ctx, cache);
- if (cc_type) {
- StringCbPrintf(wcc_name, sizeof(wcc_name), L"%S:%S", cc_type, cc_name);
- } else {
- AnsiStrToUnicode(wcc_name, sizeof(wcc_name), cc_name);
- khm_krb5_canon_cc_name(wcc_name, sizeof(wcc_name));
- }
- } else {
- cc_type = (*pkrb5_cc_get_type)(ctx, cache);
- if (cc_type) {
- StringCbPrintf(wcc_name, sizeof(wcc_name), L"%S:", cc_type);
- } else {
-#ifdef DEBUG
- assert(FALSE);
-#endif
- StringCbCopy(wcc_name, sizeof(wcc_name), L"");
- }
- }
- }
-
- _reportf(L"Getting tickets from cache [%s]", wcc_name);
-
- 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;
- }
-
- _reportf(L"Found principal [%s]", wbuf);
-
- (*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;
- khm_int32 cred_flags = 0;
-
- 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, &ft);
- kcdb_cred_set_attr(cred, KCDB_ATTR_ISSUE, &ft, sizeof(ft));
-
- tt = KRBv5Credentials.times.endtime;
- TimetToFileTime(tt, &eft);
- kcdb_cred_set_attr(cred, KCDB_ATTR_EXPIRE, &eft, sizeof(eft));
-
- {
- FILETIME ftl;
-
- ftl = FtSub(&eft, &ft);
- kcdb_cred_set_attr(cred, KCDB_ATTR_LIFETIME, &ftl, sizeof(ftl));
- }
-
- if (KRBv5Credentials.times.renew_till > 0) {
- FILETIME ftl;
-
- tt = KRBv5Credentials.times.renew_till;
- TimetToFileTime(tt, &eft);
- kcdb_cred_set_attr(cred, KCDB_ATTR_RENEW_EXPIRE, &eft,
- sizeof(eft));
-
-
- ftl = FtSub(&eft, &ft);
- kcdb_cred_set_attr(cred, KCDB_ATTR_RENEW_LIFETIME, &ftl,
- sizeof(ftl));
- }
-
- ti = KRBv5Credentials.ticket_flags;
- kcdb_cred_set_attr(cred, attr_id_krb5_flags, &ti, sizeof(ti));
-
- /* special flags understood by NetIDMgr */
- {
- khm_int32 nflags = 0;
-
- if (ti & TKT_FLG_RENEWABLE)
- nflags |= KCDB_CRED_FLAG_RENEWABLE;
- if (ti & TKT_FLG_INITIAL)
- nflags |= KCDB_CRED_FLAG_INITIAL;
- else {
- krb5_data * c0, *c1, *r;
-
- /* these are macros that do not allocate any memory */
- c0 = krb5_princ_component(ctx,KRBv5Credentials.server,0);
- c1 = krb5_princ_component(ctx,KRBv5Credentials.server,1);
- r = krb5_princ_realm(ctx,KRBv5Credentials.server);
-
- if ( c0 && c1 && r && c1->length == r->length &&
- !strncmp(c1->data,r->data,r->length) &&
- !strncmp("krbtgt",c0->data,c0->length) )
- nflags |= KCDB_CRED_FLAG_INITIAL;
- }
-
- kcdb_cred_set_flags(cred, nflags, KCDB_CRED_FLAGMASK_EXT);
-
- cred_flags = nflags;
- }
-
- if ( !pkrb5_decode_ticket(&KRBv5Credentials.ticket, &tkt)) {
- ti = tkt->enc_part.enctype;
- kcdb_cred_set_attr(cred, attr_id_tkt_enctype, &ti, sizeof(ti));
- ti = tkt->enc_part.kvno;
- kcdb_cred_set_attr(cred, attr_id_kvno, &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);
-
- if ( KRBv5Credentials.addresses && KRBv5Credentials.addresses[0] ) {
- khm_int32 buffer[1024];
- void * bufp;
- khm_size cb;
- khm_int32 rv;
-
- bufp = (void *) buffer;
- cb = sizeof(buffer);
-
- rv = serialize_krb5_addresses(KRBv5Credentials.addresses,
- bufp,
- &cb);
- if (rv == KHM_ERROR_TOO_LONG) {
- bufp = PMALLOC(cb);
- rv = serialize_krb5_addresses(KRBv5Credentials.addresses,
- bufp,
- &cb);
- }
-
- if (KHM_SUCCEEDED(rv)) {
- kcdb_cred_set_attr(cred, attr_id_addr_list,
- bufp, cb);
- }
-
- if (bufp != (void *) buffer)
- PFREE(bufp);
- }
-
- if(cred_flags & KCDB_CRED_FLAG_INITIAL) {
- FILETIME ft_issue_new;
- FILETIME ft_expire_old;
- FILETIME ft_expire_new;
- ident_data * d;
-
- /* an initial ticket! Add it to the list of identities we
- have seen so far with initial tickets. */
- d = tc_add_ident_to_list(idlist, ident);
-#ifdef DEBUG
- assert(d);
- assert(d->count > 0);
-#endif
-
- tt = KRBv5Credentials.times.endtime;
- TimetToFileTime(tt, &ft_expire_new);
-
- tt = KRBv5Credentials.times.starttime;
- TimetToFileTime(tt, &ft_issue_new);
-
- /* so now, we have to set the properties of the identity
- based on the properties of this credential under the
- following circumstances:
-
- - If this is the first time we are hitting this
- identity.
-
- - If this is not the MSLSA: cache and the expiry time
- for this credential is longer than the time already
- found for this identity.
- */
-
- ft_expire_old = d->ft_expire;
-
- if(d->count == 1
- || (CompareFileTime(&ft_expire_new, &ft_expire_old) > 0 &&
- wcscmp(wcc_name, L"MSLSA:") != 0)) {
-
- _reportf(L"Setting properties for identity (count=%d)", d->count);
-
- StringCbCopy(d->ccname, sizeof(d->ccname),
- wcc_name);
- d->ft_expire = ft_expire_new;
- d->ft_issue = ft_issue_new;
-
- if (KRBv5Credentials.times.renew_till > 0) {
- tt = KRBv5Credentials.times.renew_till;
- TimetToFileTime(tt, &ft);
- d->ft_renewexpire = ft;
- } else {
- ZeroMemory(&d->ft_renewexpire, sizeof(d->ft_renewexpire));
- }
-
- d->krb5_flags = KRBv5Credentials.ticket_flags;
- }
- }
-
- 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:
-
- return code;
-}
-
-long
-khm_krb5_list_tickets(krb5_context *krbv5Context)
-{
- krb5_context ctx = NULL;
- krb5_ccache cache = NULL;
- krb5_error_code code = 0;
- apiCB * cc_ctx = NULL;
- struct _infoNC ** pNCi = NULL;
- int i;
- khm_int32 t;
- wchar_t * ms = NULL;
- khm_size cb;
- identlist idl;
-
- kcdb_credset_flush(krb5_credset);
- tc_prep_idlist(&idl);
-
- if((*krbv5Context == 0) && (code = (*pkrb5_init_context)(krbv5Context))) {
- goto _exit;
- }
-
- ctx = (*krbv5Context);
-
- if (!pcc_initialize ||
- !pcc_get_NC_info ||
- !pcc_free_NC_info ||
- !pcc_shutdown)
- goto _skip_cc_iter;
-
- 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;
-
- for(i=0; pNCi[i]; i++) {
- char ccname[KRB5_MAXCCH_CCNAME];
-
- if (pNCi[i]->vers != CC_CRED_V5)
- continue;
-
- if (FAILED(StringCchPrintfA(ccname, sizeof(ccname), "API:%s",
- pNCi[i]->name)))
- continue;
-
- code = (*pkrb5_cc_resolve)(ctx, ccname, &cache);
-
- if (code)
- continue;
-
- code = get_tickets_from_cache(ctx, cache, &idl);
-
- if(ctx != NULL && cache != NULL)
- (*pkrb5_cc_close)(ctx, cache);
-
- cache = 0;
- }
-
- _skip_cc_iter:
-
- if (khc_read_multi_string(csp_params, L"FileCCList", NULL, &cb)
- == KHM_ERROR_TOO_LONG &&
- cb > sizeof(wchar_t) * 2) {
- wchar_t * t;
- char ccname[MAX_PATH + 6];
-
- ms = PMALLOC(cb);
-#ifdef DEBUG
- assert(ms);
-#endif
- khc_read_multi_string(csp_params, L"FileCCList", ms, &cb);
-
- for(t = ms; t && *t; t = multi_string_next(t)) {
- StringCchPrintfA(ccname, ARRAYLENGTH(ccname),
- "FILE:%S", t);
-
- code = (*pkrb5_cc_resolve)(ctx, ccname, &cache);
-
- if (code)
- continue;
-
- code = get_tickets_from_cache(ctx, cache, &idl);
-
- if (ctx != NULL && cache != NULL)
- (*pkrb5_cc_close)(ctx, cache);
- cache = 0;
- }
-
- PFREE(ms);
- }
-
- if (KHM_SUCCEEDED(khc_read_int32(csp_params, L"MsLsaList", &t)) && t) {
- code = (*pkrb5_cc_resolve)(ctx, "MSLSA:", &cache);
-
- if (code == 0 && cache) {
- code = get_tickets_from_cache(ctx, cache, &idl);
- }
-
- 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);
- tc_set_ident_data(&idl);
- tc_free_idlist(&idl);
-
- return(code);
-}
-
-int
-khm_krb5_renew_cred(khm_handle cred)
-{
- khm_handle identity = NULL;
- krb5_error_code code = 0;
- krb5_context ctx = NULL;
- krb5_ccache cc = NULL;
- krb5_principal me = NULL, server = NULL;
- krb5_creds in_creds, cc_creds;
- krb5_creds * out_creds = NULL;
-
- wchar_t wname[512];
- khm_size cbname;
- char name[512];
- khm_boolean brenewIdentity = FALSE;
- khm_boolean istgt = FALSE;
-
- khm_int32 flags;
-
- cbname = sizeof(wname);
- kcdb_cred_get_name(cred, wname, &cbname);
- _reportf(L"Krb5 renew cred for %s", wname);
-
- kcdb_cred_get_flags(cred, &flags);
-
- if (!(flags & KCDB_CRED_FLAG_INITIAL)) {
- _reportf(L"Krb5 skipping renewal because this is not an initial credential");
- return 0;
- }
-
- memset(&in_creds, 0, sizeof(in_creds));
- memset(&cc_creds, 0, sizeof(cc_creds));
-
- if (cred == NULL) {
-#ifdef DEBUG
- assert(FALSE);
-#endif
- goto cleanup;
- }
-
- if (KHM_FAILED(kcdb_cred_get_identity(cred, &identity))) {
-#ifdef DEBUG
- assert(FALSE);
-#endif
- goto cleanup;
- }
-
- code = khm_krb5_initialize(identity, &ctx, &cc);
- if (code)
- goto cleanup;
-
- code = pkrb5_cc_get_principal(ctx, cc, &me);
- if (code)
- goto cleanup;
-
- cbname = sizeof(wname);
- if (KHM_FAILED(kcdb_cred_get_name(cred, wname, &cbname)))
- goto cleanup;
-
- UnicodeStrToAnsi(name, sizeof(name), wname);
-
- code = pkrb5_parse_name(ctx, name, &server);
- if (code)
- goto cleanup;
-
- in_creds.client = me;
- in_creds.server = server;
-
-#ifdef KRB5_TC_NOTICKET
- pkrb5_cc_set_flags(ctx, cc, 0);
-#endif
-
- if (strlen("krbtgt") != krb5_princ_name(ctx, server)->length ||
- strncmp("krbtgt", krb5_princ_name(ctx, server)->data, krb5_princ_name(ctx, server)->length))
- {
- code = pkrb5_get_renewed_creds(ctx, &cc_creds, me, cc, name);
- if (code) {
- code = pkrb5_cc_retrieve_cred(ctx, cc, 0, &in_creds, &cc_creds);
- if (code == 0) {
- code = pkrb5_cc_remove_cred(ctx, cc, 0, &cc_creds);
- if (code) {
- brenewIdentity = TRUE;
- goto cleanup;
- }
- }
- }
-
- code = pkrb5_get_credentials(ctx, 0, cc, &in_creds, &out_creds);
- } else {
- istgt = TRUE;
- code = pkrb5_get_renewed_creds(ctx, &cc_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;
- }
-
- if (istgt) {
- code = pkrb5_cc_initialize(ctx, cc, me);
- if (code) goto cleanup;
-
- }
-
- code = pkrb5_cc_store_cred(ctx, cc, istgt ? &cc_creds : out_creds);
- if (code) goto cleanup;
-
-
- cleanup:
-
- if (in_creds.client == me)
- in_creds.client = NULL;
- if (in_creds.server == server)
- in_creds.server = NULL;
-
- if (me)
- pkrb5_free_principal(ctx, me);
-
- if (server)
- pkrb5_free_principal(ctx, server);
-
- pkrb5_free_cred_contents(ctx, &in_creds);
- pkrb5_free_cred_contents(ctx, &cc_creds);
-
- if (out_creds)
- pkrb5_free_creds(ctx, out_creds);
-
- if (cc && ctx)
- pkrb5_cc_close(ctx, cc);
-
- if (ctx)
- pkrb5_free_context(ctx);
-
- if (identity) {
- if (brenewIdentity)
- code = khm_krb5_renew_ident(identity);
- kcdb_identity_release(identity);
- }
-
- return code;
-}
-
-int
-khm_krb5_renew_ident(khm_handle identity)
-{
- krb5_error_code code = 0;
- krb5_context ctx = NULL;
- krb5_ccache cc = NULL;
- krb5_principal me = NULL;
- krb5_principal server = NULL;
- krb5_creds my_creds;
- krb5_data *realm = NULL;
- wchar_t idname[KCDB_IDENT_MAXCCH_NAME];
- khm_size cb;
- khm_int32 k5_flags;
-
- memset(&my_creds, 0, sizeof(krb5_creds));
-
- if ( !pkrb5_init_context )
- goto cleanup;
-
- cb = sizeof(idname);
- kcdb_identity_get_name(identity, idname, &cb);
-
- if (khm_krb5_get_identity_flags(identity) & K5IDFLAG_IMPORTED) {
-#ifndef NO_REIMPORT_MSLSA_CREDS
- /* we are trying to renew the identity that was imported from
- MSLSA: */
- BOOL imported;
- BOOL retry_import = FALSE;
- char cidname[KCDB_IDENT_MAXCCH_NAME];
- khm_handle imported_id = NULL;
- khm_size cb;
- FILETIME ft_expire;
- FILETIME ft_now;
- FILETIME ft_threshold;
- krb5_principal princ = NULL;
-
- UnicodeStrToAnsi(cidname, sizeof(cidname), idname);
-
- imported = khm_krb5_ms2mit(cidname, FALSE, TRUE, &imported_id);
-
- if (imported == 0)
- goto import_failed;
-
- /* if the imported identity has already expired or will soon,
- we clear the cache and try again. */
- khm_krb5_list_tickets(&ctx);
-
- cb = sizeof(ft_expire);
- if (KHM_FAILED(kcdb_identity_get_attr(imported_id, KCDB_ATTR_EXPIRE,
- NULL, &ft_expire, &cb)))
- goto import_failed;
-
- GetSystemTimeAsFileTime(&ft_now);
- TimetToFileTimeInterval(5 * 60, &ft_threshold);
-
- ft_now = FtAdd(&ft_now, &ft_threshold);
-
- if (CompareFileTime(&ft_expire, &ft_now) < 0) {
- /* the ticket lifetime is not long enough */
-
- code = 0;
-
- if (ctx == NULL)
- code = pkrb5_init_context(&ctx);
- if (code)
- goto import_failed;
-
- code = pkrb5_cc_resolve(ctx, "MSLSA:", &cc);
- if (code)
- goto import_failed;
-
- code = pkrb5_cc_get_principal(ctx, cc, &princ);
- if (code)
- goto import_failed;
-
- pkrb5_cc_initialize(ctx, cc, princ);
-
- retry_import = TRUE;
- }
-
- import_failed:
-
- if (imported_id) {
- kcdb_identity_release(imported_id);
- imported_id = NULL;
- }
-
- if (ctx) {
- if (cc) {
- pkrb5_cc_close(ctx, cc);
- cc = NULL;
- }
-
- if (princ) {
- pkrb5_free_principal(ctx, princ);
- princ = NULL;
- }
-
- /* leave ctx so we can use it later */
- }
-
- if (retry_import)
- imported = khm_krb5_ms2mit(cidname, FALSE, TRUE, NULL);
-
- if (imported)
- goto cleanup;
-
- /* if the import failed, then we try to renew the identity via
- the usual procedure. */
-
-#else
- /* if we are suppressing further imports from MSLSA, we just
- skip renewing this identity. */
- goto cleanup;
-#endif
- }
-
- cb = sizeof(k5_flags);
- if (KHM_SUCCEEDED(kcdb_identity_get_attr(identity,
- attr_id_krb5_flags,
- NULL,
- &k5_flags,
- &cb)) &&
- !(k5_flags & TKT_FLG_RENEWABLE)) {
-
- code = KRB5KDC_ERR_BADOPTION;
- goto cleanup;
- }
-
- {
- FILETIME ft_now;
- FILETIME ft_exp;
-
- cb = sizeof(ft_exp);
- GetSystemTimeAsFileTime(&ft_now);
- if (KHM_SUCCEEDED(kcdb_identity_get_attr(identity,
- KCDB_ATTR_EXPIRE,
- NULL,
- &ft_exp,
- &cb)) &&
- CompareFileTime(&ft_exp, &ft_now) < 0) {
-
- code = KRB5KRB_AP_ERR_TKT_EXPIRED;
- goto cleanup;
-
- }
- }
-
- 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 = NULL;
- if (my_creds.server == server)
- my_creds.server = NULL;
-
- if (ctx) {
- 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);
- 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 = NULL;
- krb5_ccache cc = NULL;
- krb5_principal me = NULL;
- char* name = NULL;
- 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;
-
- _reportf(L"In khm_krb5_kinit");
-
- pkrb5_get_init_creds_opt_init(&options);
- pkrb5_get_init_creds_opt_set_change_password_prompt(&options, 0);
-
- memset(&my_creds, 0, sizeof(my_creds));
-
- if (alt_ctx) {
- ctx = alt_ctx;
- } else {
- code = pkrb5_init_context(&ctx);
- if (code)
- goto cleanup;
- }
-
- if (ccache) {
- _reportf(L"Using supplied ccache name %S", ccache);
- code = pkrb5_cc_resolve(ctx, ccache, &cc);
- } else {
- khm_handle identity = NULL;
- khm_handle csp_ident = NULL;
- khm_handle csp_k5 = NULL;
- wchar_t idname[KCDB_IDENT_MAXCCH_NAME];
- wchar_t wccname[MAX_PATH];
- char ccname[MAX_PATH];
- char * pccname = principal_name;
- khm_size cb;
-
- idname[0] = L'\0';
- AnsiStrToUnicode(idname, sizeof(idname), principal_name);
-
- cb = sizeof(wccname);
-
- if (KHM_SUCCEEDED(kcdb_identity_create(idname, 0, &identity)) &&
-
- KHM_SUCCEEDED(kcdb_identity_get_config(identity, 0, &csp_ident)) &&
-
- KHM_SUCCEEDED(khc_open_space(csp_ident, CSNAME_KRB5CRED, 0,
- &csp_k5)) &&
-
- KHM_SUCCEEDED(khc_read_string(csp_k5, L"DefaultCCName",
- wccname, &cb)) &&
-
- cb > sizeof(wchar_t)) {
-
- _reportf(L"Using DefaultCCName [%s] from identity", wccname);
-
- UnicodeStrToAnsi(ccname, sizeof(ccname), wccname);
- pccname = ccname;
- }
-
- if (csp_k5)
- khc_close_space(csp_k5);
- if (csp_ident)
- khc_close_space(csp_ident);
- if (identity)
- kcdb_identity_release(identity);
-
- code = pkrb5_cc_resolve(ctx, pccname, &cc);
- }
-
- _reportf(L"krb5_cc_resolve returns code %d", code);
-
- 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 {
- krb5_address ** local_addrs=NULL;
- DWORD netIPAddr;
-
- pkrb5_os_localaddr(ctx, &local_addrs);
- i = 0;
- while ( local_addrs[i++] );
- addr_count = i + 1;
-
- addrs = (krb5_address **) PMALLOC((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 *)PMALLOC(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 *)PMALLOC(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);
-
- if (publicIP) {
- // we are going to add the public IP address specified by the user
- // to the list provided by the operating system
- addrs[i] = (krb5_address *)PMALLOC(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 *)PMALLOC(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);
- _reportf(L"krb5_get_init_creds_password returns code %d", code);
-
- if (code) goto cleanup;
-
- code = pkrb5_cc_initialize(ctx, cc, me);
- _reportf(L"krb5_cc_initialize returns code %d", code);
- if (code) goto cleanup;
-
- code = pkrb5_cc_store_cred(ctx, cc, &my_creds);
- _reportf(L"krb5_cc_store_cred returns code %d", code);
- if (code) goto cleanup;
-
-cleanup:
- if ( addrs ) {
- for ( i=0;i<addr_count;i++ ) {
- if ( addrs[i] ) {
- if ( addrs[i]->contents )
- PFREE(addrs[i]->contents);
- PFREE(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) {
- /* if the colon is just 1 character away from the beginning,
- it's a FILE: cc */
- if (colon - wcc_name == 1) {
- if (cb_len + 5 * sizeof(wchar_t) > cb_cc_name)
- return KHM_ERROR_TOO_LONG;
-
- memmove(&wcc_name[5], &wcc_name[0], cb_len);
- memmove(&wcc_name[0], L"FILE:", sizeof(wchar_t) * 5);
- }
-
- 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 = NULL;
- 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) {
- _reportf(L"No tickets to delete");
-
- 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;
-
- _reportf(L"Destroying ccache [%s]", ccname);
-
- 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) {
- _reportf(L"krb5_cc_destroy returns code %d", code);
- }
-
- _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;
-
- _reportf(L"Looking at ccache [%s]", ccname);
-
- 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;
-
- _reportf(L"Attempting to delete ticket %s", srvname);
-
- 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);
-
- if (ctx != NULL)
- pkrb5_free_context(ctx);
-
- 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(char * match_princ, BOOL match_realm, BOOL save_creds,
- khm_handle * ret_ident)
-{
-#ifdef NO_KRB5
- return(FALSE);
-#else /* NO_KRB5 */
- krb5_context kcontext = 0;
- krb5_error_code code = 0;
- krb5_ccache ccache=0;
- krb5_ccache mslsa_ccache=0;
- krb5_creds creds;
- krb5_cc_cursor cursor=0;
- krb5_principal princ = 0;
- khm_handle ident = NULL;
- wchar_t wname[KCDB_IDENT_MAXCCH_NAME];
- char cname[KCDB_IDENT_MAXCCH_NAME];
- char *cache_name = NULL;
- char *princ_name = NULL;
- BOOL rc = FALSE;
-
- kherr_reportf(L"Begin : khm_krb5_ms2mit. save_cred=%d\n", (int) save_creds);
-
- if ( !pkrb5_init_context )
- goto cleanup;
-
- if (code = pkrb5_init_context(&kcontext))
- goto cleanup;
-
- kherr_reportf(L"Resolving MSLSA\n");
-
- if (code = pkrb5_cc_resolve(kcontext, "MSLSA:", &mslsa_ccache))
- goto cleanup;
-
- if ( save_creds ) {
- kherr_reportf(L"Getting principal\n");
- if (code = pkrb5_cc_get_principal(kcontext, mslsa_ccache, &princ))
- goto cleanup;
-
- kherr_reportf(L"Unparsing name\n");
- if (code = pkrb5_unparse_name(kcontext, princ, &princ_name))
- goto cleanup;
-
- AnsiStrToUnicode(wname, sizeof(wname), princ_name);
-
- kherr_reportf(L"Unparsed name [%s]", wname);
-
- /* see if we have to match a specific principal */
- if (match_princ != NULL) {
- if (strcmp(princ_name, match_princ)) {
- kherr_reportf(L"Principal mismatch. Wanted [%S], found [%S]",
- match_princ, princ_name);
- goto cleanup;
- }
- } else if (match_realm) {
- wchar_t * wdefrealm;
- char defrealm[256];
- krb5_data * princ_realm;
-
- wdefrealm = khm_krb5_get_default_realm();
- if (wdefrealm == NULL) {
- kherr_reportf(L"Can't determine default realm");
- goto cleanup;
- }
-
- princ_realm = krb5_princ_realm(kcontext, princ);
- UnicodeStrToAnsi(defrealm, sizeof(defrealm), wdefrealm);
-
- if (strncmp(defrealm, princ_realm->data, princ_realm->length)) {
- kherr_reportf(L"Realm mismatch. Wanted [%S], found [%*S]",
- defrealm, princ_realm->length, princ_realm->data);
- PFREE(wdefrealm);
- goto cleanup;
- }
-
- PFREE(wdefrealm);
- }
-
- if (KHM_SUCCEEDED(kcdb_identity_create(wname,
- KCDB_IDENT_FLAG_CREATE,
- &ident))) {
- khm_handle idconfig = NULL;
- khm_handle k5config = NULL;
- khm_size cb;
-
- wname[0] = L'\0';
-
- kcdb_identity_get_config(ident, KHM_FLAG_CREATE, &idconfig);
- if (idconfig == NULL)
- goto _done_checking_config;
-
- khc_open_space(idconfig, CSNAME_KRB5CRED, KHM_FLAG_CREATE, &k5config);
- if (k5config == NULL)
- goto _done_checking_config;
-
- cb = sizeof(wname);
- khc_read_string(k5config,
- L"DefaultCCName",
- wname, &cb);
-
- _done_checking_config:
-
- if (idconfig)
- khc_close_space(idconfig);
- if (k5config)
- khc_close_space(k5config);
-
- if (wname[0]) {
- UnicodeStrToAnsi(cname, sizeof(cname), wname);
- } else {
- StringCbPrintfA(cname, sizeof(cname), "API:%s", princ_name);
- }
-
- cache_name = cname;
-
- } else {
- /* the identity could not be created. we just use the
- name of the principal as the ccache name. */
- StringCbPrintfA(cname, sizeof(cname), "API:%s", princ_name);
- cache_name = cname;
- }
-
- kherr_reportf(L"Resolving target cache [%S]\n", cache_name);
-
- if (code = pkrb5_cc_resolve(kcontext, cache_name, &ccache)) {
- kherr_reportf(L"Cannot resolve cache [%S] with code=%d. Trying default.\n", cache_name, code);
-
- if (code = pkrb5_cc_default(kcontext, &ccache)) {
- kherr_reportf(L"Failed to resolve default ccache. Code=%d", code);
- goto cleanup;
- }
- }
-
- kherr_reportf(L"Initializing ccache\n");
- if (code = pkrb5_cc_initialize(kcontext, ccache, princ))
- goto cleanup;
-
- kherr_reportf(L"Copying credentials\n");
- if (code = pkrb5_cc_copy_creds(kcontext, mslsa_ccache, ccache))
- goto cleanup;
-
- /* and mark the identity as having been imported */
- if (ident) {
- khm_krb5_set_identity_flags(ident, K5IDFLAG_IMPORTED, K5IDFLAG_IMPORTED);
-
- if (ret_ident) {
- *ret_ident = ident;
- kcdb_identity_hold(*ret_ident);
- }
- }
-
- 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:
- kherr_reportf(L" Received code=%d", code);
-
- 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);
- if (ident)
- kcdb_identity_release(ident);
-
- return(rc);
-#endif /* NO_KRB5 */
-}
-
-#define KRB_FILE "KRB.CON"
-#define KRBREALM_FILE "KRBREALM.CON"
-#define KRB5_FILE "KRB5.INI"
-#define KRB5_TMP_FILE "KRB5.INI.TMP"
-
-BOOL
-khm_krb5_get_temp_profile_file(LPSTR confname, UINT szConfname)
-{
- GetTempPathA(szConfname, confname);
- confname[szConfname-1] = '\0';
- StringCchCatA(confname, szConfname, KRB5_TMP_FILE);
- confname[szConfname-1] = '\0';
- return FALSE;
-}
-
-#ifdef NOT_QUITE_IMPLEMENTED_YET
-BOOL
-khm_krb5_set_profile_file(krb5_context ctx, LPSTR confname)
-{
- char *conffiles[2];
-
- if (confname == NULL ||
- pkrb5_set_config_files == NULL ||
- ctx == NULL)
- return FALSE;
-
- conffiles[0] = confname;
- conffiles[1] = NULL;
-
- if (pkrb5_set_config_files(ctx, conffiles))
- return FALSE;
- else
- return TRUE;
-}
-#endif
-
-BOOL
-khm_krb5_get_profile_file(LPSTR confname, UINT szConfname)
-{
- char **configFile = NULL;
- if (pkrb5_get_default_config_files(&configFile))
- {
- GetWindowsDirectoryA(confname,szConfname);
- confname[szConfname-1] = '\0';
-
- StringCchCatA(confname, szConfname, "\\");
- StringCchCatA(confname, szConfname, KRB5_FILE);
-
- return FALSE;
- }
-
- *confname = 0;
-
- if (configFile)
- {
- StringCchCopyA(confname, szConfname, *configFile);
- pkrb5_free_config_files(configFile);
- }
-
- if (!*confname)
- {
- GetWindowsDirectoryA(confname,szConfname);
- confname[szConfname-1] = '\0';
- StringCchCatA(confname, szConfname, "\\");
- StringCchCatA(confname, szConfname, KRB5_FILE);
- }
-
- 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_krb5_get_profile_file(krbConFile, sizeof(krbConFile))) {
- GetWindowsDirectoryA(krbConFile,sizeof(krbConFile));
- krbConFile[MAX_PATH-1] = '\0';
- StringCchCatA(confname, szConfname, "\\");
- }
-
- pFind = strrchr(krbConFile, '\\');
- if (pFind) {
- *pFind = '\0';
- StringCchCatA(krbConFile, ARRAYLENGTH(krbConFile), "\\");
- StringCchCatA(krbConFile, ARRAYLENGTH(krbConFile), KRB_FILE);
- }
- else
- krbConFile[0] = '\0';
-
- StringCchCopyA(confname, szConfname, krbConFile);
- }
- 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';
- StringCchCatA(confname, szConfname, "\\");
- StringCchCatA(confname, szConfname, KRB_FILE);
- }
- }
- 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_krb5_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,
- §ions);
-
- 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 = PMALLOC(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)) &&
-#if _MSC_VER >= 1400
- !fopen_s(&file, krb_conf, "rt")
-#else
- (file = fopen(krb_conf, "rt"))
-#endif
- )
- {
- char lineBuf[256];
-
- /*TODO: compute the actual required buffer size instead of hardcoding */
- cbsize = 16384; // arbitrary
- rlist = PMALLOC(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 PFREE().
-
- 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);
-
- if (ctx == 0)
- return NULL;
-
- pkrb5_get_default_realm(ctx,&def);
-
- if (def) {
- cch = strlen(def) + 1;
- realm = PMALLOC(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;
-}
-
-long
-khm_krb5_set_default_realm(wchar_t * realm) {
- krb5_context ctx=0;
- char * def = 0;
- long rv = 0;
- char astr[K5_MAXCCH_REALM];
-
- UnicodeStrToAnsi(astr, sizeof(astr), realm);
-
- pkrb5_init_context(&ctx);
- pkrb5_get_default_realm(ctx,&def);
-
- if ((def && strcmp(def, astr)) ||
- !def) {
- rv = pkrb5_set_default_realm(ctx, astr);
- }
-
- if (def) {
- pkrb5_free_default_realm(ctx, def);
- }
-
- pkrb5_free_context(ctx);
-
- return rv;
-}
-
-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 = 0;
- 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 = PMALLOC(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;
-}
-
-khm_int32 KHMAPI
-khm_krb5_creds_is_equal(khm_handle vcred1, khm_handle vcred2, void * dummy) {
- if (kcdb_creds_comp_attr(vcred1, vcred2, KCDB_ATTR_LOCATION) ||
- kcdb_creds_comp_attr(vcred1, vcred2, attr_id_key_enctype) ||
- kcdb_creds_comp_attr(vcred1, vcred2, attr_id_tkt_enctype) ||
- kcdb_creds_comp_attr(vcred1, vcred2, attr_id_kvno))
- return 1;
- else
- return 0;
-}
-
-void
-khm_krb5_set_identity_flags(khm_handle identity,
- khm_int32 flag_mask,
- khm_int32 flag_value) {
-
- khm_int32 t = 0;
- khm_size cb;
-
- cb = sizeof(t);
- if (KHM_FAILED(kcdb_identity_get_attr(identity,
- attr_id_krb5_idflags,
- NULL,
- &t, &cb))) {
- t = 0;
- }
-
- t &= ~flag_mask;
- t |= (flag_value & flag_mask);
-
- kcdb_identity_set_attr(identity,
- attr_id_krb5_idflags,
- &t, sizeof(t));
-}
-
-khm_int32
-khm_krb5_get_identity_flags(khm_handle identity) {
- khm_int32 t = 0;
- khm_size cb;
-
- cb = sizeof(t);
- kcdb_identity_get_attr(identity,
- attr_id_krb5_idflags,
- NULL, &t, &cb);
-
- return t;
-}
-
-long
-khm_krb5_get_temp_ccache(krb5_context ctx,
- krb5_ccache * prcc) {
- int rnd = rand();
- char ccname[MAX_PATH];
- long code = 0;
- krb5_ccache cc = 0;
-
- StringCbPrintfA(ccname, sizeof(ccname), "MEMORY:TempCache%8x", rnd);
-
- code = pkrb5_cc_resolve(ctx, ccname, &cc);
-
- if (code == 0)
- *prcc = cc;
-
- return code;
-}
-
-/*
-
- The configuration information for each identity comes from a
- multitude of layers organized as follows. The ordering is
- decreasing in priority. When looking up a value, the value will be
- looked up in each layer in turn starting at level 0. The first
- instance of the value found will be the effective value.
-
- 0 : <identity configuration>\Krb5Cred
-
- 0.1: per user
-
- 0.2: per machine
-
- 1 : <plugin configuration>\Parameters\Realms\<realm of identity>
-
- 1.1: per user
-
- 1.2: per machine
-
- 2 : <plugin configuration>\Parameters
-
- 2.1: per user
-
- 2.2: per machine
-
- 2.3: schema
-
- */
-khm_int32
-khm_krb5_get_identity_config(khm_handle ident,
- khm_int32 flags,
- khm_handle * ret_csp) {
-
- khm_int32 rv = KHM_ERROR_SUCCESS;
- khm_handle csp_i = NULL;
- khm_handle csp_ik5 = NULL;
- khm_handle csp_realms = NULL;
- khm_handle csp_realm = NULL;
- khm_handle csp_plugins = NULL;
- khm_handle csp_krbcfg = NULL;
- khm_handle csp_rv = NULL;
- wchar_t realm[KCDB_IDENT_MAXCCH_NAME];
-
- realm[0] = L'\0';
-
- if (ident) {
- wchar_t idname[KCDB_IDENT_MAXCCH_NAME];
- wchar_t * trealm;
- khm_size cb_idname = sizeof(idname);
-
- rv = kcdb_identity_get_name(ident, idname, &cb_idname);
- if (KHM_SUCCEEDED(rv) &&
- (trealm = khm_get_realm_from_princ(idname)) != NULL) {
- StringCbCopy(realm, sizeof(realm), trealm);
- }
- }
-
- if (ident) {
- rv = kcdb_identity_get_config(ident, flags, &csp_i);
- if (KHM_FAILED(rv))
- goto try_realm;
-
- rv = khc_open_space(csp_i, CSNAME_KRB5CRED, flags, &csp_ik5);
- if (KHM_FAILED(rv))
- goto try_realm;
-
- try_realm:
-
- if (realm[0] == L'\0')
- goto done_shadow_realm;
-
- rv = khc_open_space(csp_params, CSNAME_REALMS, flags, &csp_realms);
- if (KHM_FAILED(rv))
- goto done_shadow_realm;
-
- rv = khc_open_space(csp_realms, realm, flags, &csp_realm);
- if (KHM_FAILED(rv))
- goto done_shadow_realm;
-
- rv = khc_shadow_space(csp_realm, csp_params);
-
- done_shadow_realm:
-
- if (csp_ik5) {
- if (csp_realm)
- rv = khc_shadow_space(csp_ik5, csp_realm);
- else
- rv = khc_shadow_space(csp_ik5, csp_params);
-
- csp_rv = csp_ik5;
- } else {
- if (csp_realm)
- csp_rv = csp_realm;
- }
- }
-
- if (csp_rv == NULL) {
-
- /* No valid identity specified or the specified identity
- doesn't have any configuration. We default to the
- parameters key. */
-
- /* we don't just return csp_params since that's a global
- handle that we shouldn't close until the plugin is
- unloaded. The caller is going to close the returned handle
- when it is done. So we need to create a new csp_params
- that can safely be closed. */
-
- rv = kmm_get_plugins_config(0, &csp_plugins);
- if (KHM_FAILED(rv))
- goto done;
-
- rv = khc_open_space(csp_plugins, CSNAME_KRB5CRED, flags, &csp_krbcfg);
- if (KHM_FAILED(rv))
- goto done;
-
- rv = khc_open_space(csp_krbcfg, CSNAME_PARAMS, flags, &csp_rv);
- }
-
- done:
-
- *ret_csp = csp_rv;
-
- /* leave csp_ik5. If it's non-NULL, then it's the return value */
- /* leave csp_rv. It's the return value. */
- if (csp_i)
- khc_close_space(csp_i);
- if (csp_realms)
- khc_close_space(csp_realms);
-
- /* csp_realm can also be a return value if csp_ik5 was NULL */
- if (csp_realm && csp_realm != csp_rv)
- khc_close_space(csp_realm);
-
- if (csp_plugins)
- khc_close_space(csp_plugins);
- if (csp_krbcfg)
- khc_close_space(csp_krbcfg);
-
- return rv;
-}
-
-/* from get_in_tkt.c */
-static krb5_error_code
-get_libdefault_string(profile_t profile, const char * realm,
- const char * option, char ** ret_val) {
- char realmstr[K5_MAXCCH_REALM];
- char **nameval = NULL;
- const char * names[4];
- krb5_error_code code = 0;
-
- names[0] = "libdefaults";
-
- if (!realm || !realm[0])
- goto try_number_two;
-
- StringCbCopyA(realmstr, sizeof(realmstr), realm);
-
- /*
- * Try number one:
- *
- * [libdefaults]
- * REALM = {
- * option = <boolean>
- * }
- */
-
- names[1] = realmstr;
- names[2] = option;
- names[3] = 0;
- code = pprofile_get_values(profile, names, &nameval);
- if (code == 0 && nameval && nameval[0])
- goto goodbye;
-
- try_number_two:
-
- /*
- * Try number two:
- *
- * [libdefaults]
- * option = <boolean>
- */
-
- names[1] = option;
- names[2] = 0;
- code = pprofile_get_values(profile, names, &nameval);
- if (code == 0 && nameval && nameval[0])
- goto goodbye;
-
- goodbye:
- if (!nameval)
- return(ENOENT);
-
- if (!nameval[0]) {
- code = ENOENT;
- } else {
- size_t cb;
-
- if (FAILED(StringCbLengthA(nameval[0], K5_MAXCCH_REALM * sizeof(char), &cb))) {
- code = ENOMEM;
- } else {
- cb += sizeof(char);
- *ret_val = PMALLOC(cb);
-
- if (!*ret_val)
- code = ENOMEM;
- else {
- StringCbCopyA(*ret_val, cb, nameval[0]);
- code = 0;
- }
- }
- }
-
- pprofile_free_list(nameval);
-
- return code;
-}
-
-khm_int32
-khm_krb5_get_identity_params(khm_handle ident, k5_params * p) {
-
- khm_int32 rv = KHM_ERROR_SUCCESS;
- khm_handle csp_id = NULL;
- khm_int32 regf = 0;
- khm_int32 proff = 0;
- khm_int32 e;
- khm_int32 v;
- CHAR confname[MAX_PATH];
- CHAR realmname[K5_MAXCCH_REALM];
-
- ZeroMemory(p, sizeof(*p));
-
- rv = khm_krb5_get_identity_config(ident, 0, &csp_id);
- if (KHM_FAILED(rv))
- goto done_reg;
-
-
-#define GETVAL(vname, vfield, flag) \
- do { \
- e = khc_value_exists(csp_id, vname); \
- rv = khc_read_int32(csp_id, vname, &v); \
- if (KHM_FAILED(rv)) goto done_reg; \
- p->vfield = v; \
- if ((e & ~KCONF_FLAG_SCHEMA) != 0) regf |= flag; \
- } while(FALSE)
-
- /* Flags */
- GETVAL(L"Renewable", renewable, K5PARAM_F_RENEW);
- GETVAL(L"Forwardable", forwardable, K5PARAM_F_FORW);
- GETVAL(L"Proxiable", proxiable, K5PARAM_F_PROX);
- GETVAL(L"Addressless", addressless, K5PARAM_F_ADDL);
- GETVAL(L"PublicIP", publicIP, K5PARAM_F_PUBIP);
-
- /* Lifetime */
- GETVAL(L"DefaultLifetime", lifetime, K5PARAM_F_LIFE);
- GETVAL(L"MaxLifetime", lifetime_max, K5PARAM_F_LIFE_H);
- GETVAL(L"MinLifetime", lifetime_min, K5PARAM_F_LIFE_L);
-
- /* Renewable lifetime */
- GETVAL(L"DefaultRenewLifetime", renew_life, K5PARAM_F_RLIFE);
- GETVAL(L"MaxRenewLifetime", renew_life_max, K5PARAM_F_RLIFE_H);
- GETVAL(L"MinRenewLifetime", renew_life_min, K5PARAM_F_RLIFE_L);
-
-#undef GETVAL
-
- done_reg:
-
- if (csp_id)
- khc_close_space(csp_id);
-
- /* if all the parameters were read from the registry, then we have
- no reason to read from the profile file. */
- if (regf == K5PARAM_FM_ALL) {
- p->source_reg = regf;
- return KHM_ERROR_SUCCESS;
- }
-
- if (rv)
- return rv;
-
- /* we need to figure out the realm name, since there might be
- per-realm configuration in the profile file. */
-
- realmname[0] = '\0';
-
- if (ident) {
- wchar_t idname[KCDB_IDENT_MAXCCH_NAME];
- khm_size cb;
-
- idname[0] = L'\0';
- cb = sizeof(idname);
- rv = kcdb_identity_get_name(ident, idname, &cb);
- if (KHM_SUCCEEDED(rv)) {
- wchar_t * wrealm;
-
- wrealm = khm_get_realm_from_princ(idname);
- if (wrealm) {
- UnicodeStrToAnsi(realmname, sizeof(realmname), wrealm);
- }
- }
- }
-
- /* If we get here, then some of the settings we read from the
- configuration actually came from the schema. In other words,
- the values weren't really defined for this identity. So we now
- have to read the values from the krb5 configuration file. */
-
- if (!khm_krb5_get_profile_file(confname, sizeof(confname))) {
- profile_t profile;
- const char * filenames[2];
- long retval;
-
- filenames[0] = confname;
- filenames[1] = NULL;
-
- if (!pprofile_init(filenames, &profile)) {
-
- /* default ticket lifetime */
- if (!(regf & K5PARAM_F_LIFE)) {
- char * value = NULL;
- retval = get_libdefault_string(profile, realmname,
- "ticket_lifetime", &value);
-
- if (retval == 0 && value) {
- krb5_deltat d;
-
- retval = pkrb5_string_to_deltat(value, &d);
- if (retval == KRB5_DELTAT_BADFORMAT) {
- /* Historically some sites use relations of
- the form 'ticket_lifetime = 24000' where
- the unit is left out but is assumed to be
- seconds. Then there are other sites which
- use the form 'ticket_lifetime = 600' where
- the unit is assumed to be minutes. While
- these are technically wrong (a unit needs
- to be specified), we try to accomodate for
- this using the safe assumption that the
- unit is seconds and tack an 's' to the end
- and see if that works. */
-
- size_t cch;
- char tmpbuf[256];
- char * buf;
-
- do {
- if (FAILED(StringCchLengthA(value, 1024 /* unresonably large size */,
- &cch)))
- break;
-
- cch += sizeof(char) * 2; /* NULL and new 's' */
- if (cch > ARRAYLENGTH(tmpbuf))
- buf = PMALLOC(cch * sizeof(char));
- else
- buf = tmpbuf;
-
- StringCchCopyA(buf, cch, value);
- StringCchCatA(buf, cch, "s");
-
- retval = pkrb5_string_to_deltat(buf, &d);
- if (retval == 0) {
- p->lifetime = d;
- proff |= K5PARAM_F_LIFE;
- }
-
- if (buf != tmpbuf)
- PFREE(buf);
-
- } while(0);
-
- } else if (retval == 0) {
- p->lifetime = d;
- proff |= K5PARAM_F_LIFE;
- }
-
- PFREE(value);
- }
- }
-
- if (!(regf & K5PARAM_F_RLIFE)) {
- char * value = NULL;
- retval = get_libdefault_string(profile, realmname,
- "renew_lifetime", &value);
- if (retval == 0 && value) {
- krb5_deltat d;
-
- retval = pkrb5_string_to_deltat(value, &d);
- if (retval == 0) {
- p->renew_life = d;
- proff |= K5PARAM_F_RLIFE;
- }
- PFREE(value);
- }
- }
-
- if (!(regf & K5PARAM_F_FORW)) {
- char * value = NULL;
- retval = get_libdefault_string(profile, realmname,
- "forwardable", &value);
- if (retval == 0 && value) {
- khm_boolean b;
-
- if (!khm_krb5_parse_boolean(value, &b))
- p->forwardable = b;
- else
- p->forwardable = FALSE;
- PFREE(value);
- proff |= K5PARAM_F_FORW;
- }
- }
-
- if (!(regf & K5PARAM_F_RENEW)) {
- char * value = NULL;
- retval = get_libdefault_string(profile, realmname,
- "renewable", &value);
- if (retval == 0 && value) {
- khm_boolean b;
-
- if (!khm_krb5_parse_boolean(value, &b))
- p->renewable = b;
- else
- p->renewable = TRUE;
- PFREE(value);
- proff |= K5PARAM_F_RENEW;
- }
- }
-
- if (!(regf & K5PARAM_F_ADDL)) {
- char * value = NULL;
- retval = get_libdefault_string(profile, realmname,
- "noaddresses", &value);
- if (retval == 0 && value) {
- khm_boolean b;
-
- if (!khm_krb5_parse_boolean(value, &b))
- p->addressless = b;
- else
- p->addressless = TRUE;
- PFREE(value);
- proff |= K5PARAM_F_ADDL;
- }
- }
-
- if (!(regf & K5PARAM_F_PROX)) {
- char * value = NULL;
- retval = get_libdefault_string(profile, realmname,
- "proxiable", &value);
- if (retval == 0 && value) {
- khm_boolean b;
-
- if (!khm_krb5_parse_boolean(value, &b))
- p->proxiable = b;
- else
- p->proxiable = FALSE;
- PFREE(value);
- proff |= K5PARAM_F_PROX;
- }
- }
-
- pprofile_release(profile);
- }
- }
-
- p->source_reg = regf;
- p->source_prof = proff;
-
- return rv;
-}
-
-/* Note that p->source_reg and p->source_prof is used in special ways
- here. All fields that are flagged in source_reg will be written to
- the configuration (if they are different from what
- khm_krb5_get_identity_params() reports). All fields that are
- flagged in source_prof will be removed from the configuration
- (thereby exposing the value defined in the profile file). */
-khm_int32
-khm_krb5_set_identity_params(khm_handle ident, const k5_params * p) {
- khm_int32 rv = KHM_ERROR_SUCCESS;
- khm_handle csp_id = NULL;
- k5_params p_s;
- khm_int32 source_reg = p->source_reg;
- khm_int32 source_prof = p->source_prof;
-
- rv = khm_krb5_get_identity_config(ident,
- KHM_PERM_WRITE | KHM_FLAG_CREATE |
- KCONF_FLAG_WRITEIFMOD,
- &csp_id);
- if (KHM_FAILED(rv))
- goto done_reg;
-
- khm_krb5_get_identity_params(ident, &p_s);
-
- /* Remove any bits that don't make sense. Not all values can be
- specified in the profile file. */
- source_prof &= K5PARAM_FM_PROF;
-
- /* if a flag appears in both source_prof and source_reg, remove
- the flag from source_reg. */
- source_reg &= ~source_prof;
-
- /* we only write values that have changed, and that are flagged in
- source_reg */
-
- if ((source_reg & K5PARAM_F_RENEW) &&
- !!p_s.renewable != !!p->renewable)
- khc_write_int32(csp_id, L"Renewable", !!p->renewable);
-
- if ((source_reg & K5PARAM_F_FORW) &&
- !!p_s.forwardable != !!p->forwardable)
- khc_write_int32(csp_id, L"Forwardable", !!p->forwardable);
-
- if ((source_reg & K5PARAM_F_PROX) &&
- !!p_s.proxiable != !!p->proxiable)
- khc_write_int32(csp_id, L"Proxiable", !!p->proxiable);
-
- if ((source_reg & K5PARAM_F_ADDL) &&
- !!p_s.addressless != !!p->addressless)
- khc_write_int32(csp_id, L"Addressless", !!p->addressless);
-
- if ((source_reg & K5PARAM_F_PUBIP) &&
- p_s.publicIP != p->publicIP)
- khc_write_int32(csp_id, L"PublicIP", p->publicIP);
-
- if ((source_reg & K5PARAM_F_LIFE) &&
- p_s.lifetime != p->lifetime)
- khc_write_int32(csp_id, L"DefaultLifetime", p->lifetime);
-
- if ((source_reg & K5PARAM_F_LIFE_H) &&
- p_s.lifetime_max != p->lifetime_max)
- khc_write_int32(csp_id, L"MaxLifetime", p->lifetime_max);
-
- if ((source_reg & K5PARAM_F_LIFE_L) &&
- p_s.lifetime_min != p->lifetime_min)
- khc_write_int32(csp_id, L"MinLifetime", p->lifetime_min);
-
- if ((source_reg & K5PARAM_F_RLIFE) &&
- p_s.renew_life != p->renew_life)
- khc_write_int32(csp_id, L"DefaultRenewLifetime", p->renew_life);
-
- if ((source_reg & K5PARAM_F_RLIFE_H) &&
- p_s.renew_life_max != p->renew_life_max)
- khc_write_int32(csp_id, L"MaxRenewLifetime", p->renew_life_max);
-
- if ((source_reg & K5PARAM_F_RLIFE_L) &&
- p_s.renew_life_min != p->renew_life_min)
- khc_write_int32(csp_id, L"MinRenewLifetime", p->renew_life_min);
-
- /* and now, remove the values that are present in source_prof.
- Not all values are removed since not all values can be
- specified in the profile file. */
- if (source_prof & K5PARAM_F_RENEW)
- khc_remove_value(csp_id, L"Renewable", 0);
-
- if (source_prof & K5PARAM_F_FORW)
- khc_remove_value(csp_id, L"Forwardable", 0);
-
- if (source_prof & K5PARAM_F_PROX)
- khc_remove_value(csp_id, L"Proxiable", 0);
-
- if (source_prof & K5PARAM_F_ADDL)
- khc_remove_value(csp_id, L"Addressless", 0);
-
- if (source_prof & K5PARAM_F_LIFE)
- khc_remove_value(csp_id, L"DefaultLifetime", 0);
-
- if (source_prof & K5PARAM_F_RLIFE)
- khc_remove_value(csp_id, L"DefaultRenewLifetime", 0);
-
- done_reg:
- if (csp_id != NULL)
- khc_close_space(csp_id);
-
- return rv;
-}
-
-static const char *const conf_yes[] = {
- "y", "yes", "true", "t", "1", "on",
- 0,
-};
-
-static const char *const conf_no[] = {
- "n", "no", "false", "nil", "0", "off",
- 0,
-};
-
-int
-khm_krb5_parse_boolean(const char *s, khm_boolean * b)
-{
- const char *const *p;
-
- for(p=conf_yes; *p; p++) {
- if (!_stricmp(*p,s)) {
- *b = TRUE;
- return 0;
- }
- }
-
- for(p=conf_no; *p; p++) {
- if (!_stricmp(*p,s)) {
- *b = FALSE;
- return 0;
- }
- }
-
- /* Default to "no" */
- return KHM_ERROR_INVALID_PARAM;
-}
+/* +* Copyright (c) 2005 Massachusetts Institute of Technology +* Copyright (c) 2006,2007 Secure Endpoints Inc. +* +* 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 <string.h> +#include <time.h> +#include <stdlib.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 *) PMALLOC(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)); + PFREE(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 + +/* we use these structures to keep track of identities that we find + while going through the API, FILE and MSLSA caches and enumerating + credentials. The only identities we want to keep track of are the + ones that have an initial ticket. We collect information for each + of the identities we find that we have initial tickets for and + then set the properties for the identities at once. */ + +typedef struct tag_ident_data { + khm_handle ident; /* handle to the identity */ + khm_int32 count; /* number of initial tickets we have + found for this identity. */ + wchar_t ccname[MAX_PATH]; + FILETIME ft_issue; + FILETIME ft_expire; + FILETIME ft_renewexpire; + khm_int32 krb5_flags; +} ident_data; + +typedef struct tag_identlist { + ident_data * list; + khm_size n_list; + khm_size nc_list; +} identlist; + +#define IDLIST_ALLOC_INCR 8 + +static void +tc_prep_idlist(identlist * idlist) { + khm_int32 rv; + khm_size cb_ids = 0; + khm_size n_ids = 0; + khm_size i; + wchar_t * ids = NULL; + wchar_t *thisid; + + idlist->list = NULL; + idlist->n_list = 0; + idlist->nc_list = 0; + + do { + + if (ids) { + PFREE(ids); + ids = NULL; + } + + rv = kcdb_identity_enum(KCDB_IDENT_FLAG_ACTIVE, + KCDB_IDENT_FLAG_ACTIVE, + NULL, + &cb_ids, + &n_ids); + + if (rv != KHM_ERROR_TOO_LONG) + break; /* something else is wrong */ + + if (n_ids == 0 || cb_ids == 0) + break; /* no identities to process */ + +#ifdef DEBUG + assert(cb_ids > 0); +#endif + + ids = PMALLOC(cb_ids); +#ifdef DEBUG + assert(ids != NULL); +#endif + if (ids == NULL) + break; + + rv = kcdb_identity_enum(KCDB_IDENT_FLAG_ACTIVE, + KCDB_IDENT_FLAG_ACTIVE, + ids, + &cb_ids, + &n_ids); + + if (KHM_SUCCEEDED(rv)) + break; + + } while (TRUE); + + if (ids == NULL) + return; + + if (KHM_FAILED(rv) || n_ids == 0) { + if (ids) + PFREE(ids); + return; + } + + idlist->nc_list = UBOUNDSS(n_ids, IDLIST_ALLOC_INCR, IDLIST_ALLOC_INCR); + + idlist->list = PCALLOC(idlist->nc_list, sizeof(idlist->list[0])); + + for (i = 0, thisid = ids; + thisid && thisid[0]; + thisid = multi_string_next(thisid)) { + + khm_handle ident; + + rv = kcdb_identity_create(thisid, 0, &ident); + + if (KHM_FAILED(rv)) + continue; + + idlist->list[i].ident = ident; + idlist->list[i].count = 0; + + i++; + } + + idlist->n_list = i; + + PFREE(ids); +} + +static ident_data * +tc_add_ident_to_list(identlist * idlist, khm_handle ident) { + khm_size i; + ident_data * d; + + for (i=0; i < idlist->n_list; i++) { + if (kcdb_identity_is_equal(ident, idlist->list[i].ident)) + break; + } + + if (i < idlist->n_list) { + /* we already have this identity on our list. Increment the + count */ + idlist->list[i].count++; + return &idlist->list[i]; + } + + /* it wasn't in our list. Add it */ + + if (idlist->n_list + 1 > idlist->nc_list) { + idlist->nc_list = UBOUNDSS(idlist->n_list + 1, + IDLIST_ALLOC_INCR, + IDLIST_ALLOC_INCR); +#ifdef DEBUG + assert(idlist->n_list + 1 <= idlist->nc_list); +#endif + idlist->list = PREALLOC(idlist->list, + sizeof(idlist->list[0]) * idlist->nc_list); +#ifdef DEBUG + assert(idlist->list); +#endif + ZeroMemory(&idlist->list[idlist->n_list], + sizeof(idlist->list[0]) * + (idlist->nc_list - idlist->n_list)); + } + + d = &idlist->list[idlist->n_list]; + + ZeroMemory(d, sizeof(*d)); + + d->ident = ident; + d->count = 1; + + idlist->n_list++; + + kcdb_identity_hold(ident); + + return d; +} + +static void +tc_set_ident_data(identlist * idlist) { + khm_size i; + wchar_t k5idtype[KCDB_MAXCCH_NAME]; + + k5idtype[0] = L'\0'; + LoadString(hResModule, IDS_KRB5_NC_NAME, + k5idtype, ARRAYLENGTH(k5idtype)); + + for (i=0; i < idlist->n_list; i++) { +#ifdef DEBUG + assert(idlist->list[i].ident); +#endif + + if (idlist->list[i].count > 0) { + khm_int32 t; + + t = credtype_id_krb5; + kcdb_identity_set_attr(idlist->list[i].ident, + KCDB_ATTR_TYPE, + &t, + sizeof(t)); + + /* We need to manually add the type name if we want the + name to show up in the property list for the identity. + The type name is only automatically calculated for + credentials. */ + kcdb_identity_set_attr(idlist->list[i].ident, + KCDB_ATTR_TYPE_NAME, + k5idtype, + KCDB_CBSIZE_AUTO); + + kcdb_identity_set_attr(idlist->list[i].ident, + attr_id_krb5_ccname, + idlist->list[i].ccname, + KCDB_CBSIZE_AUTO); + + kcdb_identity_set_attr(idlist->list[i].ident, + KCDB_ATTR_EXPIRE, + &idlist->list[i].ft_expire, + sizeof(idlist->list[i].ft_expire)); + + kcdb_identity_set_attr(idlist->list[i].ident, + KCDB_ATTR_ISSUE, + &idlist->list[i].ft_issue, + sizeof(idlist->list[i].ft_issue)); + + kcdb_identity_set_attr(idlist->list[i].ident, + attr_id_krb5_flags, + &idlist->list[i].krb5_flags, + sizeof(idlist->list[i].krb5_flags)); + + if (idlist->list[i].ft_renewexpire.dwLowDateTime == 0 && + idlist->list[i].ft_renewexpire.dwHighDateTime == 0) { + kcdb_identity_set_attr(idlist->list[i].ident, + KCDB_ATTR_RENEW_EXPIRE, + NULL, 0); + } else { + kcdb_identity_set_attr(idlist->list[i].ident, + KCDB_ATTR_RENEW_EXPIRE, + &idlist->list[i].ft_renewexpire, + sizeof(idlist->list[i].ft_renewexpire)); + } + + } else { + /* We didn't see any TGTs for this identity. We have to + remove all the Krb5 supplied properties. */ + + khm_int32 t; + khm_size cb; + + cb = sizeof(t); + if (KHM_SUCCEEDED(kcdb_identity_get_attr(idlist->list[i].ident, + KCDB_ATTR_TYPE, NULL, + &t, + &cb)) && + t == credtype_id_krb5) { + + /* disown this and remove all our properties. the + system will GC this identity if nobody claims it.*/ + + kcdb_identity_set_attr(idlist->list[i].ident, + KCDB_ATTR_TYPE, NULL, 0); + kcdb_identity_set_attr(idlist->list[i].ident, + KCDB_ATTR_TYPE_NAME, NULL, 0); + kcdb_identity_set_attr(idlist->list[i].ident, + attr_id_krb5_ccname, NULL, 0); + kcdb_identity_set_attr(idlist->list[i].ident, + KCDB_ATTR_EXPIRE, NULL, 0); + kcdb_identity_set_attr(idlist->list[i].ident, + KCDB_ATTR_ISSUE, NULL, 0); + kcdb_identity_set_attr(idlist->list[i].ident, + attr_id_krb5_flags, NULL, 0); + kcdb_identity_set_attr(idlist->list[i].ident, + KCDB_ATTR_RENEW_EXPIRE, NULL, 0); + } else { + /* otherwise, this identity doesn't belong to us. We + should leave it as is. */ + } + } + } +} + +static void +tc_free_idlist(identlist * idlist) { + khm_size i; + + for (i=0; i < idlist->n_list; i++) { + if (idlist->list[i].ident != NULL) { + kcdb_identity_release(idlist->list[i].ident); + idlist->list[i].ident = NULL; + } + } + + if (idlist->list) + PFREE(idlist->list); + idlist->list = NULL; + idlist->n_list = 0; + idlist->nc_list = 0; +} + +#ifndef ENCTYPE_LOCAL_RC4_MD4 +#define ENCTYPE_LOCAL_RC4_MD4 0xFFFFFF80 +#endif + +#define MAX_ADDRS 256 + +static long get_tickets_from_cache(krb5_context ctx, + krb5_ccache cache, + identlist * idlist) +{ + krb5_error_code code; + krb5_principal KRBv5Principal; + krb5_flags flags = 0; + krb5_cc_cursor KRBv5Cursor; + krb5_creds KRBv5Credentials; + krb5_ticket *tkt=NULL; + char *ClientName = NULL; + char *PrincipalName = NULL; + wchar_t wbuf[256]; /* temporary conversion buffer */ + wchar_t wcc_name[KRB5_MAXCCH_CCNAME]; /* credential cache name */ + char *sServerName = NULL; + khm_handle ident = NULL; + khm_handle cred = NULL; + time_t tt; + FILETIME ft, eft; + khm_int32 ti; + +#ifdef KRB5_TC_NOTICKET + flags = KRB5_TC_NOTICKET; +#else + flags = 0; +#endif + + { + const char * cc_name; + const char * cc_type; + + cc_name = (*pkrb5_cc_get_name)(ctx, cache); + if(cc_name) { + cc_type = (*pkrb5_cc_get_type)(ctx, cache); + if (cc_type) { + StringCbPrintf(wcc_name, sizeof(wcc_name), L"%S:%S", cc_type, cc_name); + } else { + AnsiStrToUnicode(wcc_name, sizeof(wcc_name), cc_name); + khm_krb5_canon_cc_name(wcc_name, sizeof(wcc_name)); + } + } else { + cc_type = (*pkrb5_cc_get_type)(ctx, cache); + if (cc_type) { + StringCbPrintf(wcc_name, sizeof(wcc_name), L"%S:", cc_type); + } else { +#ifdef DEBUG + assert(FALSE); +#endif + StringCbCopy(wcc_name, sizeof(wcc_name), L""); + } + } + } + + _reportf(L"Getting tickets from cache [%s]", wcc_name); + + 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; + } + + _reportf(L"Found principal [%s]", wbuf); + + (*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; + khm_int32 cred_flags = 0; + + 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, &ft); + kcdb_cred_set_attr(cred, KCDB_ATTR_ISSUE, &ft, sizeof(ft)); + + tt = KRBv5Credentials.times.endtime; + TimetToFileTime(tt, &eft); + kcdb_cred_set_attr(cred, KCDB_ATTR_EXPIRE, &eft, sizeof(eft)); + + { + FILETIME ftl; + + ftl = FtSub(&eft, &ft); + kcdb_cred_set_attr(cred, KCDB_ATTR_LIFETIME, &ftl, sizeof(ftl)); + } + + if (KRBv5Credentials.times.renew_till > 0) { + FILETIME ftl; + + tt = KRBv5Credentials.times.renew_till; + TimetToFileTime(tt, &eft); + kcdb_cred_set_attr(cred, KCDB_ATTR_RENEW_EXPIRE, &eft, + sizeof(eft)); + + + ftl = FtSub(&eft, &ft); + kcdb_cred_set_attr(cred, KCDB_ATTR_RENEW_LIFETIME, &ftl, + sizeof(ftl)); + } + + ti = KRBv5Credentials.ticket_flags; + kcdb_cred_set_attr(cred, attr_id_krb5_flags, &ti, sizeof(ti)); + + /* special flags understood by NetIDMgr */ + { + khm_int32 nflags = 0; + + if (ti & TKT_FLG_RENEWABLE) + nflags |= KCDB_CRED_FLAG_RENEWABLE; + if (ti & TKT_FLG_INITIAL) + nflags |= KCDB_CRED_FLAG_INITIAL; + else { + krb5_data * c0, *c1, *r; + + /* these are macros that do not allocate any memory */ + c0 = krb5_princ_component(ctx,KRBv5Credentials.server,0); + c1 = krb5_princ_component(ctx,KRBv5Credentials.server,1); + r = krb5_princ_realm(ctx,KRBv5Credentials.server); + + if ( c0 && c1 && r && c1->length == r->length && + !strncmp(c1->data,r->data,r->length) && + !strncmp("krbtgt",c0->data,c0->length) ) + nflags |= KCDB_CRED_FLAG_INITIAL; + } + + kcdb_cred_set_flags(cred, nflags, KCDB_CRED_FLAGMASK_EXT); + + cred_flags = nflags; + } + + if ( !pkrb5_decode_ticket(&KRBv5Credentials.ticket, &tkt)) { + ti = tkt->enc_part.enctype; + kcdb_cred_set_attr(cred, attr_id_tkt_enctype, &ti, sizeof(ti)); + ti = tkt->enc_part.kvno; + kcdb_cred_set_attr(cred, attr_id_kvno, &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); + + if ( KRBv5Credentials.addresses && KRBv5Credentials.addresses[0] ) { + khm_int32 buffer[1024]; + void * bufp; + khm_size cb; + khm_int32 rv; + + bufp = (void *) buffer; + cb = sizeof(buffer); + + rv = serialize_krb5_addresses(KRBv5Credentials.addresses, + bufp, + &cb); + if (rv == KHM_ERROR_TOO_LONG) { + bufp = PMALLOC(cb); + rv = serialize_krb5_addresses(KRBv5Credentials.addresses, + bufp, + &cb); + } + + if (KHM_SUCCEEDED(rv)) { + kcdb_cred_set_attr(cred, attr_id_addr_list, + bufp, cb); + } + + if (bufp != (void *) buffer) + PFREE(bufp); + } + + if(cred_flags & KCDB_CRED_FLAG_INITIAL) { + FILETIME ft_issue_new; + FILETIME ft_expire_old; + FILETIME ft_expire_new; + ident_data * d; + + /* an initial ticket! Add it to the list of identities we + have seen so far with initial tickets. */ + d = tc_add_ident_to_list(idlist, ident); +#ifdef DEBUG + assert(d); + assert(d->count > 0); +#endif + + tt = KRBv5Credentials.times.endtime; + TimetToFileTime(tt, &ft_expire_new); + + tt = KRBv5Credentials.times.starttime; + TimetToFileTime(tt, &ft_issue_new); + + /* so now, we have to set the properties of the identity + based on the properties of this credential under the + following circumstances: + + - If this is the first time we are hitting this + identity. + + - If this is not the MSLSA: cache and the expiry time + for this credential is longer than the time already + found for this identity. + */ + + ft_expire_old = d->ft_expire; + + if(d->count == 1 + || (CompareFileTime(&ft_expire_new, &ft_expire_old) > 0 && + wcscmp(wcc_name, L"MSLSA:") != 0)) { + + _reportf(L"Setting properties for identity (count=%d)", d->count); + + StringCbCopy(d->ccname, sizeof(d->ccname), + wcc_name); + d->ft_expire = ft_expire_new; + d->ft_issue = ft_issue_new; + + if (KRBv5Credentials.times.renew_till > 0) { + tt = KRBv5Credentials.times.renew_till; + TimetToFileTime(tt, &ft); + d->ft_renewexpire = ft; + } else { + ZeroMemory(&d->ft_renewexpire, sizeof(d->ft_renewexpire)); + } + + d->krb5_flags = KRBv5Credentials.ticket_flags; + } + } + + 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: + + return code; +} + +long +khm_krb5_list_tickets(krb5_context *krbv5Context) +{ + krb5_context ctx = NULL; + krb5_ccache cache = NULL; + krb5_error_code code = 0; + apiCB * cc_ctx = NULL; + struct _infoNC ** pNCi = NULL; + int i; + khm_int32 t; + wchar_t * ms = NULL; + khm_size cb; + identlist idl; + + kcdb_credset_flush(krb5_credset); + tc_prep_idlist(&idl); + + if((*krbv5Context == 0) && (code = (*pkrb5_init_context)(krbv5Context))) { + goto _exit; + } + + ctx = (*krbv5Context); + + if (!pcc_initialize || + !pcc_get_NC_info || + !pcc_free_NC_info || + !pcc_shutdown) + goto _skip_cc_iter; + + 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; + + for(i=0; pNCi[i]; i++) { + char ccname[KRB5_MAXCCH_CCNAME]; + + if (pNCi[i]->vers != CC_CRED_V5) + continue; + + if (FAILED(StringCchPrintfA(ccname, sizeof(ccname), "API:%s", + pNCi[i]->name))) + continue; + + code = (*pkrb5_cc_resolve)(ctx, ccname, &cache); + + if (code) + continue; + + code = get_tickets_from_cache(ctx, cache, &idl); + + if(ctx != NULL && cache != NULL) + (*pkrb5_cc_close)(ctx, cache); + + cache = 0; + } + + _skip_cc_iter: + + if (khc_read_multi_string(csp_params, L"FileCCList", NULL, &cb) + == KHM_ERROR_TOO_LONG && + cb > sizeof(wchar_t) * 2) { + wchar_t * t; + char ccname[MAX_PATH + 6]; + + ms = PMALLOC(cb); +#ifdef DEBUG + assert(ms); +#endif + khc_read_multi_string(csp_params, L"FileCCList", ms, &cb); + + for(t = ms; t && *t; t = multi_string_next(t)) { + StringCchPrintfA(ccname, ARRAYLENGTH(ccname), + "FILE:%S", t); + + code = (*pkrb5_cc_resolve)(ctx, ccname, &cache); + + if (code) + continue; + + code = get_tickets_from_cache(ctx, cache, &idl); + + if (ctx != NULL && cache != NULL) + (*pkrb5_cc_close)(ctx, cache); + cache = 0; + } + + PFREE(ms); + } + + if (KHM_SUCCEEDED(khc_read_int32(csp_params, L"MsLsaList", &t)) && t) { + code = (*pkrb5_cc_resolve)(ctx, "MSLSA:", &cache); + + if (code == 0 && cache) { + code = get_tickets_from_cache(ctx, cache, &idl); + } + + 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); + tc_set_ident_data(&idl); + tc_free_idlist(&idl); + + return(code); +} + +int +khm_krb5_renew_cred(khm_handle cred) +{ + khm_handle identity = NULL; + krb5_error_code code = 0; + krb5_context ctx = NULL; + krb5_ccache cc = NULL; + krb5_principal me = NULL, server = NULL; + krb5_creds in_creds, cc_creds; + krb5_creds * out_creds = NULL; + + wchar_t wname[512]; + khm_size cbname; + char name[512]; + khm_boolean brenewIdentity = FALSE; + khm_boolean istgt = FALSE; + + khm_int32 flags; + + cbname = sizeof(wname); + kcdb_cred_get_name(cred, wname, &cbname); + _reportf(L"Krb5 renew cred for %s", wname); + + kcdb_cred_get_flags(cred, &flags); + + if (!(flags & KCDB_CRED_FLAG_INITIAL)) { + _reportf(L"Krb5 skipping renewal because this is not an initial credential"); + return 0; + } + + memset(&in_creds, 0, sizeof(in_creds)); + memset(&cc_creds, 0, sizeof(cc_creds)); + + if (cred == NULL) { +#ifdef DEBUG + assert(FALSE); +#endif + goto cleanup; + } + + if (KHM_FAILED(kcdb_cred_get_identity(cred, &identity))) { +#ifdef DEBUG + assert(FALSE); +#endif + goto cleanup; + } + + code = khm_krb5_initialize(identity, &ctx, &cc); + if (code) + goto cleanup; + + code = pkrb5_cc_get_principal(ctx, cc, &me); + if (code) + goto cleanup; + + cbname = sizeof(wname); + if (KHM_FAILED(kcdb_cred_get_name(cred, wname, &cbname))) + goto cleanup; + + UnicodeStrToAnsi(name, sizeof(name), wname); + + code = pkrb5_parse_name(ctx, name, &server); + if (code) + goto cleanup; + + in_creds.client = me; + in_creds.server = server; + +#ifdef KRB5_TC_NOTICKET + pkrb5_cc_set_flags(ctx, cc, 0); +#endif + + if (strlen("krbtgt") != krb5_princ_name(ctx, server)->length || + strncmp("krbtgt", krb5_princ_name(ctx, server)->data, krb5_princ_name(ctx, server)->length)) + { + code = pkrb5_get_renewed_creds(ctx, &cc_creds, me, cc, name); + if (code) { + code = pkrb5_cc_retrieve_cred(ctx, cc, 0, &in_creds, &cc_creds); + if (code == 0) { + code = pkrb5_cc_remove_cred(ctx, cc, 0, &cc_creds); + if (code) { + brenewIdentity = TRUE; + goto cleanup; + } + } + } + + code = pkrb5_get_credentials(ctx, 0, cc, &in_creds, &out_creds); + } else { + istgt = TRUE; + code = pkrb5_get_renewed_creds(ctx, &cc_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; + } + + if (istgt) { + code = pkrb5_cc_initialize(ctx, cc, me); + if (code) goto cleanup; + + } + + code = pkrb5_cc_store_cred(ctx, cc, istgt ? &cc_creds : out_creds); + if (code) goto cleanup; + + + cleanup: + + if (in_creds.client == me) + in_creds.client = NULL; + if (in_creds.server == server) + in_creds.server = NULL; + + if (me) + pkrb5_free_principal(ctx, me); + + if (server) + pkrb5_free_principal(ctx, server); + + pkrb5_free_cred_contents(ctx, &in_creds); + pkrb5_free_cred_contents(ctx, &cc_creds); + + if (out_creds) + pkrb5_free_creds(ctx, out_creds); + + if (cc && ctx) + pkrb5_cc_close(ctx, cc); + + if (ctx) + pkrb5_free_context(ctx); + + if (identity) { + if (brenewIdentity) + code = khm_krb5_renew_ident(identity); + kcdb_identity_release(identity); + } + + return code; +} + +int +khm_krb5_renew_ident(khm_handle identity) +{ + krb5_error_code code = 0; + krb5_context ctx = NULL; + krb5_ccache cc = NULL; + krb5_principal me = NULL; + krb5_principal server = NULL; + krb5_creds my_creds; + krb5_data *realm = NULL; + wchar_t idname[KCDB_IDENT_MAXCCH_NAME]; + khm_size cb; + khm_int32 k5_flags; + + memset(&my_creds, 0, sizeof(krb5_creds)); + + if ( !pkrb5_init_context ) + goto cleanup; + + cb = sizeof(idname); + kcdb_identity_get_name(identity, idname, &cb); + + if (khm_krb5_get_identity_flags(identity) & K5IDFLAG_IMPORTED) { +#ifndef NO_REIMPORT_MSLSA_CREDS + /* we are trying to renew the identity that was imported from + MSLSA: */ + BOOL imported; + BOOL retry_import = FALSE; + char cidname[KCDB_IDENT_MAXCCH_NAME]; + khm_handle imported_id = NULL; + khm_size cb; + FILETIME ft_expire; + FILETIME ft_now; + FILETIME ft_threshold; + krb5_principal princ = NULL; + + UnicodeStrToAnsi(cidname, sizeof(cidname), idname); + + imported = khm_krb5_ms2mit(cidname, FALSE, TRUE, &imported_id); + + if (imported == 0) + goto import_failed; + + /* if the imported identity has already expired or will soon, + we clear the cache and try again. */ + khm_krb5_list_tickets(&ctx); + + cb = sizeof(ft_expire); + if (KHM_FAILED(kcdb_identity_get_attr(imported_id, KCDB_ATTR_EXPIRE, + NULL, &ft_expire, &cb))) + goto import_failed; + + GetSystemTimeAsFileTime(&ft_now); + TimetToFileTimeInterval(5 * 60, &ft_threshold); + + ft_now = FtAdd(&ft_now, &ft_threshold); + + if (CompareFileTime(&ft_expire, &ft_now) < 0) { + /* the ticket lifetime is not long enough */ + + code = 0; + + if (ctx == NULL) + code = pkrb5_init_context(&ctx); + if (code) + goto import_failed; + + code = pkrb5_cc_resolve(ctx, "MSLSA:", &cc); + if (code) + goto import_failed; + + code = pkrb5_cc_get_principal(ctx, cc, &princ); + if (code) + goto import_failed; + + pkrb5_cc_initialize(ctx, cc, princ); + + retry_import = TRUE; + } + + import_failed: + + if (imported_id) { + kcdb_identity_release(imported_id); + imported_id = NULL; + } + + if (ctx) { + if (cc) { + pkrb5_cc_close(ctx, cc); + cc = NULL; + } + + if (princ) { + pkrb5_free_principal(ctx, princ); + princ = NULL; + } + + /* leave ctx so we can use it later */ + } + + if (retry_import) + imported = khm_krb5_ms2mit(cidname, FALSE, TRUE, NULL); + + if (imported) + goto cleanup; + + /* if the import failed, then we try to renew the identity via + the usual procedure. */ + +#else + /* if we are suppressing further imports from MSLSA, we just + skip renewing this identity. */ + goto cleanup; +#endif + } + + cb = sizeof(k5_flags); + if (KHM_SUCCEEDED(kcdb_identity_get_attr(identity, + attr_id_krb5_flags, + NULL, + &k5_flags, + &cb)) && + !(k5_flags & TKT_FLG_RENEWABLE)) { + + code = KRB5KDC_ERR_BADOPTION; + goto cleanup; + } + + { + FILETIME ft_now; + FILETIME ft_exp; + + cb = sizeof(ft_exp); + GetSystemTimeAsFileTime(&ft_now); + if (KHM_SUCCEEDED(kcdb_identity_get_attr(identity, + KCDB_ATTR_EXPIRE, + NULL, + &ft_exp, + &cb)) && + CompareFileTime(&ft_exp, &ft_now) < 0) { + + code = KRB5KRB_AP_ERR_TKT_EXPIRED; + goto cleanup; + + } + } + + 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 = NULL; + if (my_creds.server == server) + my_creds.server = NULL; + + if (ctx) { + 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); + 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 = NULL; + krb5_ccache cc = NULL; + krb5_principal me = NULL; + char* name = NULL; + 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; + + _reportf(L"In khm_krb5_kinit"); + + pkrb5_get_init_creds_opt_init(&options); + pkrb5_get_init_creds_opt_set_change_password_prompt(&options, 0); + + memset(&my_creds, 0, sizeof(my_creds)); + + if (alt_ctx) { + ctx = alt_ctx; + } else { + code = pkrb5_init_context(&ctx); + if (code) + goto cleanup; + } + + if (ccache) { + _reportf(L"Using supplied ccache name %S", ccache); + code = pkrb5_cc_resolve(ctx, ccache, &cc); + } else { + khm_handle identity = NULL; + khm_handle csp_ident = NULL; + khm_handle csp_k5 = NULL; + wchar_t idname[KCDB_IDENT_MAXCCH_NAME]; + wchar_t wccname[MAX_PATH]; + char ccname[MAX_PATH]; + char * pccname = principal_name; + khm_size cb; + + idname[0] = L'\0'; + AnsiStrToUnicode(idname, sizeof(idname), principal_name); + + cb = sizeof(wccname); + + if (KHM_SUCCEEDED(kcdb_identity_create(idname, 0, &identity)) && + + KHM_SUCCEEDED(kcdb_identity_get_config(identity, 0, &csp_ident)) && + + KHM_SUCCEEDED(khc_open_space(csp_ident, CSNAME_KRB5CRED, 0, + &csp_k5)) && + + KHM_SUCCEEDED(khc_read_string(csp_k5, L"DefaultCCName", + wccname, &cb)) && + + cb > sizeof(wchar_t)) { + + _reportf(L"Using DefaultCCName [%s] from identity", wccname); + + UnicodeStrToAnsi(ccname, sizeof(ccname), wccname); + pccname = ccname; + } + + if (csp_k5) + khc_close_space(csp_k5); + if (csp_ident) + khc_close_space(csp_ident); + if (identity) + kcdb_identity_release(identity); + + code = pkrb5_cc_resolve(ctx, pccname, &cc); + } + + _reportf(L"krb5_cc_resolve returns code %d", code); + + 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 { + krb5_address ** local_addrs=NULL; + DWORD netIPAddr; + + pkrb5_os_localaddr(ctx, &local_addrs); + i = 0; + while ( local_addrs[i++] ); + addr_count = i + 1; + + addrs = (krb5_address **) PMALLOC((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 *)PMALLOC(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 *)PMALLOC(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); + + if (publicIP) { + // we are going to add the public IP address specified by the user + // to the list provided by the operating system + addrs[i] = (krb5_address *)PMALLOC(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 *)PMALLOC(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); + _reportf(L"krb5_get_init_creds_password returns code %d", code); + + if (code) goto cleanup; + + code = pkrb5_cc_initialize(ctx, cc, me); + _reportf(L"krb5_cc_initialize returns code %d", code); + if (code) goto cleanup; + + code = pkrb5_cc_store_cred(ctx, cc, &my_creds); + _reportf(L"krb5_cc_store_cred returns code %d", code); + if (code) goto cleanup; + +cleanup: + if ( addrs ) { + for ( i=0;i<addr_count;i++ ) { + if ( addrs[i] ) { + if ( addrs[i]->contents ) + PFREE(addrs[i]->contents); + PFREE(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) { + /* if the colon is just 1 character away from the beginning, + it's a FILE: cc */ + if (colon - wcc_name == 1) { + if (cb_len + 5 * sizeof(wchar_t) > cb_cc_name) + return KHM_ERROR_TOO_LONG; + + memmove(&wcc_name[5], &wcc_name[0], cb_len); + memmove(&wcc_name[0], L"FILE:", sizeof(wchar_t) * 5); + } + + 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 = NULL; + 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) { + _reportf(L"No tickets to delete"); + + 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; + + _reportf(L"Destroying ccache [%s]", ccname); + + 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) { + _reportf(L"krb5_cc_destroy returns code %d", code); + } + + _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; + + _reportf(L"Looking at ccache [%s]", ccname); + + 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; + + _reportf(L"Attempting to delete ticket %s", srvname); + + 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); + + if (ctx != NULL) + pkrb5_free_context(ctx); + + 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(char * match_princ, BOOL match_realm, BOOL save_creds, + khm_handle * ret_ident) +{ +#ifdef NO_KRB5 + return(FALSE); +#else /* NO_KRB5 */ + krb5_context kcontext = 0; + krb5_error_code code = 0; + krb5_ccache ccache=0; + krb5_ccache mslsa_ccache=0; + krb5_creds creds; + krb5_cc_cursor cursor=0; + krb5_principal princ = 0; + khm_handle ident = NULL; + wchar_t wname[KCDB_IDENT_MAXCCH_NAME]; + char cname[KCDB_IDENT_MAXCCH_NAME]; + char *cache_name = NULL; + char *princ_name = NULL; + BOOL rc = FALSE; + + kherr_reportf(L"Begin : khm_krb5_ms2mit. save_cred=%d\n", (int) save_creds); + + if ( !pkrb5_init_context ) + goto cleanup; + + if (code = pkrb5_init_context(&kcontext)) + goto cleanup; + + kherr_reportf(L"Resolving MSLSA\n"); + + if (code = pkrb5_cc_resolve(kcontext, "MSLSA:", &mslsa_ccache)) + goto cleanup; + + if ( save_creds ) { + kherr_reportf(L"Getting principal\n"); + if (code = pkrb5_cc_get_principal(kcontext, mslsa_ccache, &princ)) + goto cleanup; + + kherr_reportf(L"Unparsing name\n"); + if (code = pkrb5_unparse_name(kcontext, princ, &princ_name)) + goto cleanup; + + AnsiStrToUnicode(wname, sizeof(wname), princ_name); + + kherr_reportf(L"Unparsed name [%s]", wname); + + /* see if we have to match a specific principal */ + if (match_princ != NULL) { + if (strcmp(princ_name, match_princ)) { + kherr_reportf(L"Principal mismatch. Wanted [%S], found [%S]", + match_princ, princ_name); + goto cleanup; + } + } else if (match_realm) { + wchar_t * wdefrealm; + char defrealm[256]; + krb5_data * princ_realm; + + wdefrealm = khm_krb5_get_default_realm(); + if (wdefrealm == NULL) { + kherr_reportf(L"Can't determine default realm"); + goto cleanup; + } + + princ_realm = krb5_princ_realm(kcontext, princ); + UnicodeStrToAnsi(defrealm, sizeof(defrealm), wdefrealm); + + if (strncmp(defrealm, princ_realm->data, princ_realm->length)) { + kherr_reportf(L"Realm mismatch. Wanted [%S], found [%*S]", + defrealm, princ_realm->length, princ_realm->data); + PFREE(wdefrealm); + goto cleanup; + } + + PFREE(wdefrealm); + } + + if (KHM_SUCCEEDED(kcdb_identity_create(wname, + KCDB_IDENT_FLAG_CREATE, + &ident))) { + khm_handle idconfig = NULL; + khm_handle k5config = NULL; + khm_size cb; + + wname[0] = L'\0'; + + kcdb_identity_get_config(ident, KHM_FLAG_CREATE, &idconfig); + if (idconfig == NULL) + goto _done_checking_config; + + khc_open_space(idconfig, CSNAME_KRB5CRED, KHM_FLAG_CREATE, &k5config); + if (k5config == NULL) + goto _done_checking_config; + + cb = sizeof(wname); + khc_read_string(k5config, + L"DefaultCCName", + wname, &cb); + + _done_checking_config: + + if (idconfig) + khc_close_space(idconfig); + if (k5config) + khc_close_space(k5config); + + if (wname[0]) { + UnicodeStrToAnsi(cname, sizeof(cname), wname); + } else { + StringCbPrintfA(cname, sizeof(cname), "API:%s", princ_name); + } + + cache_name = cname; + + } else { + /* the identity could not be created. we just use the + name of the principal as the ccache name. */ + StringCbPrintfA(cname, sizeof(cname), "API:%s", princ_name); + cache_name = cname; + } + + kherr_reportf(L"Resolving target cache [%S]\n", cache_name); + + if (code = pkrb5_cc_resolve(kcontext, cache_name, &ccache)) { + kherr_reportf(L"Cannot resolve cache [%S] with code=%d. Trying default.\n", cache_name, code); + + if (code = pkrb5_cc_default(kcontext, &ccache)) { + kherr_reportf(L"Failed to resolve default ccache. Code=%d", code); + goto cleanup; + } + } + + kherr_reportf(L"Initializing ccache\n"); + if (code = pkrb5_cc_initialize(kcontext, ccache, princ)) + goto cleanup; + + kherr_reportf(L"Copying credentials\n"); + if (code = pkrb5_cc_copy_creds(kcontext, mslsa_ccache, ccache)) + goto cleanup; + + /* and mark the identity as having been imported */ + if (ident) { + khm_krb5_set_identity_flags(ident, K5IDFLAG_IMPORTED, K5IDFLAG_IMPORTED); + + if (ret_ident) { + *ret_ident = ident; + kcdb_identity_hold(*ret_ident); + } + } + + 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: + kherr_reportf(L" Received code=%d", code); + + 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); + if (ident) + kcdb_identity_release(ident); + + return(rc); +#endif /* NO_KRB5 */ +} + +#define KRB_FILE "KRB.CON" +#define KRBREALM_FILE "KRBREALM.CON" +#define KRB5_FILE "KRB5.INI" +#define KRB5_TMP_FILE "KRB5.INI.TMP" + +BOOL +khm_krb5_get_temp_profile_file(LPSTR confname, UINT szConfname) +{ + GetTempPathA(szConfname, confname); + confname[szConfname-1] = '\0'; + StringCchCatA(confname, szConfname, KRB5_TMP_FILE); + confname[szConfname-1] = '\0'; + return FALSE; +} + +#ifdef NOT_QUITE_IMPLEMENTED_YET +BOOL +khm_krb5_set_profile_file(krb5_context ctx, LPSTR confname) +{ + char *conffiles[2]; + + if (confname == NULL || + pkrb5_set_config_files == NULL || + ctx == NULL) + return FALSE; + + conffiles[0] = confname; + conffiles[1] = NULL; + + if (pkrb5_set_config_files(ctx, conffiles)) + return FALSE; + else + return TRUE; +} +#endif + +BOOL +khm_krb5_get_profile_file(LPSTR confname, UINT szConfname) +{ + char **configFile = NULL; + if (pkrb5_get_default_config_files(&configFile)) + { + GetWindowsDirectoryA(confname,szConfname); + confname[szConfname-1] = '\0'; + + StringCchCatA(confname, szConfname, "\\"); + StringCchCatA(confname, szConfname, KRB5_FILE); + + return FALSE; + } + + *confname = 0; + + if (configFile) + { + StringCchCopyA(confname, szConfname, *configFile); + pkrb5_free_config_files(configFile); + } + + if (!*confname) + { + GetWindowsDirectoryA(confname,szConfname); + confname[szConfname-1] = '\0'; + StringCchCatA(confname, szConfname, "\\"); + StringCchCatA(confname, szConfname, KRB5_FILE); + } + + 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_krb5_get_profile_file(krbConFile, sizeof(krbConFile))) { + GetWindowsDirectoryA(krbConFile,sizeof(krbConFile)); + krbConFile[MAX_PATH-1] = '\0'; + StringCchCatA(confname, szConfname, "\\"); + } + + pFind = strrchr(krbConFile, '\\'); + if (pFind) { + *pFind = '\0'; + StringCchCatA(krbConFile, ARRAYLENGTH(krbConFile), "\\"); + StringCchCatA(krbConFile, ARRAYLENGTH(krbConFile), KRB_FILE); + } + else + krbConFile[0] = '\0'; + + StringCchCopyA(confname, szConfname, krbConFile); + } + 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'; + StringCchCatA(confname, szConfname, "\\"); + StringCchCatA(confname, szConfname, KRB_FILE); + } + } + 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_krb5_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, + §ions); + + 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 = PMALLOC(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)) && +#if _MSC_VER >= 1400 + !fopen_s(&file, krb_conf, "rt") +#else + (file = fopen(krb_conf, "rt")) +#endif + ) + { + char lineBuf[256]; + + /*TODO: compute the actual required buffer size instead of hardcoding */ + cbsize = 16384; // arbitrary + rlist = PMALLOC(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 PFREE(). + + 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); + + if (ctx == 0) + return NULL; + + pkrb5_get_default_realm(ctx,&def); + + if (def) { + cch = strlen(def) + 1; + realm = PMALLOC(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; +} + +long +khm_krb5_set_default_realm(wchar_t * realm) { + krb5_context ctx=0; + char * def = 0; + long rv = 0; + char astr[K5_MAXCCH_REALM]; + + UnicodeStrToAnsi(astr, sizeof(astr), realm); + + pkrb5_init_context(&ctx); + pkrb5_get_default_realm(ctx,&def); + + if ((def && strcmp(def, astr)) || + !def) { + rv = pkrb5_set_default_realm(ctx, astr); + } + + if (def) { + pkrb5_free_default_realm(ctx, def); + } + + pkrb5_free_context(ctx); + + return rv; +} + +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 = 0; + 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 = PMALLOC(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; +} + +khm_int32 KHMAPI +khm_krb5_creds_is_equal(khm_handle vcred1, khm_handle vcred2, void * dummy) { + if (kcdb_creds_comp_attr(vcred1, vcred2, KCDB_ATTR_LOCATION) || + kcdb_creds_comp_attr(vcred1, vcred2, attr_id_key_enctype) || + kcdb_creds_comp_attr(vcred1, vcred2, attr_id_tkt_enctype) || + kcdb_creds_comp_attr(vcred1, vcred2, attr_id_kvno)) + return 1; + else + return 0; +} + +void +khm_krb5_set_identity_flags(khm_handle identity, + khm_int32 flag_mask, + khm_int32 flag_value) { + + khm_int32 t = 0; + khm_size cb; + + cb = sizeof(t); + if (KHM_FAILED(kcdb_identity_get_attr(identity, + attr_id_krb5_idflags, + NULL, + &t, &cb))) { + t = 0; + } + + t &= ~flag_mask; + t |= (flag_value & flag_mask); + + kcdb_identity_set_attr(identity, + attr_id_krb5_idflags, + &t, sizeof(t)); +} + +khm_int32 +khm_krb5_get_identity_flags(khm_handle identity) { + khm_int32 t = 0; + khm_size cb; + + cb = sizeof(t); + kcdb_identity_get_attr(identity, + attr_id_krb5_idflags, + NULL, &t, &cb); + + return t; +} + +long +khm_krb5_get_temp_ccache(krb5_context ctx, + krb5_ccache * prcc) { + int rnd = rand(); + char ccname[MAX_PATH]; + long code = 0; + krb5_ccache cc = 0; + + StringCbPrintfA(ccname, sizeof(ccname), "MEMORY:TempCache%8x", rnd); + + code = pkrb5_cc_resolve(ctx, ccname, &cc); + + if (code == 0) + *prcc = cc; + + return code; +} + +/* + + The configuration information for each identity comes from a + multitude of layers organized as follows. The ordering is + decreasing in priority. When looking up a value, the value will be + looked up in each layer in turn starting at level 0. The first + instance of the value found will be the effective value. + + 0 : <identity configuration>\Krb5Cred + + 0.1: per user + + 0.2: per machine + + 1 : <plugin configuration>\Parameters\Realms\<realm of identity> + + 1.1: per user + + 1.2: per machine + + 2 : <plugin configuration>\Parameters + + 2.1: per user + + 2.2: per machine + + 2.3: schema + + */ +khm_int32 +khm_krb5_get_identity_config(khm_handle ident, + khm_int32 flags, + khm_handle * ret_csp) { + + khm_int32 rv = KHM_ERROR_SUCCESS; + khm_handle csp_i = NULL; + khm_handle csp_ik5 = NULL; + khm_handle csp_realms = NULL; + khm_handle csp_realm = NULL; + khm_handle csp_plugins = NULL; + khm_handle csp_krbcfg = NULL; + khm_handle csp_rv = NULL; + wchar_t realm[KCDB_IDENT_MAXCCH_NAME]; + + realm[0] = L'\0'; + + if (ident) { + wchar_t idname[KCDB_IDENT_MAXCCH_NAME]; + wchar_t * trealm; + khm_size cb_idname = sizeof(idname); + + rv = kcdb_identity_get_name(ident, idname, &cb_idname); + if (KHM_SUCCEEDED(rv) && + (trealm = khm_get_realm_from_princ(idname)) != NULL) { + StringCbCopy(realm, sizeof(realm), trealm); + } + } + + if (ident) { + rv = kcdb_identity_get_config(ident, flags, &csp_i); + if (KHM_FAILED(rv)) + goto try_realm; + + rv = khc_open_space(csp_i, CSNAME_KRB5CRED, flags, &csp_ik5); + if (KHM_FAILED(rv)) + goto try_realm; + + try_realm: + + if (realm[0] == L'\0') + goto done_shadow_realm; + + rv = khc_open_space(csp_params, CSNAME_REALMS, flags, &csp_realms); + if (KHM_FAILED(rv)) + goto done_shadow_realm; + + rv = khc_open_space(csp_realms, realm, flags, &csp_realm); + if (KHM_FAILED(rv)) + goto done_shadow_realm; + + rv = khc_shadow_space(csp_realm, csp_params); + + done_shadow_realm: + + if (csp_ik5) { + if (csp_realm) + rv = khc_shadow_space(csp_ik5, csp_realm); + else + rv = khc_shadow_space(csp_ik5, csp_params); + + csp_rv = csp_ik5; + } else { + if (csp_realm) + csp_rv = csp_realm; + } + } + + if (csp_rv == NULL) { + + /* No valid identity specified or the specified identity + doesn't have any configuration. We default to the + parameters key. */ + + /* we don't just return csp_params since that's a global + handle that we shouldn't close until the plugin is + unloaded. The caller is going to close the returned handle + when it is done. So we need to create a new csp_params + that can safely be closed. */ + + rv = kmm_get_plugins_config(0, &csp_plugins); + if (KHM_FAILED(rv)) + goto done; + + rv = khc_open_space(csp_plugins, CSNAME_KRB5CRED, flags, &csp_krbcfg); + if (KHM_FAILED(rv)) + goto done; + + rv = khc_open_space(csp_krbcfg, CSNAME_PARAMS, flags, &csp_rv); + } + + done: + + *ret_csp = csp_rv; + + /* leave csp_ik5. If it's non-NULL, then it's the return value */ + /* leave csp_rv. It's the return value. */ + if (csp_i) + khc_close_space(csp_i); + if (csp_realms) + khc_close_space(csp_realms); + + /* csp_realm can also be a return value if csp_ik5 was NULL */ + if (csp_realm && csp_realm != csp_rv) + khc_close_space(csp_realm); + + if (csp_plugins) + khc_close_space(csp_plugins); + if (csp_krbcfg) + khc_close_space(csp_krbcfg); + + return rv; +} + +/* from get_in_tkt.c */ +static krb5_error_code +get_libdefault_string(profile_t profile, const char * realm, + const char * option, char ** ret_val) { + char realmstr[K5_MAXCCH_REALM]; + char **nameval = NULL; + const char * names[4]; + krb5_error_code code = 0; + + names[0] = "libdefaults"; + + if (!realm || !realm[0]) + goto try_number_two; + + StringCbCopyA(realmstr, sizeof(realmstr), realm); + + /* + * Try number one: + * + * [libdefaults] + * REALM = { + * option = <boolean> + * } + */ + + names[1] = realmstr; + names[2] = option; + names[3] = 0; + code = pprofile_get_values(profile, names, &nameval); + if (code == 0 && nameval && nameval[0]) + goto goodbye; + + try_number_two: + + /* + * Try number two: + * + * [libdefaults] + * option = <boolean> + */ + + names[1] = option; + names[2] = 0; + code = pprofile_get_values(profile, names, &nameval); + if (code == 0 && nameval && nameval[0]) + goto goodbye; + + goodbye: + if (!nameval) + return(ENOENT); + + if (!nameval[0]) { + code = ENOENT; + } else { + size_t cb; + + if (FAILED(StringCbLengthA(nameval[0], K5_MAXCCH_REALM * sizeof(char), &cb))) { + code = ENOMEM; + } else { + cb += sizeof(char); + *ret_val = PMALLOC(cb); + + if (!*ret_val) + code = ENOMEM; + else { + StringCbCopyA(*ret_val, cb, nameval[0]); + code = 0; + } + } + } + + pprofile_free_list(nameval); + + return code; +} + +khm_int32 +khm_krb5_get_identity_params(khm_handle ident, k5_params * p) { + + khm_int32 rv = KHM_ERROR_SUCCESS; + khm_handle csp_id = NULL; + khm_int32 regf = 0; + khm_int32 proff = 0; + khm_int32 e; + khm_int32 v; + CHAR confname[MAX_PATH]; + CHAR realmname[K5_MAXCCH_REALM]; + + ZeroMemory(p, sizeof(*p)); + + rv = khm_krb5_get_identity_config(ident, 0, &csp_id); + if (KHM_FAILED(rv)) + goto done_reg; + + +#define GETVAL(vname, vfield, flag) \ + do { \ + e = khc_value_exists(csp_id, vname); \ + rv = khc_read_int32(csp_id, vname, &v); \ + if (KHM_FAILED(rv)) goto done_reg; \ + p->vfield = v; \ + if ((e & ~KCONF_FLAG_SCHEMA) != 0) regf |= flag; \ + } while(FALSE) + + /* Flags */ + GETVAL(L"Renewable", renewable, K5PARAM_F_RENEW); + GETVAL(L"Forwardable", forwardable, K5PARAM_F_FORW); + GETVAL(L"Proxiable", proxiable, K5PARAM_F_PROX); + GETVAL(L"Addressless", addressless, K5PARAM_F_ADDL); + GETVAL(L"PublicIP", publicIP, K5PARAM_F_PUBIP); + + /* Lifetime */ + GETVAL(L"DefaultLifetime", lifetime, K5PARAM_F_LIFE); + GETVAL(L"MaxLifetime", lifetime_max, K5PARAM_F_LIFE_H); + GETVAL(L"MinLifetime", lifetime_min, K5PARAM_F_LIFE_L); + + /* Renewable lifetime */ + GETVAL(L"DefaultRenewLifetime", renew_life, K5PARAM_F_RLIFE); + GETVAL(L"MaxRenewLifetime", renew_life_max, K5PARAM_F_RLIFE_H); + GETVAL(L"MinRenewLifetime", renew_life_min, K5PARAM_F_RLIFE_L); + +#undef GETVAL + + done_reg: + + if (csp_id) + khc_close_space(csp_id); + + /* if all the parameters were read from the registry, then we have + no reason to read from the profile file. */ + if (regf == K5PARAM_FM_ALL) { + p->source_reg = regf; + return KHM_ERROR_SUCCESS; + } + + if (rv) + return rv; + + /* we need to figure out the realm name, since there might be + per-realm configuration in the profile file. */ + + realmname[0] = '\0'; + + if (ident) { + wchar_t idname[KCDB_IDENT_MAXCCH_NAME]; + khm_size cb; + + idname[0] = L'\0'; + cb = sizeof(idname); + rv = kcdb_identity_get_name(ident, idname, &cb); + if (KHM_SUCCEEDED(rv)) { + wchar_t * wrealm; + + wrealm = khm_get_realm_from_princ(idname); + if (wrealm) { + UnicodeStrToAnsi(realmname, sizeof(realmname), wrealm); + } + } + } + + /* If we get here, then some of the settings we read from the + configuration actually came from the schema. In other words, + the values weren't really defined for this identity. So we now + have to read the values from the krb5 configuration file. */ + + if (!khm_krb5_get_profile_file(confname, sizeof(confname))) { + profile_t profile; + const char * filenames[2]; + long retval; + + filenames[0] = confname; + filenames[1] = NULL; + + if (!pprofile_init(filenames, &profile)) { + + /* default ticket lifetime */ + if (!(regf & K5PARAM_F_LIFE)) { + char * value = NULL; + retval = get_libdefault_string(profile, realmname, + "ticket_lifetime", &value); + + if (retval == 0 && value) { + krb5_deltat d; + + retval = pkrb5_string_to_deltat(value, &d); + if (retval == KRB5_DELTAT_BADFORMAT) { + /* Historically some sites use relations of + the form 'ticket_lifetime = 24000' where + the unit is left out but is assumed to be + seconds. Then there are other sites which + use the form 'ticket_lifetime = 600' where + the unit is assumed to be minutes. While + these are technically wrong (a unit needs + to be specified), we try to accomodate for + this using the safe assumption that the + unit is seconds and tack an 's' to the end + and see if that works. */ + + size_t cch; + char tmpbuf[256]; + char * buf; + + do { + if (FAILED(StringCchLengthA(value, 1024 /* unresonably large size */, + &cch))) + break; + + cch += sizeof(char) * 2; /* NULL and new 's' */ + if (cch > ARRAYLENGTH(tmpbuf)) + buf = PMALLOC(cch * sizeof(char)); + else + buf = tmpbuf; + + StringCchCopyA(buf, cch, value); + StringCchCatA(buf, cch, "s"); + + retval = pkrb5_string_to_deltat(buf, &d); + if (retval == 0) { + p->lifetime = d; + proff |= K5PARAM_F_LIFE; + } + + if (buf != tmpbuf) + PFREE(buf); + + } while(0); + + } else if (retval == 0) { + p->lifetime = d; + proff |= K5PARAM_F_LIFE; + } + + PFREE(value); + } + } + + if (!(regf & K5PARAM_F_RLIFE)) { + char * value = NULL; + retval = get_libdefault_string(profile, realmname, + "renew_lifetime", &value); + if (retval == 0 && value) { + krb5_deltat d; + + retval = pkrb5_string_to_deltat(value, &d); + if (retval == 0) { + p->renew_life = d; + proff |= K5PARAM_F_RLIFE; + } + PFREE(value); + } + } + + if (!(regf & K5PARAM_F_FORW)) { + char * value = NULL; + retval = get_libdefault_string(profile, realmname, + "forwardable", &value); + if (retval == 0 && value) { + khm_boolean b; + + if (!khm_krb5_parse_boolean(value, &b)) + p->forwardable = b; + else + p->forwardable = FALSE; + PFREE(value); + proff |= K5PARAM_F_FORW; + } + } + + if (!(regf & K5PARAM_F_RENEW)) { + char * value = NULL; + retval = get_libdefault_string(profile, realmname, + "renewable", &value); + if (retval == 0 && value) { + khm_boolean b; + + if (!khm_krb5_parse_boolean(value, &b)) + p->renewable = b; + else + p->renewable = TRUE; + PFREE(value); + proff |= K5PARAM_F_RENEW; + } + } + + if (!(regf & K5PARAM_F_ADDL)) { + char * value = NULL; + retval = get_libdefault_string(profile, realmname, + "noaddresses", &value); + if (retval == 0 && value) { + khm_boolean b; + + if (!khm_krb5_parse_boolean(value, &b)) + p->addressless = b; + else + p->addressless = TRUE; + PFREE(value); + proff |= K5PARAM_F_ADDL; + } + } + + if (!(regf & K5PARAM_F_PROX)) { + char * value = NULL; + retval = get_libdefault_string(profile, realmname, + "proxiable", &value); + if (retval == 0 && value) { + khm_boolean b; + + if (!khm_krb5_parse_boolean(value, &b)) + p->proxiable = b; + else + p->proxiable = FALSE; + PFREE(value); + proff |= K5PARAM_F_PROX; + } + } + + pprofile_release(profile); + } + } + + p->source_reg = regf; + p->source_prof = proff; + + return rv; +} + +/* Note that p->source_reg and p->source_prof is used in special ways + here. All fields that are flagged in source_reg will be written to + the configuration (if they are different from what + khm_krb5_get_identity_params() reports). All fields that are + flagged in source_prof will be removed from the configuration + (thereby exposing the value defined in the profile file). */ +khm_int32 +khm_krb5_set_identity_params(khm_handle ident, const k5_params * p) { + khm_int32 rv = KHM_ERROR_SUCCESS; + khm_handle csp_id = NULL; + k5_params p_s; + khm_int32 source_reg = p->source_reg; + khm_int32 source_prof = p->source_prof; + + rv = khm_krb5_get_identity_config(ident, + KHM_PERM_WRITE | KHM_FLAG_CREATE | + KCONF_FLAG_WRITEIFMOD, + &csp_id); + if (KHM_FAILED(rv)) + goto done_reg; + + khm_krb5_get_identity_params(ident, &p_s); + + /* Remove any bits that don't make sense. Not all values can be + specified in the profile file. */ + source_prof &= K5PARAM_FM_PROF; + + /* if a flag appears in both source_prof and source_reg, remove + the flag from source_reg. */ + source_reg &= ~source_prof; + + /* we only write values that have changed, and that are flagged in + source_reg */ + + if ((source_reg & K5PARAM_F_RENEW) && + !!p_s.renewable != !!p->renewable) + khc_write_int32(csp_id, L"Renewable", !!p->renewable); + + if ((source_reg & K5PARAM_F_FORW) && + !!p_s.forwardable != !!p->forwardable) + khc_write_int32(csp_id, L"Forwardable", !!p->forwardable); + + if ((source_reg & K5PARAM_F_PROX) && + !!p_s.proxiable != !!p->proxiable) + khc_write_int32(csp_id, L"Proxiable", !!p->proxiable); + + if ((source_reg & K5PARAM_F_ADDL) && + !!p_s.addressless != !!p->addressless) + khc_write_int32(csp_id, L"Addressless", !!p->addressless); + + if ((source_reg & K5PARAM_F_PUBIP) && + p_s.publicIP != p->publicIP) + khc_write_int32(csp_id, L"PublicIP", p->publicIP); + + if ((source_reg & K5PARAM_F_LIFE) && + p_s.lifetime != p->lifetime) + khc_write_int32(csp_id, L"DefaultLifetime", p->lifetime); + + if ((source_reg & K5PARAM_F_LIFE_H) && + p_s.lifetime_max != p->lifetime_max) + khc_write_int32(csp_id, L"MaxLifetime", p->lifetime_max); + + if ((source_reg & K5PARAM_F_LIFE_L) && + p_s.lifetime_min != p->lifetime_min) + khc_write_int32(csp_id, L"MinLifetime", p->lifetime_min); + + if ((source_reg & K5PARAM_F_RLIFE) && + p_s.renew_life != p->renew_life) + khc_write_int32(csp_id, L"DefaultRenewLifetime", p->renew_life); + + if ((source_reg & K5PARAM_F_RLIFE_H) && + p_s.renew_life_max != p->renew_life_max) + khc_write_int32(csp_id, L"MaxRenewLifetime", p->renew_life_max); + + if ((source_reg & K5PARAM_F_RLIFE_L) && + p_s.renew_life_min != p->renew_life_min) + khc_write_int32(csp_id, L"MinRenewLifetime", p->renew_life_min); + + /* and now, remove the values that are present in source_prof. + Not all values are removed since not all values can be + specified in the profile file. */ + if (source_prof & K5PARAM_F_RENEW) + khc_remove_value(csp_id, L"Renewable", 0); + + if (source_prof & K5PARAM_F_FORW) + khc_remove_value(csp_id, L"Forwardable", 0); + + if (source_prof & K5PARAM_F_PROX) + khc_remove_value(csp_id, L"Proxiable", 0); + + if (source_prof & K5PARAM_F_ADDL) + khc_remove_value(csp_id, L"Addressless", 0); + + if (source_prof & K5PARAM_F_LIFE) + khc_remove_value(csp_id, L"DefaultLifetime", 0); + + if (source_prof & K5PARAM_F_RLIFE) + khc_remove_value(csp_id, L"DefaultRenewLifetime", 0); + + done_reg: + if (csp_id != NULL) + khc_close_space(csp_id); + + return rv; +} + +static const char *const conf_yes[] = { + "y", "yes", "true", "t", "1", "on", + 0, +}; + +static const char *const conf_no[] = { + "n", "no", "false", "nil", "0", "off", + 0, +}; + +int +khm_krb5_parse_boolean(const char *s, khm_boolean * b) +{ + const char *const *p; + + for(p=conf_yes; *p; p++) { + if (!_stricmp(*p,s)) { + *b = TRUE; + return 0; + } + } + + for(p=conf_no; *p; p++) { + if (!_stricmp(*p,s)) { + *b = FALSE; + return 0; + } + } + + /* Default to "no" */ + return KHM_ERROR_INVALID_PARAM; +} diff --git a/src/windows/identity/plugins/krb5/krb5funcs.h b/src/windows/identity/plugins/krb5/krb5funcs.h index b4ab452b3..d2ec28b47 100644 --- a/src/windows/identity/plugins/krb5/krb5funcs.h +++ b/src/windows/identity/plugins/krb5/krb5funcs.h @@ -1,217 +1,217 @@ -/*
- * Copyright (c) 2005 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>
-
-#if _WIN32_WINNT < 0x0501
-#define KHM_SAVE_WIN32_WINNT _WIN32_WINNT
-#undef _WIN32_WINNT
-#define _WIN32_WINNT 0x0501
-#endif
-#include<ntsecapi.h>
-#ifdef KHM_SAVE_WIN32_WINNT
-#undef _WIN32_WINNT
-#define _WIN32_WINNT KHM_SAVE_WIN32_WINNT
-#undef KHM_SAVE_WIN32_WINNT
-#endif
-
-#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
-
-#define KRB5_CONF_YES "yes"
-#define KRB5_CONF_NO "no"
-
-typedef struct tag_k5params {
-
- khm_int32 source_reg; /* flags indicating which fields were
- retrieved using the registry */
- khm_int32 source_prof; /* flags indicating which fields were
- retrieved using krb5.ini */
-
- khm_boolean renewable;
- khm_boolean forwardable;
- khm_boolean proxiable;
- khm_boolean addressless;
-
- khm_ui_4 publicIP;
-
- krb5_deltat lifetime;
- krb5_deltat lifetime_min;
- krb5_deltat lifetime_max;
-
- krb5_deltat renew_life;
- krb5_deltat renew_life_min;
- krb5_deltat renew_life_max;
-
-} k5_params;
-
-#define K5PARAM_F_RENEW 0x00000001
-#define K5PARAM_F_FORW 0x00000002
-#define K5PARAM_F_PROX 0x00000004
-#define K5PARAM_F_ADDL 0x00000008
-#define K5PARAM_F_PUBIP 0x00000010
-#define K5PARAM_F_LIFE 0x00000020
-#define K5PARAM_F_RLIFE 0x00000040
-#define K5PARAM_F_LIFE_L 0x00000080
-#define K5PARAM_F_LIFE_H 0x00000100
-#define K5PARAM_F_RLIFE_L 0x00000200
-#define K5PARAM_F_RLIFE_H 0x00000400
-
-#define K5PARAM_FM_ALL 0x000007ff
-#define K5PARAM_FM_PROF 0x0000007f
-
-/* Credential and principal operations */
-
-BOOL
-khm_krb5_ms2mit(char * match_princ,
- BOOL match_realm,
- BOOL save_creds,
- khm_handle * ret_ident);
-
-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_cred(khm_handle cred);
-
-int
-khm_krb5_renew_ident(khm_handle identity);
-
-long
-khm_krb5_list_tickets(krb5_context *krbv5Context);
-
-long
-khm_krb5_copy_ccache_by_name(krb5_context in_ctx,
- wchar_t * wscc_dest,
- wchar_t * wscc_src);
-
-long
-khm_krb5_get_temp_ccache(krb5_context ctx,
- krb5_ccache * cc);
-
-khm_int32 KHMAPI
-khm_krb5_creds_is_equal(khm_handle vcred1, khm_handle vcred2, void * dummy);
-
-
-/* Configuration */
-
-BOOL
-khm_krb5_get_profile_file(LPSTR confname, UINT szConfname);
-
-BOOL
-khm_krb5_get_temp_profile_file(LPSTR confname, UINT szConfname);
-
-wchar_t *
-khm_krb5_get_default_realm(void);
-
-long
-khm_krb5_set_default_realm(wchar_t * realm);
-
-wchar_t *
-khm_krb5_get_realm_list(void);
-
-khm_int32
-khm_krb5_get_identity_config(khm_handle ident,
- khm_int32 flags,
- khm_handle * ret_csp);
-
-void
-khm_krb5_set_identity_flags(khm_handle identity,
- khm_int32 flag_mask,
- khm_int32 flag_value);
-
-khm_int32
-khm_krb5_get_identity_flags(khm_handle identity);
-
-khm_int32
-khm_krb5_set_identity_params(khm_handle ident, const k5_params * p);
-
-khm_int32
-khm_krb5_get_identity_params(khm_handle ident, k5_params * p);
-
-/* Utility */
-
-wchar_t *
-khm_get_realm_from_princ(wchar_t * princ);
-
-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);
-
-int
-khm_krb5_parse_boolean(const char *s, khm_boolean * b);
-
-#endif
+/* + * Copyright (c) 2005 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> + +#if _WIN32_WINNT < 0x0501 +#define KHM_SAVE_WIN32_WINNT _WIN32_WINNT +#undef _WIN32_WINNT +#define _WIN32_WINNT 0x0501 +#endif +#include<ntsecapi.h> +#ifdef KHM_SAVE_WIN32_WINNT +#undef _WIN32_WINNT +#define _WIN32_WINNT KHM_SAVE_WIN32_WINNT +#undef KHM_SAVE_WIN32_WINNT +#endif + +#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 + +#define KRB5_CONF_YES "yes" +#define KRB5_CONF_NO "no" + +typedef struct tag_k5params { + + khm_int32 source_reg; /* flags indicating which fields were + retrieved using the registry */ + khm_int32 source_prof; /* flags indicating which fields were + retrieved using krb5.ini */ + + khm_boolean renewable; + khm_boolean forwardable; + khm_boolean proxiable; + khm_boolean addressless; + + khm_ui_4 publicIP; + + krb5_deltat lifetime; + krb5_deltat lifetime_min; + krb5_deltat lifetime_max; + + krb5_deltat renew_life; + krb5_deltat renew_life_min; + krb5_deltat renew_life_max; + +} k5_params; + +#define K5PARAM_F_RENEW 0x00000001 +#define K5PARAM_F_FORW 0x00000002 +#define K5PARAM_F_PROX 0x00000004 +#define K5PARAM_F_ADDL 0x00000008 +#define K5PARAM_F_PUBIP 0x00000010 +#define K5PARAM_F_LIFE 0x00000020 +#define K5PARAM_F_RLIFE 0x00000040 +#define K5PARAM_F_LIFE_L 0x00000080 +#define K5PARAM_F_LIFE_H 0x00000100 +#define K5PARAM_F_RLIFE_L 0x00000200 +#define K5PARAM_F_RLIFE_H 0x00000400 + +#define K5PARAM_FM_ALL 0x000007ff +#define K5PARAM_FM_PROF 0x0000007f + +/* Credential and principal operations */ + +BOOL +khm_krb5_ms2mit(char * match_princ, + BOOL match_realm, + BOOL save_creds, + khm_handle * ret_ident); + +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_cred(khm_handle cred); + +int +khm_krb5_renew_ident(khm_handle identity); + +long +khm_krb5_list_tickets(krb5_context *krbv5Context); + +long +khm_krb5_copy_ccache_by_name(krb5_context in_ctx, + wchar_t * wscc_dest, + wchar_t * wscc_src); + +long +khm_krb5_get_temp_ccache(krb5_context ctx, + krb5_ccache * cc); + +khm_int32 KHMAPI +khm_krb5_creds_is_equal(khm_handle vcred1, khm_handle vcred2, void * dummy); + + +/* Configuration */ + +BOOL +khm_krb5_get_profile_file(LPSTR confname, UINT szConfname); + +BOOL +khm_krb5_get_temp_profile_file(LPSTR confname, UINT szConfname); + +wchar_t * +khm_krb5_get_default_realm(void); + +long +khm_krb5_set_default_realm(wchar_t * realm); + +wchar_t * +khm_krb5_get_realm_list(void); + +khm_int32 +khm_krb5_get_identity_config(khm_handle ident, + khm_int32 flags, + khm_handle * ret_csp); + +void +khm_krb5_set_identity_flags(khm_handle identity, + khm_int32 flag_mask, + khm_int32 flag_value); + +khm_int32 +khm_krb5_get_identity_flags(khm_handle identity); + +khm_int32 +khm_krb5_set_identity_params(khm_handle ident, const k5_params * p); + +khm_int32 +khm_krb5_get_identity_params(khm_handle ident, k5_params * p); + +/* Utility */ + +wchar_t * +khm_get_realm_from_princ(wchar_t * princ); + +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); + +int +khm_krb5_parse_boolean(const char *s, khm_boolean * b); + +#endif diff --git a/src/windows/identity/plugins/krb5/krb5identpro.c b/src/windows/identity/plugins/krb5/krb5identpro.c index 0072b967d..4d1120f39 100644 --- a/src/windows/identity/plugins/krb5/krb5identpro.c +++ b/src/windows/identity/plugins/krb5/krb5identpro.c @@ -1,1881 +1,1881 @@ -/*
- * Copyright (c) 2005 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;
-
-static
-void
-trim_str(wchar_t * s, khm_size cch) {
- wchar_t * c, * last_ws;
-
- for (c = s; *c && iswspace(*c) && ((khm_size)(c - s)) < cch; c++);
-
- if (((khm_size)(c - s)) >= cch)
- return;
-
- if (c != s && ((khm_size)(c - s)) < cch) {
-#if _MSC_VER >= 1400
- wmemmove_s(s, cch, c, cch - ((khm_size)(c - s)));
-#else
- memmove(s, c, (cch - ((khm_size)(c - s))) * sizeof(wchar_t));
-#endif
- }
-
- last_ws = NULL;
- for (c = s; *c && ((khm_size)(c - s)) < cch; c++) {
- if (!iswspace(*c))
- last_ws = NULL;
- else if (last_ws == NULL)
- last_ws = c;
- }
-
- if (last_ws)
- *last_ws = L'\0';
-}
-
-/* Runs in the UI thread */
-int
-k5_get_realm_from_nc(khui_new_creds * nc,
- wchar_t * buf,
- khm_size cch_buf) {
- k5_new_cred_data * d;
- khm_size s;
-
- d = (k5_new_cred_data *) nc->ident_aux;
- buf[0] = L'\0';
- GetWindowText(d->hw_realm, buf, (int) cch_buf);
- trim_str(buf, cch_buf);
-
- StringCchLength(buf, cch_buf, &s);
-
- return (int) s;
-}
-
-/* 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;
- khm_int32 rv = KHM_ERROR_SUCCESS;
-
- 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));
- trim_str(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);
-
- if (cch >= KCDB_IDENT_MAXCCH_NAME - 3) {
- /* has to allow space for the '@' and at least a single
- character realm, and the NULL terminator. */
- rv = KHM_ERROR_TOO_LONG;
- goto _set_null_ident;
- }
-
- realm = un + cch; /* now points at terminating NULL */
- cch_left = KCDB_IDENT_MAXCCH_NAME - cch;
-
- *realm++ = L'@';
- *realm = L'\0';
- cch_left--;
-
- cch = GetWindowTextLength(d->hw_realm);
- if (cch == 0 || cch >= cch_left) {
- rv = KHM_ERROR_INVALID_NAME;
- goto _set_null_ident;
- }
-
- GetWindowText(d->hw_realm, realm, (int) cch_left);
- trim_str(realm, cch_left);
-
- _set_ident:
- if (KHM_FAILED(rv = 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_new_creds_by_type * nct = NULL;
- wchar_t cmsg[256];
-
- khui_cw_find_type(nc, credtype_id_krb5, &nct);
- if (nct && nct->hwnd_panel) {
-
- switch(rv) {
- case KHM_ERROR_TOO_LONG:
- LoadString(hResModule, IDS_NCERR_IDENT_TOO_LONG,
- cmsg, ARRAYLENGTH(cmsg));
- break;
-
- case KHM_ERROR_INVALID_NAME:
- LoadString(hResModule, IDS_NCERR_IDENT_INVALID,
- cmsg, ARRAYLENGTH(cmsg));
- break;
-
- default:
- LoadString(hResModule, IDS_NCERR_IDENT_UNKNOWN,
- cmsg, ARRAYLENGTH(cmsg));
- }
-
- SendMessage(nct->hwnd_panel,
- KHUI_WM_NC_NOTIFY,
- MAKEWPARAM(0, K5_SET_CRED_MSG),
- (LPARAM) cmsg);
- }
-
- khui_cw_set_primary_id(nc, NULL);
- }
- return;
-}
-
-/* runs in the UI thread */
-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;
- int idx;
-
- 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));
- trim_str(un, ARRAYLENGTH(un));
-
- un_realm = khm_get_realm_from_princ(un);
-
- if (un_realm == NULL) {
- EnableWindow(d->hw_realm, TRUE);
- return FALSE;
- }
-
- if (ctrl_id_src == K5_NCID_UN) {
-
- idx = (int)SendMessage(d->hw_realm,
- CB_FINDSTRINGEXACT,
- (WPARAM) -1,
- (LPARAM) un_realm);
-
- if (idx != CB_ERR) {
- wchar_t srealm[KCDB_IDENT_MAXCCH_NAME];
-
- cch = SendMessage(d->hw_realm,
- CB_GETLBTEXTLEN,
- (WPARAM) idx,
- 0);
-
-#ifdef DEBUG
- assert(cch < ARRAYLENGTH(srealm) - 1);
-#endif
- SendMessage(d->hw_realm,
- CB_GETLBTEXT,
- (WPARAM) idx,
- (LPARAM) srealm);
-
- if (!_wcsicmp(srealm, un_realm) && wcscmp(srealm, un_realm)) {
- /* differ only by case */
-
- StringCchCopy(un_realm, ARRAYLENGTH(un) - (un_realm - un),
- srealm);
-
- SetWindowText(d->hw_username, un);
- }
- }
-
- SendMessage(d->hw_realm,
- CB_SELECTSTRING,
- (WPARAM) -1,
- (LPARAM) un_realm);
-
- SetWindowText(d->hw_realm,
- un_realm);
-
- if (GetFocus() == d->hw_realm) {
- HWND hw_next = GetNextDlgTabItem(nc->hwnd, d->hw_realm,
- FALSE);
- if (hw_next)
- SetFocus(hw_next);
- }
-
- EnableWindow(d->hw_realm, FALSE);
-
- 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));
- trim_str(realm, ARRAYLENGTH(realm));
-
- idx = (int)SendMessage(d->hw_realm,
- CB_FINDSTRINGEXACT,
- (WPARAM) -1,
- (LPARAM) realm);
-
- if (idx != CB_ERR) {
- wchar_t srealm[KCDB_IDENT_MAXCCH_NAME];
-
- SendMessage(d->hw_realm,
- CB_GETLBTEXT,
- (WPARAM) idx,
- (LPARAM) srealm);
-
- if (!_wcsicmp(srealm, realm) && wcscmp(srealm, realm)) {
- StringCbCopy(realm, sizeof(realm), srealm);
-
- SetWindowText(d->hw_realm, srealm);
- }
- }
-
- 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 = PMALLOC(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 | WS_VSCROLL,
- 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 | WS_VSCROLL,
- 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 || cb_ms <= sizeof(wchar_t) * 2)
- goto _add_lru_realms;
-
- ms = PMALLOC(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) {
- PFREE(ms);
- ms = PMALLOC(cb);
- assert(ms);
- cb_ms = cb;
- }
- } else {
- ms = PMALLOC(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:
-
- {
- khm_int32 inc_realms = 0;
-
- if (KHM_FAILED(khc_read_int32(csp_params,
- L"UseFullRealmList",
- &inc_realms)) ||
- !inc_realms)
- goto _done_adding_all_realms;
- }
-
- if(ms)
- PFREE(ms);
-
- ms = khm_krb5_get_realm_list();
- if(ms) {
- 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_all_realms:
-
- /* 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)
- PFREE(defrealm);
-
- if (ms)
- PFREE(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. */
- PFREE(d);
- }
- return TRUE;
- }
- return FALSE;
-}
-
-static khm_int32
-k5_ident_validate_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;
- wchar_t * atsign;
-
- 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);
-
- /* krb5_parse_name() accepts principal names with no realm or an
- empty realm. We don't. */
- atsign = wcschr(nx->name_src, L'@');
- if (atsign == NULL || atsign[1] == L'\0') {
- nx->result = KHM_ERROR_INVALID_NAME;
- } else {
- nx->result = KHM_ERROR_SUCCESS;
- }
-
- return KHM_ERROR_SUCCESS;
-}
-
-static void
-k5_update_last_default_identity(khm_handle ident) {
- wchar_t idname[KCDB_IDENT_MAXCCH_NAME];
- khm_size cb;
-
- cb = sizeof(idname);
- if (KHM_FAILED(kcdb_identity_get_name(ident, idname, &cb)))
- return;
-
- assert(csp_params);
-
- khc_write_string(csp_params, L"LastDefaultIdent", idname);
-}
-
-static khm_int32
-k5_ident_set_default_int(khm_handle def_ident) {
- wchar_t id_ccname[KRB5_MAXCCH_CCNAME];
- khm_size cb;
- DWORD dw;
- LONG l;
- HKEY hk_ccname;
- DWORD dwType;
- DWORD dwSize;
- wchar_t reg_ccname[KRB5_MAXCCH_CCNAME];
-
-#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))) {
- khm_handle csp_ident = NULL;
- khm_handle csp_k5 = NULL;
-
- _reportf(L"The specified identity does not have the Krb5CCName property");
-
- cb = sizeof(id_ccname);
- if (KHM_SUCCEEDED(kcdb_identity_get_config(def_ident, 0, &csp_ident)) &&
- KHM_SUCCEEDED(khc_open_space(csp_ident, CSNAME_KRB5CRED, 0, &csp_k5)) &&
- KHM_SUCCEEDED(khc_read_string(csp_k5, L"DefaultCCName",
- id_ccname, &cb))) {
-
- _reportf(L"Found CC name in configuration [%s]", id_ccname);
- } else {
- /* last resort, use the name of the identity as the cc
- name */
- cb = sizeof(id_ccname);
- if (KHM_FAILED(kcdb_identity_get_name(def_ident, id_ccname, &cb))) {
- _reportf(L"Can't use name of identity as CCName");
- _end_task();
-
- id_ccname[0] = L'\0';
- }
- }
-
- if (csp_k5)
- khc_close_space(csp_k5);
- if (csp_ident)
- khc_close_space(csp_ident);
-
- if (id_ccname[0] == L'\0')
- return KHM_ERROR_INVALID_PARAM;
- }
-
- khm_krb5_canon_cc_name(id_ccname, sizeof(id_ccname));
-
- _reportf(L"Found Krb5CCName property : %s", id_ccname);
-
- StringCbLength(id_ccname, sizeof(id_ccname), &cb);
- cb += sizeof(wchar_t);
-
- _reportf(L"Setting default CC name in the registry");
-
- 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) {
- _reportf(L"Can't create registry key : %d", l);
- _end_task();
- 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) {
- _reportf(L"Successfully set the default ccache");
- k5_update_last_default_identity(def_ident);
- return KHM_ERROR_SUCCESS;
- } else {
- _reportf(L"Can't set the registry value : %d", l);
- return KHM_ERROR_UNKNOWN;
- }
-}
-
-static khm_int32
-k5_ident_set_default(khm_int32 msg_type,
- khm_int32 msg_subtype,
- khm_ui_4 uparam,
- void * vparam) {
-
- /*
- Currently, setting the default identity simply sets the
- "ccname" registry value at "Software\MIT\kerberos5".
- */
-
- if (uparam) {
- /* an identity is being made default */
- khm_handle def_ident = (khm_handle) vparam;
- khm_int32 rv;
-
-#ifdef DEBUG
- assert(def_ident != NULL);
-#endif
-
- {
- wchar_t idname[KCDB_IDENT_MAXCCH_NAME];
- khm_size cb;
-
- cb = sizeof(idname);
- kcdb_identity_get_name(def_ident, idname, &cb);
-
- _begin_task(0);
- _report_cs1(KHERR_DEBUG_1, L"Setting default identity [%1!s!]", _cstr(idname));
- _describe();
- }
-
- rv = k5_ident_set_default_int(def_ident);
-
- _end_task();
-
- return rv;
-
- } 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;
-
- /* if there is a default identity already, we assume we don't need
- to check this one. */
-
- khm_handle def_ident;
-
- if (KHM_SUCCEEDED(kcdb_identity_get_default(&def_ident))) {
- kcdb_identity_release(def_ident);
-
- return KHM_ERROR_SUCCESS;
- }
-
- 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;
-}
-
-struct k5_ident_update_data {
- khm_handle identity;
-
- FILETIME ft_expire; /* expiration */
- FILETIME ft_issue; /* issue */
- FILETIME ft_rexpire; /* renew expiration */
- wchar_t ccname[KRB5_MAXCCH_CCNAME];
- khm_int32 k5_flags;
-};
-
-/* The logic here has to reflect the logic in khm_krb5_list_tickets().
- We use this to handle an identity update request because some other
- plug-in or maybe NetIDMgr itself is about to do something
- important(tm) with the identity and needs to make sure that the
- properties of the identity are up-to-date. */
-static khm_int32 KHMAPI
-k5_ident_update_apply_proc(khm_handle cred,
- void * rock) {
- struct k5_ident_update_data * d = (struct k5_ident_update_data *) rock;
- khm_handle ident = NULL;
- khm_int32 t;
- khm_int32 flags;
- FILETIME t_cexpire;
- FILETIME 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 (!kcdb_identity_is_equal(ident,d->identity))
-
- goto _cleanup;
-
- if (KHM_FAILED(kcdb_cred_get_flags(cred, &flags)))
-
- flags = 0;
-
- if (flags & KCDB_CRED_FLAG_INITIAL) {
- cb = sizeof(t_cexpire);
- if (KHM_SUCCEEDED(kcdb_cred_get_attr(cred,
- KCDB_ATTR_EXPIRE,
- NULL,
- &t_cexpire,
- &cb))) {
- if ((d->ft_expire.dwLowDateTime == 0 &&
- d->ft_expire.dwHighDateTime == 0) ||
- CompareFileTime(&t_cexpire, &d->ft_expire) > 0) {
- goto update_identity;
- }
- }
- }
-
- goto _cleanup;
-
- update_identity:
-
- d->ft_expire = t_cexpire;
-
- cb = sizeof(d->ccname);
- if (KHM_FAILED(kcdb_cred_get_attr(cred, KCDB_ATTR_LOCATION, NULL, d->ccname, &cb))) {
- d->ccname[0] = L'\0';
- }
-
- cb = sizeof(d->k5_flags);
- if (KHM_FAILED(kcdb_cred_get_attr(cred, attr_id_krb5_flags, NULL,
- &d->k5_flags, &cb))) {
- d->k5_flags = 0;
- }
-
- cb = sizeof(d->ft_issue);
- if (KHM_FAILED(kcdb_cred_get_attr(cred, KCDB_ATTR_ISSUE, NULL, &d->ft_issue, &cb))) {
- ZeroMemory(&d->ft_issue, sizeof(d->ft_issue));
- }
-
- cb = sizeof(t_rexpire);
- if ((d->k5_flags & TKT_FLG_RENEWABLE) &&
- KHM_SUCCEEDED(kcdb_cred_get_attr(cred,
- KCDB_ATTR_RENEW_EXPIRE,
- NULL,
- &t_rexpire,
- &cb))) {
- d->ft_rexpire = t_rexpire;
- } else {
- ZeroMemory(&d->ft_rexpire, sizeof(d->ft_rexpire));
- }
-
- _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) {
-
-#if 0
- struct k5_ident_update_data d;
-#endif
- khm_handle ident;
- khm_handle tident;
- krb5_ccache cc = NULL;
- char * ccname;
- krb5_error_code code;
- khm_size cb;
- wchar_t wid_ccname[MAX_PATH];
- wchar_t w_ccname[MAX_PATH];
-
- ident = (khm_handle) vparam;
- if (ident == NULL)
- return KHM_ERROR_SUCCESS;
-
-#if 0
- /* we are going to skip doing this here since
- khm_krb5_list_tickets() performs this function for us each time
- we enumerate tickets. Since it also gets run each time our
- list of tickets changes and since we are basing this operation
- on existing tickets, we are unlikely to find anything new
- here. */
- ZeroMemory(&d, sizeof(d));
- d.identity = ident;
-
- kcdb_credset_apply(NULL,
- k5_ident_update_apply_proc,
- (void *) &d);
-
- if (d.ft_expire.dwLowDateTime != 0 ||
- d.ft_expire.dwHighDateTime != 0) {
-
- /* we found a TGT */
-
- kcdb_identity_set_attr(ident, KCDB_ATTR_EXPIRE,
- &d.ft_expire, sizeof(d.ft_expire));
- if (d.ft_issue.dwLowDateTime != 0 ||
- d.ft_issue.dwHighDateTime != 0)
- kcdb_identity_set_attr(ident, KCDB_ATTR_ISSUE,
- &d.ft_issue, sizeof(d.ft_issue));
- else
- kcdb_identity_set_attr(ident, KCDB_ATTR_ISSUE, NULL, 0);
-
- if (d.ft_rexpire.dwLowDateTime != 0 ||
- d.ft_rexpire.dwHighDateTime != 0)
- kcdb_identity_set_attr(ident, KCDB_ATTR_RENEW_EXPIRE,
- &d.ft_rexpire, sizeof(d.ft_rexpire));
- else
- kcdb_identity_set_attr(ident, KCDB_ATTR_RENEW_EXPIRE, NULL, 0);
-
- kcdb_identity_set_attr(ident, attr_id_krb5_flags,
- &d.k5_flags, sizeof(d.k5_flags));
-
- if (d.ccname[0])
- kcdb_identity_set_attr(ident, attr_id_krb5_ccname,
- d.ccname, KCDB_CBSIZE_AUTO);
- else
- kcdb_identity_set_attr(ident, attr_id_krb5_ccname, NULL, 0);
-
- } else {
- /* Clear out the attributes. We don't have any information
- about this identity */
- kcdb_identity_set_attr(ident, KCDB_ATTR_EXPIRE, NULL, 0);
- kcdb_identity_set_attr(ident, KCDB_ATTR_ISSUE, NULL, 0);
- kcdb_identity_set_attr(ident, KCDB_ATTR_RENEW_EXPIRE, NULL, 0);
- kcdb_identity_set_attr(ident, attr_id_krb5_flags, NULL, 0);
- kcdb_identity_set_attr(ident, attr_id_krb5_ccname, NULL, 0);
- }
-#endif
-
- if (KHM_SUCCEEDED(kcdb_identity_get_default(&tident))) {
- kcdb_identity_release(tident);
- goto _iu_cleanup;
- }
-
- cb = sizeof(wid_ccname);
- if (KHM_FAILED(kcdb_identity_get_attr(ident,
- attr_id_krb5_ccname,
- NULL,
- wid_ccname,
- &cb)))
- goto _iu_cleanup;
-
- if(k5_identpro_ctx == NULL)
- goto _iu_cleanup;
-
- code = pkrb5_cc_default(k5_identpro_ctx, &cc);
- if (code)
- goto _iu_cleanup;
-
- ccname = pkrb5_cc_get_name(k5_identpro_ctx, cc);
- if (ccname == NULL)
- goto _iu_cleanup;
-
- AnsiStrToUnicode(w_ccname, sizeof(w_ccname), ccname);
-
- khm_krb5_canon_cc_name(w_ccname, sizeof(w_ccname));
- khm_krb5_canon_cc_name(wid_ccname, sizeof(wid_ccname));
-
- if (!_wcsicmp(w_ccname, wid_ccname))
- kcdb_identity_set_default_int(ident);
-
- _iu_cleanup:
- if (cc && k5_identpro_ctx)
- pkrb5_cc_close(k5_identpro_ctx, cc);
-
- return KHM_ERROR_SUCCESS;
-}
-
-static khm_boolean
-k5_refresh_default_identity(krb5_context ctx) {
- /* 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];
- char * ccname = NULL;
- khm_handle ident = NULL;
- khm_boolean found_default = FALSE;
-
- assert(ctx != NULL);
-
- _begin_task(0);
- _report_cs0(KHERR_DEBUG_1, L"Refreshing default identity");
- _describe();
-
- code = pkrb5_cc_default(ctx, &cc);
- if (code) {
- _reportf(L"Can't open default ccache. code=%d", code);
- goto _nc_cleanup;
- }
-
- code = pkrb5_cc_get_principal(ctx, cc, &princ);
- if (code) {
- /* try to determine the identity from the ccache name */
- ccname = pkrb5_cc_get_name(ctx, cc);
-
- if (ccname) {
- char * namepart = strchr(ccname, ':');
-
- _reportf(L"CC name is [%S]", ccname);
-
- if (namepart == NULL)
- namepart = ccname;
- else
- namepart++;
-
- _reportf(L"Checking if [%S] is a valid identity name", namepart);
-
- AnsiStrToUnicode(princ_nameW, sizeof(princ_nameW), namepart);
- if (kcdb_identity_is_valid_name(princ_nameW)) {
- kcdb_identity_create(princ_nameW, KCDB_IDENT_FLAG_CREATE, &ident);
- if (ident) {
- _reportf(L"Setting [%S] as the default identity", namepart);
- kcdb_identity_set_default_int(ident);
- found_default = TRUE;
- }
- }
- } else {
- _reportf(L"Can't determine ccache name");
- }
-
- goto _nc_cleanup;
- }
-
- code = pkrb5_unparse_name(ctx, princ, &princ_nameA);
- if (code)
- goto _nc_cleanup;
-
- AnsiStrToUnicode(princ_nameW, sizeof(princ_nameW), princ_nameA);
-
- _reportf(L"Found principal [%s]", princ_nameW);
-
- if (KHM_FAILED(kcdb_identity_create(princ_nameW, KCDB_IDENT_FLAG_CREATE, &ident))) {
- _reportf(L"Failed to create identity");
- goto _nc_cleanup;
- }
-
- _reportf(L"Setting default identity to [%s]", princ_nameW);
- kcdb_identity_set_default_int(ident);
-
- found_default = TRUE;
-
- _nc_cleanup:
-
- _end_task();
-
- if (princ_nameA)
- pkrb5_free_unparsed_name(ctx, princ_nameA);
-
- if (princ)
- pkrb5_free_principal(ctx, princ);
-
- if (cc)
- pkrb5_cc_close(ctx, cc);
-
- if (ident)
- kcdb_identity_release(ident);
-
- return found_default;
-}
-
-static khm_int32
-k5_ident_init(khm_int32 msg_type,
- khm_int32 msg_subtype,
- khm_ui_4 uparam,
- void * vparam) {
-
- khm_boolean found_default;
- khm_handle ident;
-
- found_default = k5_refresh_default_identity(k5_identpro_ctx);
-
- if (!found_default) {
- wchar_t widname[KCDB_IDENT_MAXCCH_NAME];
- khm_size cb;
-
- cb = sizeof(widname);
-
- assert(csp_params);
-
- if (KHM_SUCCEEDED(khc_read_string(csp_params, L"LastDefaultIdent",
- widname, &cb))) {
- ident = NULL;
- kcdb_identity_create(widname, KCDB_IDENT_FLAG_CREATE, &ident);
- if (ident) {
- kcdb_identity_set_default_int(ident);
- kcdb_identity_release(ident);
-
- found_default = TRUE;
- }
- }
- }
-
- if (!found_default) {
-
- /* There was no default ccache and we don't have a
- "LastDefaultIdent" value. Next we see if there are any
- identities that have credentials which have a Krb5CCName
- property (i.e. an identity that has a Kerberos 5 TGT), and
- make it the default.
-
- Note that since the Krb5Ident plug-in has a dependency on
- Krb5Cred, by the time this code runs, we already have a
- listing of Kerberos 5 tickets and identities. */
-
- wchar_t * idlist = NULL;
- wchar_t * thisid;
- khm_size cb = 0;
- khm_size n_idents = 0;
- khm_int32 rv;
- wchar_t ccname[KRB5_MAXCCH_CCNAME];
- FILETIME ft_expire;
- FILETIME ft_now;
- FILETIME ft_threshold;
- BOOL match_all = FALSE;
-
- rv = kcdb_identity_enum(0, 0, NULL, &cb, &n_idents);
-
- TimetToFileTimeInterval(5 * 60, &ft_threshold);
- GetSystemTimeAsFileTime(&ft_now);
- ft_now = FtAdd(&ft_now, &ft_threshold);
-
- while (rv == KHM_ERROR_TOO_LONG && n_idents > 0) {
- if (idlist) {
- PFREE(idlist);
- idlist = NULL;
- }
-
- idlist = PMALLOC(cb);
-
- if (idlist == NULL)
- break;
-
- rv = kcdb_identity_enum(0, 0, idlist, &cb, &n_idents);
- }
-
- if (KHM_SUCCEEDED(rv)) {
-
- /* first we try to find an identity that has a valid TGT.
- If that fails, then we try to find an identity with
- *any* TGT. */
-
- try_again:
-
- for (thisid = idlist;
- thisid && *thisid && !found_default;
- thisid = multi_string_next(thisid)) {
-
- if (KHM_SUCCEEDED(kcdb_identity_create(thisid, 0, &ident))) {
- khm_size cb_ft = sizeof(FILETIME);
- cb = sizeof(ccname);
-
- if (KHM_SUCCEEDED(kcdb_identity_get_attr(ident, attr_id_krb5_ccname,
- NULL, ccname, &cb)) &&
- (match_all ||
- (KHM_SUCCEEDED(kcdb_identity_get_attr(ident, KCDB_ATTR_EXPIRE,
- NULL, &ft_expire, &cb_ft)) &&
- CompareFileTime(&ft_expire, &ft_now) > 0))) {
-
- /* found one */
- k5_ident_set_default_int(ident);
- kcdb_identity_set_default_int(ident);
- found_default = TRUE;
-
- }
-
- kcdb_identity_release(ident);
- ident = NULL;
- }
- }
-
- if (!found_default && !match_all) {
- match_all = TRUE;
- goto try_again;
- }
- }
-
- if (idlist) {
- PFREE(idlist);
- idlist = NULL;
- }
- }
-
- 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;
-}
-
-/* forward dcl */
-khm_int32 KHMAPI
-k5_ident_name_comp_func(const void * dl, khm_size cb_dl,
- const void * dr, khm_size cb_dr);
-
-static khm_int32
-k5_ident_compare_name(khm_int32 msg_type,
- khm_int32 msg_subtype,
- khm_ui_4 uparam,
- void * vparam) {
- kcdb_ident_name_xfer *px;
-
- px = (kcdb_ident_name_xfer *) vparam;
-
- /* note that k5_ident_name_comp_func() ignores the size
- specifiers. So we can just pass in 0's. */
- px->result = k5_ident_name_comp_func(px->name_src, 0,
- px->name_alt, 0);
-
- 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_validate_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:
- return k5_ident_compare_name(msg_type,
- msg_subtype,
- uparam,
- vparam);
-
- 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;
-}
-
-/* note that we are ignoring the size specifiers. We can do that
- because we are guaranteed that dl and dr point to NULL terminated
- unicode strings when used with credential data buffers. We also
- use the fact that we are ignoring the size specifiers when we call
- this function from k5_ident_compare_name() to avoid calculating the
- length of the string. */
-khm_int32 KHMAPI
-k5_ident_name_comp_func(const void * dl, khm_size cb_dl,
- const void * dr, khm_size cb_dr) {
- wchar_t * idl = (wchar_t *) dl;
- wchar_t * idr = (wchar_t *) dr;
- wchar_t * rl;
- wchar_t * rr;
- khm_int32 r;
-
- rl = khm_get_realm_from_princ(idl);
- rr = khm_get_realm_from_princ(idr);
-
- if (rl == NULL && rr == NULL)
- return wcscmp(idl, idr);
- else if (rl == NULL)
- return 1;
- else if (rr == NULL)
- return -1;
-
- r = wcscmp(rl, rr);
- if (r == 0)
- return wcscmp(idl, idr);
- else
- return r;
-}
-
-
-/* Identity change notification thread */
-
-HANDLE h_ccname_exit_event;
-HANDLE h_ccname_thread;
-
-DWORD WINAPI k5_ccname_monitor_thread(LPVOID lpParameter) {
- krb5_context ctx = 0;
-
- HKEY hk_ccname;
- HANDLE h_notify;
- HANDLE h_waits[2];
-
- khm_int32 rv = KHM_ERROR_SUCCESS;
- DWORD dwType;
- DWORD dwSize;
- DWORD dwDisp;
- wchar_t reg_ccname[KRB5_MAXCCH_CCNAME];
- LONG l;
-
- PDESCTHREAD(L"Krb5 CCName Monitor", L"Krb5");
-
- 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,
- &dwDisp);
-
- if (l != ERROR_SUCCESS) {
- rv = KHM_ERROR_UNKNOWN;
- goto _exit;
- }
-
- dwSize = sizeof(reg_ccname);
-
- l = RegQueryValueEx(hk_ccname,
- L"ccname",
- NULL,
- &dwType,
- (LPBYTE) reg_ccname,
- &dwSize);
-
- if (l != ERROR_SUCCESS ||
- dwType != REG_SZ) {
-
- reg_ccname[0] = L'\0';
- }
-
- l = pkrb5_init_context(&ctx);
-
- if (l)
- goto _exit_0;
-
- h_notify = CreateEvent(NULL, FALSE, FALSE, L"Local\\Krb5CCNameChangeNotifier");
-
- if (h_notify == NULL)
- goto _exit_0;
-
- /* begin wait loop */
-
- h_waits[0] = h_ccname_exit_event;
- h_waits[1] = h_notify;
-
- do {
- DWORD dwrv;
-
- l = RegNotifyChangeKeyValue(hk_ccname, FALSE,
- REG_NOTIFY_CHANGE_LAST_SET,
- h_notify, TRUE);
-
- if (l != ERROR_SUCCESS) {
- rv = KHM_ERROR_UNKNOWN;
- break;
- }
-
- dwrv = WaitForMultipleObjects(2, h_waits, FALSE, INFINITE);
-
- if (dwrv == WAIT_OBJECT_0) {
- /* exit! */
- break;
-
- } else if (dwrv == WAIT_OBJECT_0 + 1) {
- /* change notify! */
- wchar_t new_ccname[KRB5_MAXCCH_CCNAME];
-
- dwSize = sizeof(new_ccname);
-
- l = RegQueryValueEx(hk_ccname,
- L"ccname",
- NULL,
- &dwType,
- (LPBYTE) new_ccname,
- &dwSize);
-
- if (l != ERROR_SUCCESS ||
- dwType != REG_SZ) {
- new_ccname[0] = L'\0';
- }
-
- if (_wcsicmp(new_ccname, reg_ccname)) {
- k5_refresh_default_identity(ctx);
- StringCbCopy(reg_ccname, sizeof(reg_ccname), new_ccname);
- }
-
- } else {
- /* something went wrong */
- rv = KHM_ERROR_UNKNOWN;
- break;
- }
-
- } while (TRUE);
-
- CloseHandle(h_notify);
-
- _exit_0:
-
- RegCloseKey(hk_ccname);
-
- if (ctx)
- pkrb5_free_context(ctx);
-
- _exit:
- ExitThread(rv);
-
- /* not reached */
- return rv;
-}
-
-khm_int32
-k5_msg_system_idpro(khm_int32 msg_type, khm_int32 msg_subtype,
- khm_ui_4 uparam, void * vparam) {
-
- switch(msg_subtype) {
- case KMSG_SYSTEM_INIT:
- {
-
- pkrb5_init_context(&k5_identpro_ctx);
- kcdb_identity_set_type(credtype_id_krb5);
-
- if (KHM_FAILED(kcdb_type_get_id(TYPENAME_KRB5_PRINC,
- &type_id_krb5_princ))) {
- kcdb_type dt;
- kcdb_type * pstr;
-
- kcdb_type_get_info(KCDB_TYPE_STRING, &pstr);
-
- ZeroMemory(&dt, sizeof(dt));
- dt.name = TYPENAME_KRB5_PRINC;
- dt.id = KCDB_TYPE_INVALID;
- dt.flags = KCDB_TYPE_FLAG_CB_AUTO;
- dt.cb_min = pstr->cb_min;
- dt.cb_max = pstr->cb_max;
- dt.toString = pstr->toString;
- dt.isValid = pstr->isValid;
- dt.comp = k5_ident_name_comp_func;
- dt.dup = pstr->dup;
-
- kcdb_type_register(&dt, &type_id_krb5_princ);
-
- type_regd_krb5_princ = TRUE;
-
- kcdb_type_release_info(pstr);
- }
-
- if (type_id_krb5_princ != -1) {
- kcdb_attrib * attr;
-
- kcdb_attrib_get_info(KCDB_ATTR_ID_NAME, &attr);
-
- attr->type = type_id_krb5_princ;
-
- kcdb_attrib_release_info(attr);
- }
-
- h_ccname_exit_event = CreateEvent(NULL, FALSE, FALSE, NULL);
- if (h_ccname_exit_event) {
- h_ccname_thread = CreateThread(NULL,
- 200 * 1024,
- k5_ccname_monitor_thread,
- NULL,
- 0,
- NULL);
- } else {
- h_ccname_thread = NULL;
- }
- }
- break;
-
- case KMSG_SYSTEM_EXIT:
- {
-
- if (h_ccname_thread) {
- SetEvent(h_ccname_exit_event);
- WaitForSingleObject(h_ccname_thread, INFINITE);
- CloseHandle(h_ccname_thread);
- CloseHandle(h_ccname_exit_event);
-
- h_ccname_exit_event = NULL;
- h_ccname_thread = NULL;
- }
-
- if (k5_identpro_ctx) {
- pkrb5_free_context(k5_identpro_ctx);
- k5_identpro_ctx = NULL;
- }
-
- if (type_id_krb5_princ != -1) {
- kcdb_attrib * attr;
-
- kcdb_attrib_get_info(KCDB_ATTR_ID_NAME, &attr);
-
- attr->type = KCDB_TYPE_STRING;
-
- kcdb_attrib_release_info(attr);
- }
-
- /* allow a brief moment for any stale references to die */
- Sleep(100);
-
- if (type_regd_krb5_princ) {
- kcdb_type_unregister(type_id_krb5_princ);
- }
- }
- break;
- }
-
- return KHM_ERROR_SUCCESS;
-}
-
-khm_int32 KHMAPI
-k5_ident_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_idpro(msg_type, msg_subtype, uparam, vparam);
-
- case KMSG_IDENT:
- return k5_msg_ident(msg_type, msg_subtype, uparam, vparam);
- }
-
- return KHM_ERROR_SUCCESS;
-}
+/* + * Copyright (c) 2005 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; + +static +void +trim_str(wchar_t * s, khm_size cch) { + wchar_t * c, * last_ws; + + for (c = s; *c && iswspace(*c) && ((khm_size)(c - s)) < cch; c++); + + if (((khm_size)(c - s)) >= cch) + return; + + if (c != s && ((khm_size)(c - s)) < cch) { +#if _MSC_VER >= 1400 + wmemmove_s(s, cch, c, cch - ((khm_size)(c - s))); +#else + memmove(s, c, (cch - ((khm_size)(c - s))) * sizeof(wchar_t)); +#endif + } + + last_ws = NULL; + for (c = s; *c && ((khm_size)(c - s)) < cch; c++) { + if (!iswspace(*c)) + last_ws = NULL; + else if (last_ws == NULL) + last_ws = c; + } + + if (last_ws) + *last_ws = L'\0'; +} + +/* Runs in the UI thread */ +int +k5_get_realm_from_nc(khui_new_creds * nc, + wchar_t * buf, + khm_size cch_buf) { + k5_new_cred_data * d; + khm_size s; + + d = (k5_new_cred_data *) nc->ident_aux; + buf[0] = L'\0'; + GetWindowText(d->hw_realm, buf, (int) cch_buf); + trim_str(buf, cch_buf); + + StringCchLength(buf, cch_buf, &s); + + return (int) s; +} + +/* 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; + khm_int32 rv = KHM_ERROR_SUCCESS; + + 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)); + trim_str(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); + + if (cch >= KCDB_IDENT_MAXCCH_NAME - 3) { + /* has to allow space for the '@' and at least a single + character realm, and the NULL terminator. */ + rv = KHM_ERROR_TOO_LONG; + goto _set_null_ident; + } + + realm = un + cch; /* now points at terminating NULL */ + cch_left = KCDB_IDENT_MAXCCH_NAME - cch; + + *realm++ = L'@'; + *realm = L'\0'; + cch_left--; + + cch = GetWindowTextLength(d->hw_realm); + if (cch == 0 || cch >= cch_left) { + rv = KHM_ERROR_INVALID_NAME; + goto _set_null_ident; + } + + GetWindowText(d->hw_realm, realm, (int) cch_left); + trim_str(realm, cch_left); + + _set_ident: + if (KHM_FAILED(rv = 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_new_creds_by_type * nct = NULL; + wchar_t cmsg[256]; + + khui_cw_find_type(nc, credtype_id_krb5, &nct); + if (nct && nct->hwnd_panel) { + + switch(rv) { + case KHM_ERROR_TOO_LONG: + LoadString(hResModule, IDS_NCERR_IDENT_TOO_LONG, + cmsg, ARRAYLENGTH(cmsg)); + break; + + case KHM_ERROR_INVALID_NAME: + LoadString(hResModule, IDS_NCERR_IDENT_INVALID, + cmsg, ARRAYLENGTH(cmsg)); + break; + + default: + LoadString(hResModule, IDS_NCERR_IDENT_UNKNOWN, + cmsg, ARRAYLENGTH(cmsg)); + } + + SendMessage(nct->hwnd_panel, + KHUI_WM_NC_NOTIFY, + MAKEWPARAM(0, K5_SET_CRED_MSG), + (LPARAM) cmsg); + } + + khui_cw_set_primary_id(nc, NULL); + } + return; +} + +/* runs in the UI thread */ +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; + int idx; + + 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)); + trim_str(un, ARRAYLENGTH(un)); + + un_realm = khm_get_realm_from_princ(un); + + if (un_realm == NULL) { + EnableWindow(d->hw_realm, TRUE); + return FALSE; + } + + if (ctrl_id_src == K5_NCID_UN) { + + idx = (int)SendMessage(d->hw_realm, + CB_FINDSTRINGEXACT, + (WPARAM) -1, + (LPARAM) un_realm); + + if (idx != CB_ERR) { + wchar_t srealm[KCDB_IDENT_MAXCCH_NAME]; + + cch = SendMessage(d->hw_realm, + CB_GETLBTEXTLEN, + (WPARAM) idx, + 0); + +#ifdef DEBUG + assert(cch < ARRAYLENGTH(srealm) - 1); +#endif + SendMessage(d->hw_realm, + CB_GETLBTEXT, + (WPARAM) idx, + (LPARAM) srealm); + + if (!_wcsicmp(srealm, un_realm) && wcscmp(srealm, un_realm)) { + /* differ only by case */ + + StringCchCopy(un_realm, ARRAYLENGTH(un) - (un_realm - un), + srealm); + + SetWindowText(d->hw_username, un); + } + } + + SendMessage(d->hw_realm, + CB_SELECTSTRING, + (WPARAM) -1, + (LPARAM) un_realm); + + SetWindowText(d->hw_realm, + un_realm); + + if (GetFocus() == d->hw_realm) { + HWND hw_next = GetNextDlgTabItem(nc->hwnd, d->hw_realm, + FALSE); + if (hw_next) + SetFocus(hw_next); + } + + EnableWindow(d->hw_realm, FALSE); + + 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)); + trim_str(realm, ARRAYLENGTH(realm)); + + idx = (int)SendMessage(d->hw_realm, + CB_FINDSTRINGEXACT, + (WPARAM) -1, + (LPARAM) realm); + + if (idx != CB_ERR) { + wchar_t srealm[KCDB_IDENT_MAXCCH_NAME]; + + SendMessage(d->hw_realm, + CB_GETLBTEXT, + (WPARAM) idx, + (LPARAM) srealm); + + if (!_wcsicmp(srealm, realm) && wcscmp(srealm, realm)) { + StringCbCopy(realm, sizeof(realm), srealm); + + SetWindowText(d->hw_realm, srealm); + } + } + + 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 = PMALLOC(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 | WS_VSCROLL, + 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 | WS_VSCROLL, + 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 || cb_ms <= sizeof(wchar_t) * 2) + goto _add_lru_realms; + + ms = PMALLOC(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) { + PFREE(ms); + ms = PMALLOC(cb); + assert(ms); + cb_ms = cb; + } + } else { + ms = PMALLOC(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: + + { + khm_int32 inc_realms = 0; + + if (KHM_FAILED(khc_read_int32(csp_params, + L"UseFullRealmList", + &inc_realms)) || + !inc_realms) + goto _done_adding_all_realms; + } + + if(ms) + PFREE(ms); + + ms = khm_krb5_get_realm_list(); + if(ms) { + 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_all_realms: + + /* 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) + PFREE(defrealm); + + if (ms) + PFREE(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. */ + PFREE(d); + } + return TRUE; + } + return FALSE; +} + +static khm_int32 +k5_ident_validate_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; + wchar_t * atsign; + + 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); + + /* krb5_parse_name() accepts principal names with no realm or an + empty realm. We don't. */ + atsign = wcschr(nx->name_src, L'@'); + if (atsign == NULL || atsign[1] == L'\0') { + nx->result = KHM_ERROR_INVALID_NAME; + } else { + nx->result = KHM_ERROR_SUCCESS; + } + + return KHM_ERROR_SUCCESS; +} + +static void +k5_update_last_default_identity(khm_handle ident) { + wchar_t idname[KCDB_IDENT_MAXCCH_NAME]; + khm_size cb; + + cb = sizeof(idname); + if (KHM_FAILED(kcdb_identity_get_name(ident, idname, &cb))) + return; + + assert(csp_params); + + khc_write_string(csp_params, L"LastDefaultIdent", idname); +} + +static khm_int32 +k5_ident_set_default_int(khm_handle def_ident) { + wchar_t id_ccname[KRB5_MAXCCH_CCNAME]; + khm_size cb; + DWORD dw; + LONG l; + HKEY hk_ccname; + DWORD dwType; + DWORD dwSize; + wchar_t reg_ccname[KRB5_MAXCCH_CCNAME]; + +#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))) { + khm_handle csp_ident = NULL; + khm_handle csp_k5 = NULL; + + _reportf(L"The specified identity does not have the Krb5CCName property"); + + cb = sizeof(id_ccname); + if (KHM_SUCCEEDED(kcdb_identity_get_config(def_ident, 0, &csp_ident)) && + KHM_SUCCEEDED(khc_open_space(csp_ident, CSNAME_KRB5CRED, 0, &csp_k5)) && + KHM_SUCCEEDED(khc_read_string(csp_k5, L"DefaultCCName", + id_ccname, &cb))) { + + _reportf(L"Found CC name in configuration [%s]", id_ccname); + } else { + /* last resort, use the name of the identity as the cc + name */ + cb = sizeof(id_ccname); + if (KHM_FAILED(kcdb_identity_get_name(def_ident, id_ccname, &cb))) { + _reportf(L"Can't use name of identity as CCName"); + _end_task(); + + id_ccname[0] = L'\0'; + } + } + + if (csp_k5) + khc_close_space(csp_k5); + if (csp_ident) + khc_close_space(csp_ident); + + if (id_ccname[0] == L'\0') + return KHM_ERROR_INVALID_PARAM; + } + + khm_krb5_canon_cc_name(id_ccname, sizeof(id_ccname)); + + _reportf(L"Found Krb5CCName property : %s", id_ccname); + + StringCbLength(id_ccname, sizeof(id_ccname), &cb); + cb += sizeof(wchar_t); + + _reportf(L"Setting default CC name in the registry"); + + 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) { + _reportf(L"Can't create registry key : %d", l); + _end_task(); + 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) { + _reportf(L"Successfully set the default ccache"); + k5_update_last_default_identity(def_ident); + return KHM_ERROR_SUCCESS; + } else { + _reportf(L"Can't set the registry value : %d", l); + return KHM_ERROR_UNKNOWN; + } +} + +static khm_int32 +k5_ident_set_default(khm_int32 msg_type, + khm_int32 msg_subtype, + khm_ui_4 uparam, + void * vparam) { + + /* + Currently, setting the default identity simply sets the + "ccname" registry value at "Software\MIT\kerberos5". + */ + + if (uparam) { + /* an identity is being made default */ + khm_handle def_ident = (khm_handle) vparam; + khm_int32 rv; + +#ifdef DEBUG + assert(def_ident != NULL); +#endif + + { + wchar_t idname[KCDB_IDENT_MAXCCH_NAME]; + khm_size cb; + + cb = sizeof(idname); + kcdb_identity_get_name(def_ident, idname, &cb); + + _begin_task(0); + _report_cs1(KHERR_DEBUG_1, L"Setting default identity [%1!s!]", _cstr(idname)); + _describe(); + } + + rv = k5_ident_set_default_int(def_ident); + + _end_task(); + + return rv; + + } 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; + + /* if there is a default identity already, we assume we don't need + to check this one. */ + + khm_handle def_ident; + + if (KHM_SUCCEEDED(kcdb_identity_get_default(&def_ident))) { + kcdb_identity_release(def_ident); + + return KHM_ERROR_SUCCESS; + } + + 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; +} + +struct k5_ident_update_data { + khm_handle identity; + + FILETIME ft_expire; /* expiration */ + FILETIME ft_issue; /* issue */ + FILETIME ft_rexpire; /* renew expiration */ + wchar_t ccname[KRB5_MAXCCH_CCNAME]; + khm_int32 k5_flags; +}; + +/* The logic here has to reflect the logic in khm_krb5_list_tickets(). + We use this to handle an identity update request because some other + plug-in or maybe NetIDMgr itself is about to do something + important(tm) with the identity and needs to make sure that the + properties of the identity are up-to-date. */ +static khm_int32 KHMAPI +k5_ident_update_apply_proc(khm_handle cred, + void * rock) { + struct k5_ident_update_data * d = (struct k5_ident_update_data *) rock; + khm_handle ident = NULL; + khm_int32 t; + khm_int32 flags; + FILETIME t_cexpire; + FILETIME 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 (!kcdb_identity_is_equal(ident,d->identity)) + + goto _cleanup; + + if (KHM_FAILED(kcdb_cred_get_flags(cred, &flags))) + + flags = 0; + + if (flags & KCDB_CRED_FLAG_INITIAL) { + cb = sizeof(t_cexpire); + if (KHM_SUCCEEDED(kcdb_cred_get_attr(cred, + KCDB_ATTR_EXPIRE, + NULL, + &t_cexpire, + &cb))) { + if ((d->ft_expire.dwLowDateTime == 0 && + d->ft_expire.dwHighDateTime == 0) || + CompareFileTime(&t_cexpire, &d->ft_expire) > 0) { + goto update_identity; + } + } + } + + goto _cleanup; + + update_identity: + + d->ft_expire = t_cexpire; + + cb = sizeof(d->ccname); + if (KHM_FAILED(kcdb_cred_get_attr(cred, KCDB_ATTR_LOCATION, NULL, d->ccname, &cb))) { + d->ccname[0] = L'\0'; + } + + cb = sizeof(d->k5_flags); + if (KHM_FAILED(kcdb_cred_get_attr(cred, attr_id_krb5_flags, NULL, + &d->k5_flags, &cb))) { + d->k5_flags = 0; + } + + cb = sizeof(d->ft_issue); + if (KHM_FAILED(kcdb_cred_get_attr(cred, KCDB_ATTR_ISSUE, NULL, &d->ft_issue, &cb))) { + ZeroMemory(&d->ft_issue, sizeof(d->ft_issue)); + } + + cb = sizeof(t_rexpire); + if ((d->k5_flags & TKT_FLG_RENEWABLE) && + KHM_SUCCEEDED(kcdb_cred_get_attr(cred, + KCDB_ATTR_RENEW_EXPIRE, + NULL, + &t_rexpire, + &cb))) { + d->ft_rexpire = t_rexpire; + } else { + ZeroMemory(&d->ft_rexpire, sizeof(d->ft_rexpire)); + } + + _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) { + +#if 0 + struct k5_ident_update_data d; +#endif + khm_handle ident; + khm_handle tident; + krb5_ccache cc = NULL; + char * ccname; + krb5_error_code code; + khm_size cb; + wchar_t wid_ccname[MAX_PATH]; + wchar_t w_ccname[MAX_PATH]; + + ident = (khm_handle) vparam; + if (ident == NULL) + return KHM_ERROR_SUCCESS; + +#if 0 + /* we are going to skip doing this here since + khm_krb5_list_tickets() performs this function for us each time + we enumerate tickets. Since it also gets run each time our + list of tickets changes and since we are basing this operation + on existing tickets, we are unlikely to find anything new + here. */ + ZeroMemory(&d, sizeof(d)); + d.identity = ident; + + kcdb_credset_apply(NULL, + k5_ident_update_apply_proc, + (void *) &d); + + if (d.ft_expire.dwLowDateTime != 0 || + d.ft_expire.dwHighDateTime != 0) { + + /* we found a TGT */ + + kcdb_identity_set_attr(ident, KCDB_ATTR_EXPIRE, + &d.ft_expire, sizeof(d.ft_expire)); + if (d.ft_issue.dwLowDateTime != 0 || + d.ft_issue.dwHighDateTime != 0) + kcdb_identity_set_attr(ident, KCDB_ATTR_ISSUE, + &d.ft_issue, sizeof(d.ft_issue)); + else + kcdb_identity_set_attr(ident, KCDB_ATTR_ISSUE, NULL, 0); + + if (d.ft_rexpire.dwLowDateTime != 0 || + d.ft_rexpire.dwHighDateTime != 0) + kcdb_identity_set_attr(ident, KCDB_ATTR_RENEW_EXPIRE, + &d.ft_rexpire, sizeof(d.ft_rexpire)); + else + kcdb_identity_set_attr(ident, KCDB_ATTR_RENEW_EXPIRE, NULL, 0); + + kcdb_identity_set_attr(ident, attr_id_krb5_flags, + &d.k5_flags, sizeof(d.k5_flags)); + + if (d.ccname[0]) + kcdb_identity_set_attr(ident, attr_id_krb5_ccname, + d.ccname, KCDB_CBSIZE_AUTO); + else + kcdb_identity_set_attr(ident, attr_id_krb5_ccname, NULL, 0); + + } else { + /* Clear out the attributes. We don't have any information + about this identity */ + kcdb_identity_set_attr(ident, KCDB_ATTR_EXPIRE, NULL, 0); + kcdb_identity_set_attr(ident, KCDB_ATTR_ISSUE, NULL, 0); + kcdb_identity_set_attr(ident, KCDB_ATTR_RENEW_EXPIRE, NULL, 0); + kcdb_identity_set_attr(ident, attr_id_krb5_flags, NULL, 0); + kcdb_identity_set_attr(ident, attr_id_krb5_ccname, NULL, 0); + } +#endif + + if (KHM_SUCCEEDED(kcdb_identity_get_default(&tident))) { + kcdb_identity_release(tident); + goto _iu_cleanup; + } + + cb = sizeof(wid_ccname); + if (KHM_FAILED(kcdb_identity_get_attr(ident, + attr_id_krb5_ccname, + NULL, + wid_ccname, + &cb))) + goto _iu_cleanup; + + if(k5_identpro_ctx == NULL) + goto _iu_cleanup; + + code = pkrb5_cc_default(k5_identpro_ctx, &cc); + if (code) + goto _iu_cleanup; + + ccname = pkrb5_cc_get_name(k5_identpro_ctx, cc); + if (ccname == NULL) + goto _iu_cleanup; + + AnsiStrToUnicode(w_ccname, sizeof(w_ccname), ccname); + + khm_krb5_canon_cc_name(w_ccname, sizeof(w_ccname)); + khm_krb5_canon_cc_name(wid_ccname, sizeof(wid_ccname)); + + if (!_wcsicmp(w_ccname, wid_ccname)) + kcdb_identity_set_default_int(ident); + + _iu_cleanup: + if (cc && k5_identpro_ctx) + pkrb5_cc_close(k5_identpro_ctx, cc); + + return KHM_ERROR_SUCCESS; +} + +static khm_boolean +k5_refresh_default_identity(krb5_context ctx) { + /* 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]; + char * ccname = NULL; + khm_handle ident = NULL; + khm_boolean found_default = FALSE; + + assert(ctx != NULL); + + _begin_task(0); + _report_cs0(KHERR_DEBUG_1, L"Refreshing default identity"); + _describe(); + + code = pkrb5_cc_default(ctx, &cc); + if (code) { + _reportf(L"Can't open default ccache. code=%d", code); + goto _nc_cleanup; + } + + code = pkrb5_cc_get_principal(ctx, cc, &princ); + if (code) { + /* try to determine the identity from the ccache name */ + ccname = pkrb5_cc_get_name(ctx, cc); + + if (ccname) { + char * namepart = strchr(ccname, ':'); + + _reportf(L"CC name is [%S]", ccname); + + if (namepart == NULL) + namepart = ccname; + else + namepart++; + + _reportf(L"Checking if [%S] is a valid identity name", namepart); + + AnsiStrToUnicode(princ_nameW, sizeof(princ_nameW), namepart); + if (kcdb_identity_is_valid_name(princ_nameW)) { + kcdb_identity_create(princ_nameW, KCDB_IDENT_FLAG_CREATE, &ident); + if (ident) { + _reportf(L"Setting [%S] as the default identity", namepart); + kcdb_identity_set_default_int(ident); + found_default = TRUE; + } + } + } else { + _reportf(L"Can't determine ccache name"); + } + + goto _nc_cleanup; + } + + code = pkrb5_unparse_name(ctx, princ, &princ_nameA); + if (code) + goto _nc_cleanup; + + AnsiStrToUnicode(princ_nameW, sizeof(princ_nameW), princ_nameA); + + _reportf(L"Found principal [%s]", princ_nameW); + + if (KHM_FAILED(kcdb_identity_create(princ_nameW, KCDB_IDENT_FLAG_CREATE, &ident))) { + _reportf(L"Failed to create identity"); + goto _nc_cleanup; + } + + _reportf(L"Setting default identity to [%s]", princ_nameW); + kcdb_identity_set_default_int(ident); + + found_default = TRUE; + + _nc_cleanup: + + _end_task(); + + if (princ_nameA) + pkrb5_free_unparsed_name(ctx, princ_nameA); + + if (princ) + pkrb5_free_principal(ctx, princ); + + if (cc) + pkrb5_cc_close(ctx, cc); + + if (ident) + kcdb_identity_release(ident); + + return found_default; +} + +static khm_int32 +k5_ident_init(khm_int32 msg_type, + khm_int32 msg_subtype, + khm_ui_4 uparam, + void * vparam) { + + khm_boolean found_default; + khm_handle ident; + + found_default = k5_refresh_default_identity(k5_identpro_ctx); + + if (!found_default) { + wchar_t widname[KCDB_IDENT_MAXCCH_NAME]; + khm_size cb; + + cb = sizeof(widname); + + assert(csp_params); + + if (KHM_SUCCEEDED(khc_read_string(csp_params, L"LastDefaultIdent", + widname, &cb))) { + ident = NULL; + kcdb_identity_create(widname, KCDB_IDENT_FLAG_CREATE, &ident); + if (ident) { + kcdb_identity_set_default_int(ident); + kcdb_identity_release(ident); + + found_default = TRUE; + } + } + } + + if (!found_default) { + + /* There was no default ccache and we don't have a + "LastDefaultIdent" value. Next we see if there are any + identities that have credentials which have a Krb5CCName + property (i.e. an identity that has a Kerberos 5 TGT), and + make it the default. + + Note that since the Krb5Ident plug-in has a dependency on + Krb5Cred, by the time this code runs, we already have a + listing of Kerberos 5 tickets and identities. */ + + wchar_t * idlist = NULL; + wchar_t * thisid; + khm_size cb = 0; + khm_size n_idents = 0; + khm_int32 rv; + wchar_t ccname[KRB5_MAXCCH_CCNAME]; + FILETIME ft_expire; + FILETIME ft_now; + FILETIME ft_threshold; + BOOL match_all = FALSE; + + rv = kcdb_identity_enum(0, 0, NULL, &cb, &n_idents); + + TimetToFileTimeInterval(5 * 60, &ft_threshold); + GetSystemTimeAsFileTime(&ft_now); + ft_now = FtAdd(&ft_now, &ft_threshold); + + while (rv == KHM_ERROR_TOO_LONG && n_idents > 0) { + if (idlist) { + PFREE(idlist); + idlist = NULL; + } + + idlist = PMALLOC(cb); + + if (idlist == NULL) + break; + + rv = kcdb_identity_enum(0, 0, idlist, &cb, &n_idents); + } + + if (KHM_SUCCEEDED(rv)) { + + /* first we try to find an identity that has a valid TGT. + If that fails, then we try to find an identity with + *any* TGT. */ + + try_again: + + for (thisid = idlist; + thisid && *thisid && !found_default; + thisid = multi_string_next(thisid)) { + + if (KHM_SUCCEEDED(kcdb_identity_create(thisid, 0, &ident))) { + khm_size cb_ft = sizeof(FILETIME); + cb = sizeof(ccname); + + if (KHM_SUCCEEDED(kcdb_identity_get_attr(ident, attr_id_krb5_ccname, + NULL, ccname, &cb)) && + (match_all || + (KHM_SUCCEEDED(kcdb_identity_get_attr(ident, KCDB_ATTR_EXPIRE, + NULL, &ft_expire, &cb_ft)) && + CompareFileTime(&ft_expire, &ft_now) > 0))) { + + /* found one */ + k5_ident_set_default_int(ident); + kcdb_identity_set_default_int(ident); + found_default = TRUE; + + } + + kcdb_identity_release(ident); + ident = NULL; + } + } + + if (!found_default && !match_all) { + match_all = TRUE; + goto try_again; + } + } + + if (idlist) { + PFREE(idlist); + idlist = NULL; + } + } + + 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; +} + +/* forward dcl */ +khm_int32 KHMAPI +k5_ident_name_comp_func(const void * dl, khm_size cb_dl, + const void * dr, khm_size cb_dr); + +static khm_int32 +k5_ident_compare_name(khm_int32 msg_type, + khm_int32 msg_subtype, + khm_ui_4 uparam, + void * vparam) { + kcdb_ident_name_xfer *px; + + px = (kcdb_ident_name_xfer *) vparam; + + /* note that k5_ident_name_comp_func() ignores the size + specifiers. So we can just pass in 0's. */ + px->result = k5_ident_name_comp_func(px->name_src, 0, + px->name_alt, 0); + + 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_validate_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: + return k5_ident_compare_name(msg_type, + msg_subtype, + uparam, + vparam); + + 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; +} + +/* note that we are ignoring the size specifiers. We can do that + because we are guaranteed that dl and dr point to NULL terminated + unicode strings when used with credential data buffers. We also + use the fact that we are ignoring the size specifiers when we call + this function from k5_ident_compare_name() to avoid calculating the + length of the string. */ +khm_int32 KHMAPI +k5_ident_name_comp_func(const void * dl, khm_size cb_dl, + const void * dr, khm_size cb_dr) { + wchar_t * idl = (wchar_t *) dl; + wchar_t * idr = (wchar_t *) dr; + wchar_t * rl; + wchar_t * rr; + khm_int32 r; + + rl = khm_get_realm_from_princ(idl); + rr = khm_get_realm_from_princ(idr); + + if (rl == NULL && rr == NULL) + return wcscmp(idl, idr); + else if (rl == NULL) + return 1; + else if (rr == NULL) + return -1; + + r = wcscmp(rl, rr); + if (r == 0) + return wcscmp(idl, idr); + else + return r; +} + + +/* Identity change notification thread */ + +HANDLE h_ccname_exit_event; +HANDLE h_ccname_thread; + +DWORD WINAPI k5_ccname_monitor_thread(LPVOID lpParameter) { + krb5_context ctx = 0; + + HKEY hk_ccname; + HANDLE h_notify; + HANDLE h_waits[2]; + + khm_int32 rv = KHM_ERROR_SUCCESS; + DWORD dwType; + DWORD dwSize; + DWORD dwDisp; + wchar_t reg_ccname[KRB5_MAXCCH_CCNAME]; + LONG l; + + PDESCTHREAD(L"Krb5 CCName Monitor", L"Krb5"); + + 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, + &dwDisp); + + if (l != ERROR_SUCCESS) { + rv = KHM_ERROR_UNKNOWN; + goto _exit; + } + + dwSize = sizeof(reg_ccname); + + l = RegQueryValueEx(hk_ccname, + L"ccname", + NULL, + &dwType, + (LPBYTE) reg_ccname, + &dwSize); + + if (l != ERROR_SUCCESS || + dwType != REG_SZ) { + + reg_ccname[0] = L'\0'; + } + + l = pkrb5_init_context(&ctx); + + if (l) + goto _exit_0; + + h_notify = CreateEvent(NULL, FALSE, FALSE, L"Local\\Krb5CCNameChangeNotifier"); + + if (h_notify == NULL) + goto _exit_0; + + /* begin wait loop */ + + h_waits[0] = h_ccname_exit_event; + h_waits[1] = h_notify; + + do { + DWORD dwrv; + + l = RegNotifyChangeKeyValue(hk_ccname, FALSE, + REG_NOTIFY_CHANGE_LAST_SET, + h_notify, TRUE); + + if (l != ERROR_SUCCESS) { + rv = KHM_ERROR_UNKNOWN; + break; + } + + dwrv = WaitForMultipleObjects(2, h_waits, FALSE, INFINITE); + + if (dwrv == WAIT_OBJECT_0) { + /* exit! */ + break; + + } else if (dwrv == WAIT_OBJECT_0 + 1) { + /* change notify! */ + wchar_t new_ccname[KRB5_MAXCCH_CCNAME]; + + dwSize = sizeof(new_ccname); + + l = RegQueryValueEx(hk_ccname, + L"ccname", + NULL, + &dwType, + (LPBYTE) new_ccname, + &dwSize); + + if (l != ERROR_SUCCESS || + dwType != REG_SZ) { + new_ccname[0] = L'\0'; + } + + if (_wcsicmp(new_ccname, reg_ccname)) { + k5_refresh_default_identity(ctx); + StringCbCopy(reg_ccname, sizeof(reg_ccname), new_ccname); + } + + } else { + /* something went wrong */ + rv = KHM_ERROR_UNKNOWN; + break; + } + + } while (TRUE); + + CloseHandle(h_notify); + + _exit_0: + + RegCloseKey(hk_ccname); + + if (ctx) + pkrb5_free_context(ctx); + + _exit: + ExitThread(rv); + + /* not reached */ + return rv; +} + +khm_int32 +k5_msg_system_idpro(khm_int32 msg_type, khm_int32 msg_subtype, + khm_ui_4 uparam, void * vparam) { + + switch(msg_subtype) { + case KMSG_SYSTEM_INIT: + { + + pkrb5_init_context(&k5_identpro_ctx); + kcdb_identity_set_type(credtype_id_krb5); + + if (KHM_FAILED(kcdb_type_get_id(TYPENAME_KRB5_PRINC, + &type_id_krb5_princ))) { + kcdb_type dt; + kcdb_type * pstr; + + kcdb_type_get_info(KCDB_TYPE_STRING, &pstr); + + ZeroMemory(&dt, sizeof(dt)); + dt.name = TYPENAME_KRB5_PRINC; + dt.id = KCDB_TYPE_INVALID; + dt.flags = KCDB_TYPE_FLAG_CB_AUTO; + dt.cb_min = pstr->cb_min; + dt.cb_max = pstr->cb_max; + dt.toString = pstr->toString; + dt.isValid = pstr->isValid; + dt.comp = k5_ident_name_comp_func; + dt.dup = pstr->dup; + + kcdb_type_register(&dt, &type_id_krb5_princ); + + type_regd_krb5_princ = TRUE; + + kcdb_type_release_info(pstr); + } + + if (type_id_krb5_princ != -1) { + kcdb_attrib * attr; + + kcdb_attrib_get_info(KCDB_ATTR_ID_NAME, &attr); + + attr->type = type_id_krb5_princ; + + kcdb_attrib_release_info(attr); + } + + h_ccname_exit_event = CreateEvent(NULL, FALSE, FALSE, NULL); + if (h_ccname_exit_event) { + h_ccname_thread = CreateThread(NULL, + 200 * 1024, + k5_ccname_monitor_thread, + NULL, + 0, + NULL); + } else { + h_ccname_thread = NULL; + } + } + break; + + case KMSG_SYSTEM_EXIT: + { + + if (h_ccname_thread) { + SetEvent(h_ccname_exit_event); + WaitForSingleObject(h_ccname_thread, INFINITE); + CloseHandle(h_ccname_thread); + CloseHandle(h_ccname_exit_event); + + h_ccname_exit_event = NULL; + h_ccname_thread = NULL; + } + + if (k5_identpro_ctx) { + pkrb5_free_context(k5_identpro_ctx); + k5_identpro_ctx = NULL; + } + + if (type_id_krb5_princ != -1) { + kcdb_attrib * attr; + + kcdb_attrib_get_info(KCDB_ATTR_ID_NAME, &attr); + + attr->type = KCDB_TYPE_STRING; + + kcdb_attrib_release_info(attr); + } + + /* allow a brief moment for any stale references to die */ + Sleep(100); + + if (type_regd_krb5_princ) { + kcdb_type_unregister(type_id_krb5_princ); + } + } + break; + } + + return KHM_ERROR_SUCCESS; +} + +khm_int32 KHMAPI +k5_ident_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_idpro(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/krb5main.c b/src/windows/identity/plugins/krb5/krb5main.c index 3d2f2c0e9..befa7a980 100644 --- a/src/windows/identity/plugins/krb5/krb5main.c +++ b/src/windows/identity/plugins/krb5/krb5main.c @@ -1,497 +1,497 @@ -/*
- * Copyright (c) 2005 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"Krb5Cred";
-
-khm_int32 type_id_enctype = -1;
-khm_int32 type_id_addr_list = -1;
-khm_int32 type_id_krb5_flags = -1;
-khm_int32 type_id_krb5_princ = -1;
-khm_int32 type_id_kvno = -1;
-
-BOOL type_regd_enctype = FALSE;
-BOOL type_regd_addr_list = FALSE;
-BOOL type_regd_krb5_flags = FALSE;
-BOOL type_regd_krb5_princ = FALSE;
-BOOL type_regd_kvno = 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;
-khm_int32 attr_id_kvno = -1;
-khm_int32 attr_id_krb5_idflags = -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;
-BOOL attr_regd_kvno = FALSE;
-BOOL attr_regd_krb5_idflags = FALSE;
-
-khm_handle csp_plugins = NULL;
-khm_handle csp_krbcred = NULL;
-khm_handle csp_params = NULL;
-
-BOOL is_k5_identpro = TRUE;
-
-khm_ui_4 k5_commctl_version;
-
-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;
-
- k5_commctl_version = khm_get_commctl_version(NULL);
-
- /* register the plugin */
- ZeroMemory(&pi, sizeof(pi));
- pi.name = KRB5_PLUGIN_NAME;
- pi.type = KHM_PITYPE_CRED;
- pi.icon = LoadImage(hResModule, MAKEINTRESOURCE(IDI_PLUGIN),
- IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR | LR_DEFAULTSIZE);
- pi.flags = 0;
- pi.msg_proc = k5_msg_callback;
- pi.description = buf;
- pi.dependencies = NULL;
- LoadString(hResModule, IDS_PLUGIN_DESC,
- buf, ARRAYLENGTH(buf));
- kmm_provide_plugin(h_module, &pi);
-
- ZeroMemory(&pi, sizeof(pi));
- pi.name = KRB5_IDENTPRO_NAME;
- pi.type = KHM_PITYPE_IDENT;
- pi.icon = LoadImage(hResModule, MAKEINTRESOURCE(IDI_PLUGIN),
- IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR | LR_DEFAULTSIZE);
- pi.flags = 0;
- pi.msg_proc = k5_ident_callback;
- pi.description = buf;
- pi.dependencies = KRB5_PLUGIN_NAME L"\0";
- LoadString(hResModule, IDS_IDENTPRO_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 = addr_list_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;
- }
-
- if (KHM_FAILED(kcdb_type_get_id(TYPENAME_KVNO, &type_id_kvno))) {
- kcdb_type type;
- kcdb_type *t32;
-
- kcdb_type_get_info(KCDB_TYPE_INT32, &t32);
-
- type.id = KCDB_TYPE_INVALID;
- type.name = TYPENAME_KVNO;
- 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 = kvno_toString;
-
- rv = kcdb_type_register(&type, &type_id_kvno);
- kcdb_type_release_info(t32);
-
- if (KHM_FAILED(rv))
- goto _exit;
-
- type_regd_kvno = 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 = KCDB_ATTR_FLAG_TRANSIENT;
- 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 = KCDB_ATTR_FLAG_TRANSIENT;
- 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 = KCDB_ATTR_FLAG_TRANSIENT;
- 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 = KCDB_ATTR_FLAG_TRANSIENT;
- 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 |
- KCDB_ATTR_FLAG_TRANSIENT;
- 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;
- }
-
- if (KHM_FAILED(kcdb_attrib_get_id(ATTRNAME_KVNO, &attr_id_kvno))) {
- kcdb_attrib attrib;
- wchar_t sbuf[KCDB_MAXCCH_SHORT_DESC];
- wchar_t lbuf[KCDB_MAXCCH_LONG_DESC];
- /* although we are loading a long description, it still fits
- in the short description buffer */
-
- ZeroMemory(&attrib, sizeof(attrib));
-
- attrib.name = ATTRNAME_KVNO;
- attrib.id = KCDB_ATTR_INVALID;
- attrib.type = type_id_kvno;
- attrib.flags = KCDB_ATTR_FLAG_TRANSIENT;
- LoadString(hResModule, IDS_KVNO_SHORT_DESC, sbuf, ARRAYLENGTH(sbuf));
- LoadString(hResModule, IDS_KVNO_LONG_DESC, lbuf, ARRAYLENGTH(lbuf));
- attrib.short_desc = sbuf;
- attrib.long_desc = lbuf;
-
- rv = kcdb_attrib_register(&attrib, &attr_id_kvno);
-
- if (KHM_FAILED(rv))
- goto _exit;
-
- attr_regd_kvno = TRUE;
- }
-
- if (KHM_FAILED(kcdb_attrib_get_id(ATTRNAME_KRB5_IDFLAGS, &attr_id_krb5_idflags))) {
- kcdb_attrib attrib;
-
- ZeroMemory(&attrib, sizeof(attrib));
-
- attrib.name = ATTRNAME_KRB5_IDFLAGS;
- attrib.id = KCDB_ATTR_INVALID;
- attrib.type = KCDB_TYPE_INT32;
- attrib.flags = KCDB_ATTR_FLAG_PROPERTY |
- KCDB_ATTR_FLAG_HIDDEN;
- /* we don't bother localizing these strings since the
- attribute is hidden. The user will not see these
- descriptions anyway. */
- attrib.short_desc = L"Krb5 ID flags";
- attrib.long_desc = L"Kerberos 5 Identity Flags";
-
- rv = kcdb_attrib_register(&attrib, &attr_id_krb5_idflags);
-
- if (KHM_FAILED(rv))
- goto _exit;
-
- attr_regd_krb5_idflags = 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(attr_regd_kvno)
- kcdb_attrib_unregister(attr_id_kvno);
- if(attr_regd_krb5_idflags)
- kcdb_attrib_unregister(attr_id_krb5_idflags);
-
- 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(type_regd_kvno)
- kcdb_type_unregister(type_id_kvno);
-
- 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;
-}
+/* + * Copyright (c) 2005 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"Krb5Cred"; + +khm_int32 type_id_enctype = -1; +khm_int32 type_id_addr_list = -1; +khm_int32 type_id_krb5_flags = -1; +khm_int32 type_id_krb5_princ = -1; +khm_int32 type_id_kvno = -1; + +BOOL type_regd_enctype = FALSE; +BOOL type_regd_addr_list = FALSE; +BOOL type_regd_krb5_flags = FALSE; +BOOL type_regd_krb5_princ = FALSE; +BOOL type_regd_kvno = 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; +khm_int32 attr_id_kvno = -1; +khm_int32 attr_id_krb5_idflags = -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; +BOOL attr_regd_kvno = FALSE; +BOOL attr_regd_krb5_idflags = FALSE; + +khm_handle csp_plugins = NULL; +khm_handle csp_krbcred = NULL; +khm_handle csp_params = NULL; + +BOOL is_k5_identpro = TRUE; + +khm_ui_4 k5_commctl_version; + +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; + + k5_commctl_version = khm_get_commctl_version(NULL); + + /* register the plugin */ + ZeroMemory(&pi, sizeof(pi)); + pi.name = KRB5_PLUGIN_NAME; + pi.type = KHM_PITYPE_CRED; + pi.icon = LoadImage(hResModule, MAKEINTRESOURCE(IDI_PLUGIN), + IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR | LR_DEFAULTSIZE); + pi.flags = 0; + pi.msg_proc = k5_msg_callback; + pi.description = buf; + pi.dependencies = NULL; + LoadString(hResModule, IDS_PLUGIN_DESC, + buf, ARRAYLENGTH(buf)); + kmm_provide_plugin(h_module, &pi); + + ZeroMemory(&pi, sizeof(pi)); + pi.name = KRB5_IDENTPRO_NAME; + pi.type = KHM_PITYPE_IDENT; + pi.icon = LoadImage(hResModule, MAKEINTRESOURCE(IDI_PLUGIN), + IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR | LR_DEFAULTSIZE); + pi.flags = 0; + pi.msg_proc = k5_ident_callback; + pi.description = buf; + pi.dependencies = KRB5_PLUGIN_NAME L"\0"; + LoadString(hResModule, IDS_IDENTPRO_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 = addr_list_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; + } + + if (KHM_FAILED(kcdb_type_get_id(TYPENAME_KVNO, &type_id_kvno))) { + kcdb_type type; + kcdb_type *t32; + + kcdb_type_get_info(KCDB_TYPE_INT32, &t32); + + type.id = KCDB_TYPE_INVALID; + type.name = TYPENAME_KVNO; + 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 = kvno_toString; + + rv = kcdb_type_register(&type, &type_id_kvno); + kcdb_type_release_info(t32); + + if (KHM_FAILED(rv)) + goto _exit; + + type_regd_kvno = 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 = KCDB_ATTR_FLAG_TRANSIENT; + 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 = KCDB_ATTR_FLAG_TRANSIENT; + 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 = KCDB_ATTR_FLAG_TRANSIENT; + 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 = KCDB_ATTR_FLAG_TRANSIENT; + 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 | + KCDB_ATTR_FLAG_TRANSIENT; + 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; + } + + if (KHM_FAILED(kcdb_attrib_get_id(ATTRNAME_KVNO, &attr_id_kvno))) { + kcdb_attrib attrib; + wchar_t sbuf[KCDB_MAXCCH_SHORT_DESC]; + wchar_t lbuf[KCDB_MAXCCH_LONG_DESC]; + /* although we are loading a long description, it still fits + in the short description buffer */ + + ZeroMemory(&attrib, sizeof(attrib)); + + attrib.name = ATTRNAME_KVNO; + attrib.id = KCDB_ATTR_INVALID; + attrib.type = type_id_kvno; + attrib.flags = KCDB_ATTR_FLAG_TRANSIENT; + LoadString(hResModule, IDS_KVNO_SHORT_DESC, sbuf, ARRAYLENGTH(sbuf)); + LoadString(hResModule, IDS_KVNO_LONG_DESC, lbuf, ARRAYLENGTH(lbuf)); + attrib.short_desc = sbuf; + attrib.long_desc = lbuf; + + rv = kcdb_attrib_register(&attrib, &attr_id_kvno); + + if (KHM_FAILED(rv)) + goto _exit; + + attr_regd_kvno = TRUE; + } + + if (KHM_FAILED(kcdb_attrib_get_id(ATTRNAME_KRB5_IDFLAGS, &attr_id_krb5_idflags))) { + kcdb_attrib attrib; + + ZeroMemory(&attrib, sizeof(attrib)); + + attrib.name = ATTRNAME_KRB5_IDFLAGS; + attrib.id = KCDB_ATTR_INVALID; + attrib.type = KCDB_TYPE_INT32; + attrib.flags = KCDB_ATTR_FLAG_PROPERTY | + KCDB_ATTR_FLAG_HIDDEN; + /* we don't bother localizing these strings since the + attribute is hidden. The user will not see these + descriptions anyway. */ + attrib.short_desc = L"Krb5 ID flags"; + attrib.long_desc = L"Kerberos 5 Identity Flags"; + + rv = kcdb_attrib_register(&attrib, &attr_id_krb5_idflags); + + if (KHM_FAILED(rv)) + goto _exit; + + attr_regd_krb5_idflags = 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(attr_regd_kvno) + kcdb_attrib_unregister(attr_id_kvno); + if(attr_regd_krb5_idflags) + kcdb_attrib_unregister(attr_id_krb5_idflags); + + 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(type_regd_kvno) + kcdb_type_unregister(type_id_kvno); + + 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/krb5newcreds.c b/src/windows/identity/plugins/krb5/krb5newcreds.c index edd64725d..d2458fe50 100644 --- a/src/windows/identity/plugins/krb5/krb5newcreds.c +++ b/src/windows/identity/plugins/krb5/krb5newcreds.c @@ -1,2747 +1,2747 @@ -/*
- * Copyright (c) 2006 Secure Endpoints Inc.
- *
- * 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<commctrl.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; /* is the data in sync with the
- configuration store? */
- BOOL sync; /* is the data in sync with the kinit
- request? */
- DWORD renewable;
- DWORD forwardable;
- DWORD proxiable;
- DWORD addressless;
- DWORD publicIP;
-
- wchar_t * cred_message; /* overrides the credential text, if
- non-NULL */
- BOOL pwd_change; /* force a password change */
-} 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 = PMALLOC(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);
-
- if (!d)
- return TRUE;
-
- 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);
- }
-
- PFREE(d);
-
- return TRUE;
-}
-
-LRESULT
-k5_force_password_change(k5_dlg_data * d) {
- /* we are turning this dialog into a change password dialog... */
- wchar_t wbuf[KHUI_MAXCCH_BANNER];
-
- khui_cw_clear_prompts(d->nc);
-
- LoadString(hResModule, IDS_NC_PWD_BANNER,
- wbuf, ARRAYLENGTH(wbuf));
- khui_cw_begin_custom_prompts(d->nc, 3, NULL, wbuf);
-
- LoadString(hResModule, IDS_NC_PWD_PWD,
- wbuf, ARRAYLENGTH(wbuf));
- khui_cw_add_prompt(d->nc, KHUI_NCPROMPT_TYPE_PASSWORD,
- wbuf, NULL, KHUI_NCPROMPT_FLAG_HIDDEN);
-
- LoadString(hResModule, IDS_NC_PWD_NPWD,
- wbuf, ARRAYLENGTH(wbuf));
- khui_cw_add_prompt(d->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(d->nc, KHUI_NCPROMPT_TYPE_NEW_PASSWORD_AGAIN,
- wbuf, NULL, KHUI_NCPROMPT_FLAG_HIDDEN);
-
- d->pwd_change = TRUE;
-
- if (is_k5_identpro &&
- d->nc->n_identities > 0 &&
- d->nc->identities[0]) {
-
- kcdb_identity_set_flags(d->nc->identities[0],
- KCDB_IDENT_FLAG_VALID,
- KCDB_IDENT_FLAG_VALID);
-
- }
-
- PostMessage(d->nc->hwnd, KHUI_WM_NC_NOTIFY,
- MAKEWPARAM(0, WMNC_UPDATE_CREDTEXT),
- (LPARAM) d->nc);
-
- 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;
- BOOL old_sync;
-
- d = (k5_dlg_data *)(LONG_PTR)
- GetWindowLongPtr(hwnd, DWLP_USER);
-
- if (d->nc->subtype == KMSG_CRED_PASSWORD)
- return TRUE;
-
- /* we save the value of the 'sync' field here because some
- of the notifications that are generated while setting
- the controls overwrite the field. */
- old_sync = d->sync;
-
- /* need to update the controls with d->* */
- SendDlgItemMessage(hwnd, IDC_NCK5_RENEWABLE,
- BM_SETCHECK,
- (d->renewable? BST_CHECKED : BST_UNCHECKED),
- 0);
- EnableWindow(GetDlgItem(hwnd, IDC_NCK5_RENEW_EDIT),
- !!d->renewable);
-
- khui_tracker_refresh(&d->tc_lifetime);
- khui_tracker_refresh(&d->tc_renew);
-
- SendDlgItemMessage(hwnd, IDC_NCK5_FORWARDABLE,
- BM_SETCHECK,
- (d->forwardable ? BST_CHECKED : BST_UNCHECKED),
- 0);
-
- SendDlgItemMessage(hwnd, IDC_NCK5_ADDRESS,
- BM_SETCHECK,
- (d->addressless ? BST_CHECKED : BST_UNCHECKED),
- 0);
-
- SendDlgItemMessage(hwnd, IDC_NCK5_PUBLICIP,
- IPM_SETADDRESS,
- 0, d->publicIP);
-
- EnableWindow(GetDlgItem(hwnd, IDC_NCK5_PUBLICIP), !d->addressless);
-
- d->sync = old_sync;
- }
- break;
-
- case WMNC_CREDTEXT_LINK:
- {
- k5_dlg_data * d;
- khui_htwnd_link * l;
- khui_new_creds * nc;
- wchar_t linktext[128];
-
- d = (k5_dlg_data *)(LONG_PTR)
- GetWindowLongPtr(hwnd, DWLP_USER);
- nc = d->nc;
- l = (khui_htwnd_link *) lParam;
-
- if (!l)
- break;
-
- StringCchCopyN(linktext, ARRAYLENGTH(linktext),
- l->id, l->id_len);
-
- if (!wcscmp(linktext, L"Krb5Cred:!Passwd")) {
- return k5_force_password_change(d);
- }
- }
- 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)
- PFREE(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 &&
- !d->pwd_change) {
-
- 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 = PMALLOC(cbsize);
-
- StringCbCopy(nct->credtext, cbsize, sbuf);
- } else if (nc->n_identities > 0 &&
- (nc->subtype == KMSG_CRED_PASSWORD ||
- (nc->subtype == KMSG_CRED_NEW_CREDS && d->pwd_change))) {
- 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 = PMALLOC(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 = PMALLOC(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->sync && d->nc->result == KHUI_NC_RESULT_PROCESS) {
- kmq_post_sub_msg(k5_sub, KMSG_CRED,
- KMSG_CRED_DIALOG_NEW_OPTIONS,
- 0, (void *) d->nc);
- }
- }
- break;
-
- case K5_SET_CRED_MSG:
- {
- k5_dlg_data * d;
- khm_size cb;
- wchar_t * msg;
-
- d = (k5_dlg_data *) (LONG_PTR)
- GetWindowLongPtr(hwnd, DWLP_USER);
-
- msg = (wchar_t *) lParam;
-
- if (d->cred_message) {
- PFREE(d->cred_message);
- d->cred_message = NULL;
- }
-
- if (msg &&
- SUCCEEDED(StringCbLength(msg,
- KHUI_MAXCB_MESSAGE,
- &cb))) {
- cb += sizeof(wchar_t);
- d->cred_message = PMALLOC(cb);
-#ifdef DEBUG
- assert(d->cred_message);
-#endif
- StringCbCopy(d->cred_message, cb, msg);
- }
- }
- break;
- }
-
- return 0;
-}
-
-INT_PTR
-k5_handle_wm_notify(HWND hwnd,
- WPARAM wParam,
- LPARAM lParam) {
- LPNMHDR pnmh;
- k5_dlg_data * d;
-
- pnmh = (LPNMHDR) lParam;
- if (pnmh->idFrom == IDC_NCK5_PUBLICIP &&
- pnmh->code == IPN_FIELDCHANGED) {
-
- d = (k5_dlg_data *) (LONG_PTR) GetWindowLongPtr(hwnd, DWLP_USER);
-
- SendDlgItemMessage(hwnd, IDC_NCK5_PUBLICIP,
- IPM_GETADDRESS,
- 0, (LPARAM) &d->publicIP);
-
- d->dirty = TRUE;
- d->sync = FALSE;
-
- return TRUE;
- }
-
- 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;
- d->sync = FALSE;
- } else if(notif == BN_CLICKED && cid == IDC_NCK5_FORWARDABLE) {
- int c;
- c = (int) SendDlgItemMessage(hwnd, IDC_NCK5_FORWARDABLE,
- BM_GETCHECK, 0, 0);
- if(c==BST_CHECKED) {
- d->forwardable = TRUE;
- } else {
- d->forwardable = FALSE;
- }
- d->dirty = TRUE;
- d->sync = FALSE;
- } else if (notif == BN_CLICKED && cid == IDC_NCK5_ADDRESS) {
- int c;
-
- c = (int) SendDlgItemMessage(hwnd, IDC_NCK5_ADDRESS,
- BM_GETCHECK, 0, 0);
-
- if (c==BST_CHECKED) {
- d->addressless = TRUE;
- } else {
- d->addressless = FALSE;
- }
- d->dirty = TRUE;
- d->sync = FALSE;
-
- EnableWindow(GetDlgItem(hwnd, IDC_NCK5_PUBLICIP), !d->addressless);
- } else if (notif == EN_CHANGE && (cid == IDC_NCK5_RENEW_EDIT ||
- cid == IDC_NCK5_LIFETIME_EDIT)) {
- d->dirty = TRUE;
- d->sync = FALSE;
- } 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_NOTIFY:
- return k5_handle_wm_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()) {
- g_fjob.code = KRB5KRB_AP_ERR_BAD_INTEGRITY;
- goto _switch_to_main;
- }
- }
-
-#ifdef DEBUG
- /* log the state of g_fjob.* */
- _reportf(L"g_fjob state prior to calling khm_krb5_kinit() :");
- _reportf(L" g_fjob.principal = [%S]", g_fjob.principal);
- _reportf(L" g_fjob.code = %d", g_fjob.code);
- _reportf(L" g_fjob.state = %d", g_fjob.state);
- _reportf(L" g_fjob.prompt_set= %d", g_fjob.prompt_set);
- _reportf(L" g_fjob.valid_principal = %d", (int) g_fjob.valid_principal);
-#endif
-
- /* If we don't know if we have a valid principal, we
- restrict the options that are set when we call kinit.
- This way we will be able to use the response from the
- KDC to verify the principal. */
-
- g_fjob.retry_if_valid_principal = (g_fjob.forwardable ||
- g_fjob.proxiable ||
- g_fjob.renewable);
-
- retry_kinit:
- g_fjob.code =
- khm_krb5_kinit(0,
- g_fjob.principal,
- g_fjob.password,
- g_fjob.ccache,
- g_fjob.lifetime,
- g_fjob.valid_principal ? g_fjob.forwardable : 0,
- g_fjob.valid_principal ? g_fjob.proxiable : 0,
- (g_fjob.valid_principal && g_fjob.renewable ? g_fjob.renew_life : 0),
- g_fjob.addressless,
- g_fjob.publicIP,
- k5_kinit_prompter,
- &g_fjob);
-
- /* If the principal was found to be valid, and if we
- restricted the options that were being passed to kinit,
- then we need to retry the kinit call. This time we use
- the real options. */
- if (g_fjob.state == FIBER_STATE_RETRY_KINIT) {
-#ifdef DEBUG
- assert(g_fjob.valid_principal);
-#endif
- g_fjob.state = FIBER_STATE_KINIT;
- goto retry_kinit;
- }
- }
-
- _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;
- khm_int64 iexpiry;
- FILETIME expiry;
- FILETIME current;
-
-#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;
-
- if (KHM_SUCCEEDED(khc_read_int64(csp_prcache, L"ExpiresOn", &iexpiry))) {
- /* has the cache expired? */
- expiry = IntToFt(iexpiry);
- GetSystemTimeAsFileTime(¤t);
-
- if (CompareFileTime(&expiry, ¤t) < 0)
- /* already expired */
- goto _cleanup;
- } else {
- /* if there is no value for ExpiresOn, we assume the prompts
- have already expired. */
- goto _cleanup;
- }
-
- /* we found a prompt cache. We take this to imply that the
- principal is valid. */
- g_fjob.valid_principal = TRUE;
-
- /* 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;
-
-#ifdef DEBUG
- _reportf(L"k5_kinit_prompter() received %d prompts with name=[%S] banner=[%S]",
- num_prompts,
- name, banner);
- for (i=0; i < num_prompts; i++) {
- _reportf(L"Prompt[%d]: string[%S]", i, prompts[i].prompt);
- }
-#endif
-
- /* we got prompts? Then we assume that the principal is valid */
-
- if (!g_fjob.valid_principal) {
- g_fjob.valid_principal = TRUE;
-
- /* if the flags that were used to call kinit were restricted
- because we didn't know the validity of the principal, then
- we need to go back and retry the call with the correct
- flags. */
- if (g_fjob.retry_if_valid_principal) {
- _reportf(L"Retrying kinit call due to restricted flags on first call.");
- g_fjob.state = FIBER_STATE_RETRY_KINIT;
- return KRB5_LIBOS_PWDINTR;
- }
- }
-
- 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];
- FILETIME current;
- FILETIME lifetime;
- FILETIME expiry;
- khm_int64 iexpiry;
- khm_int32 t = 0;
-
- 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 (csp_prcache) {
-
- if (banner)
- khc_write_string(csp_prcache,
- L"Banner",
- wbanner);
- else
- khc_write_string(csp_prcache,
- L"Banner",
- L"");
-
- if (name)
- khc_write_string(csp_prcache,
- L"Name",
- wname);
- else if (csp_prcache)
- khc_write_string(csp_prcache,
- L"Name",
- L"");
-
- khc_write_int32(csp_prcache,
- L"PromptCount",
- (khm_int32) num_prompts);
-
- GetSystemTimeAsFileTime(¤t);
-#ifdef USE_PROMPT_CACHE_LIFETIME
- khc_read_int32(csp_params, L"PromptCacheLifetime", &t);
- if (t == 0)
- t = 172800; /* 48 hours */
-#else
- khc_read_int32(csp_params, L"MaxRenewLifetime", &t);
- if (t == 0)
- t = 2592000; /* 30 days */
- t += 604800; /* + 7 days */
-#endif
- TimetToFileTimeInterval(t, &lifetime);
- expiry = FtAdd(¤t, &lifetime);
- iexpiry = FtToInt(&expiry);
-
- khc_write_int64(csp_prcache, L"ExpiresOn", iexpiry);
- }
- }
-
- 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 = KRB5_LIBOS_PWDINTR;
- 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 KRB5_LIBOS_PWDINTR;
- else
- return code;
-}
-
-
-void
-k5_read_dlg_params(k5_dlg_data * d, khm_handle identity)
-{
- k5_params p;
-
- khm_krb5_get_identity_params(identity, &p);
-
- d->renewable = p.renewable;
- d->forwardable = p.forwardable;
- d->proxiable = p.proxiable;
- d->addressless = p.addressless;
- d->publicIP = p.publicIP;
-
- d->tc_lifetime.current = p.lifetime;
- d->tc_lifetime.max = p.lifetime_max;
- d->tc_lifetime.min = p.lifetime_min;
-
- d->tc_renew.current = p.renew_life;
- d->tc_renew.max = p.renew_life_max;
- d->tc_renew.min = p.renew_life_min;
-
- /* 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;
- d->sync = FALSE;
-}
-
-void
-k5_write_dlg_params(k5_dlg_data * d, khm_handle identity)
-{
-
- k5_params p;
-
- ZeroMemory(&p, sizeof(p));
-
- p.source_reg = K5PARAM_FM_ALL; /* we want to write all the
- settings to the registry, if
- necessary. */
-
- p.renewable = d->renewable;
- p.forwardable = d->forwardable;
- p.proxiable = d->proxiable;
- p.addressless = d->addressless;
- p.publicIP = d->publicIP;
-
- p.lifetime = (krb5_deltat) d->tc_lifetime.current;
- p.lifetime_max = (krb5_deltat) d->tc_lifetime.max;
- p.lifetime_min = (krb5_deltat) d->tc_lifetime.min;
-
- p.renew_life = (krb5_deltat) d->tc_renew.current;
- p.renew_life_max = (krb5_deltat) d->tc_renew.max;
- p.renew_life_min = (krb5_deltat) d->tc_renew.min;
-
- khm_krb5_set_identity_params(identity, &p);
-
- /* as in k5_read_dlg_params, once we write the data in, the local
- data is no longer dirty */
- d->dirty = FALSE;
-}
-
-void
-k5_free_kinit_job(void)
-{
- if (g_fjob.principal)
- PFREE(g_fjob.principal);
-
- if (g_fjob.password)
- PFREE(g_fjob.password);
-
- if (g_fjob.identity)
- kcdb_identity_release(g_fjob.identity);
-
- if (g_fjob.ccache)
- PFREE(g_fjob.ccache);
-
- ZeroMemory(&g_fjob, sizeof(g_fjob));
-}
-
-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);
-
- if (!d)
- return;
-
- 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++;
-
- k5_free_kinit_job();
-
- g_fjob.command = FIBER_CMD_KINIT;
- g_fjob.nc = nc;
- g_fjob.nct = nct;
- g_fjob.dialog = nct->hwnd_panel;
- g_fjob.principal = PMALLOC(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 = d->publicIP;
- g_fjob.code = 0;
- g_fjob.identity = ident;
- g_fjob.prompt_set = 0;
- g_fjob.valid_principal = FALSE;
- g_fjob.retry_if_valid_principal = FALSE;
-
- /* the value for
- retry_if_valid_principal is not
- necessarily the correct value here,
- but the correct value will be
- assigned k5_kinit_fiber_proc(). */
-
- /* 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 = PMALLOC(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 */
-}
-
-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) &&
- !(f & KCDB_CRED_FLAG_EXPIRED))
- rv = 1;
- else
- rv = 0;
-
- if (cident)
- kcdb_identity_release(cident);
-
- return rv;
-}
-
-khm_int32
-k5_remove_from_LRU(khm_handle identity)
-{
- wchar_t * wbuf = NULL;
- wchar_t idname[KCDB_IDENT_MAXCCH_NAME];
- khm_size cb;
- khm_size cb_ms;
- khm_int32 rv = KHM_ERROR_SUCCESS;
-
- cb = sizeof(idname);
- rv = kcdb_identity_get_name(identity, idname, &cb);
- assert(rv == KHM_ERROR_SUCCESS);
-
- rv = khc_read_multi_string(csp_params, L"LRUPrincipals", NULL, &cb_ms);
- if (rv != KHM_ERROR_TOO_LONG)
- cb_ms = sizeof(wchar_t) * 2;
-
- wbuf = PMALLOC(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) {
- multi_string_delete(wbuf, idname, KHM_CASE_SENSITIVE);
- }
- } else {
- multi_string_init(wbuf, cb_ms);
- }
-
- rv = khc_write_multi_string(csp_params, L"LRUPrincipals", wbuf);
-
- if (wbuf)
- PFREE(wbuf);
-
- return rv;
-}
-
-khm_int32
-k5_update_LRU(khm_handle identity)
-{
- wchar_t * wbuf = NULL;
- wchar_t * idname = NULL;
- wchar_t * realm = NULL;
- khm_size cb;
- khm_size cb_ms;
- khm_int32 rv = KHM_ERROR_SUCCESS;
-
- rv = kcdb_identity_get_name(identity, NULL, &cb);
- assert(rv == KHM_ERROR_TOO_LONG);
-
- idname = PMALLOC(cb);
- assert(idname);
-
- rv = kcdb_identity_get_name(identity, 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 = PMALLOC(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. We remove it here and add it at
- the top of the LRU list. */
- multi_string_delete(wbuf, idname, KHM_CASE_SENSITIVE);
- }
- } 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);
-
- realm = khm_get_realm_from_princ(idname);
- if (realm == NULL || *realm == L'\0')
- goto _done_with_LRU;
-
- cb = cb_ms;
- rv = khc_read_multi_string(csp_params, L"LRURealms", wbuf, &cb);
-
- if (rv == KHM_ERROR_TOO_LONG) {
- PFREE(wbuf);
- wbuf = PMALLOC(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, realm, KHM_CASE_SENSITIVE) != NULL) {
- /* remove the realm and add it at the top later. */
- multi_string_delete(wbuf, realm, KHM_CASE_SENSITIVE);
- }
- } else {
- multi_string_init(wbuf, cb_ms);
- }
-
- cb = cb_ms;
- rv = multi_string_prepend(wbuf, &cb, realm);
-
- if (rv == KHM_ERROR_TOO_LONG) {
- wbuf = PREALLOC(wbuf, cb);
-
- rv = multi_string_prepend(wbuf, &cb, realm);
-
- assert(KHM_SUCCEEDED(rv));
- }
-
- rv = khc_write_multi_string(csp_params, L"LRURealms", wbuf);
-
- assert(KHM_SUCCEEDED(rv));
-
- _done_with_LRU:
-
- if (wbuf)
- PFREE(wbuf);
- if (idname)
- PFREE(idname);
-
- 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 = PMALLOC(sizeof(*nct));
- ZeroMemory(nct, sizeof(*nct));
-
- nct->type = credtype_id_krb5;
- nct->ordinal = 1;
-
- LoadString(hResModule, IDS_KRB5_NC_NAME,
- wbuf, ARRAYLENGTH(wbuf));
- StringCbLength(wbuf, sizeof(wbuf), &cbsize);
- cbsize += sizeof(wchar_t);
-
- nct->name = PMALLOC(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 = PMALLOC(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);
-
- /* this can be NULL if the dialog was closed while the
- plug-in thread was processing. */
- if (d == NULL)
- break;
-
- 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) {
- for (t = realms; t && *t; t = multi_string_next(t)) {
- SendDlgItemMessage(hwnd, IDC_NCK5_REALM,
- CB_ADDSTRING,
- 0, (LPARAM) t);
- }
- PFREE(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);
- PFREE(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(d, NULL);
- }
-
- 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);
-
- if (d == NULL)
- break;
-
- /* we only load the identity specific defaults if the user
- hasn't changed the options */
- khui_cw_lock_nc(nc);
-
- /* ?: It might be better to not load identity defaults if
- the user has already changed options in the dialog. */
- if(/* !d->dirty && */ nc->n_identities > 0 &&
- nc->subtype == KMSG_CRED_NEW_CREDS) {
-
- k5_read_dlg_params(d, nc->identities[0]);
-
- PostMessage(nct->hwnd_panel, KHUI_WM_NC_NOTIFY,
- MAKEWPARAM(0,WMNC_DIALOG_SETUP), 0);
- }
-
- khui_cw_unlock_nc(nc);
-
- /* reset the force-password-change flag if this is a new
- identity. */
- d->pwd_change = FALSE;
- }
-
- /* 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 (d == NULL)
- break;
-
- 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 we are forcing a password change, then we don't do
- anything here. Note that if the identity changed, then
- this field would have been reset, so we would proceed
- as usual. */
- if (d->pwd_change)
- return KHM_ERROR_SUCCESS;
-
-#if 0
- /* Clearing the prompts at this point is a bad idea since
- the prompter depends on the prompts to know if this set
- of prompts is the same as the new set and if so, use
- the values entered in the old prompts as responses to
- the new one. */
- khui_cw_clear_prompts(nc);
-#endif
-
- /* 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);
-
- /* after the switch to the fiber, the dialog will be
- back in sync with the kinit thread. */
- d->sync = TRUE;
-
- 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;
-
- /* Special case. If the users' password has
- expired, we force a password change dialog on
- top of the new credentials dialog using a set
- of custom prompts, but only if we are the
- identity provider. */
- if (g_fjob.code == KRB5KDC_ERR_KEY_EXP &&
- is_k5_identpro) {
-
- k5_force_password_change(d);
- goto done_with_bad_princ;
-
- }
-
- /* we can't possibly have succeeded without a
- password */
- if(g_fjob.code == KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN &&
- is_k5_identpro) {
- kcdb_identity_set_flags(ident,
- KCDB_IDENT_FLAG_INVALID,
- KCDB_IDENT_FLAG_INVALID);
-
- khui_cw_clear_prompts(nc);
- }
-
- if (d->cred_message) {
- PFREE(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 = PMALLOC(cb);
- StringCbCopy(d->cred_message, cb, msg);
- }
-
- done_with_bad_princ:
-
- k5_free_kinit_job();
-
- if (is_k5_identpro)
- kcdb_identity_set_flags(ident,
- KCDB_IDENT_FLAG_UNKNOWN,
- KCDB_IDENT_FLAG_UNKNOWN);
-
-
- } 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,
- 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 = 0;
-
- 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;
- if (d == NULL)
- break;
-
- if (d->pwd_change) {
- /* we are forcing a password change */
- goto change_password;
- }
-
- _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;
-
- _reportf(L"Cancelling");
- } else if (nc->result == KHUI_NC_RESULT_PROCESS) {
- 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_PROCESS) {
- /* 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)))) {
- _reportf(L"No password entered, but a valid TGT exists. Continuing");
- g_fjob.code = 0;
- } else if (g_fjob.state == FIBER_STATE_NONE &&
- g_fjob.code == 0 &&
- nc->n_identities > 0 &&
- nc->identities[0] != NULL) {
-
- /* we had a password and we used it to get
- tickets. We should reset the IMPORTED flag now
- since the tickets are not imported. */
-
- khm_krb5_set_identity_flags(nc->identities[0],
- K5IDFLAG_IMPORTED,
- 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
-
- if (g_fjob.valid_principal &&
- nc->n_identities > 0 &&
- nc->identities[0]) {
- /* the principal was valid, so we can go ahead
- and update the LRU */
- k5_update_LRU(nc->identities[0]);
- }
-
- } else if (nc->result == KHUI_NC_RESULT_PROCESS &&
- g_fjob.state == FIBER_STATE_NONE) {
- krb5_context ctx = NULL;
-
- _reportf(L"Tickets successfully acquired");
-
- 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]);
-
- k5_write_dlg_params(d, nc->identities[0]);
-
- /* 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);
-
- if (nc->set_default) {
- _reportf(L"Setting default identity");
- kcdb_identity_set_default(nc->identities[0]);
- }
-
- /* If there is no default identity, then make this the default */
- kcdb_identity_refresh(nc->identities[0]);
- {
- khm_handle tdefault = NULL;
-
- if (KHM_SUCCEEDED(kcdb_identity_get_default(&tdefault))) {
- kcdb_identity_release(tdefault);
- } else {
- _reportf(L"There was no default identity. Setting default");
- kcdb_identity_set_default(nc->identities[0]);
- }
- }
-
- /* and update the LRU */
- k5_update_LRU(nc->identities[0]);
-
- if (ctx != NULL)
- pkrb5_free_context(ctx);
- } 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) {
-
- FILETIME ftidexp = {0,0};
- FILETIME ftcurrent;
- khm_size cb;
-
- GetSystemTimeAsFileTime(&ftcurrent);
-
- _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) ||
- (nc->ctx.scope == KHUI_SCOPE_CRED &&
- nc->ctx.cred_type == credtype_id_krb5)) {
- int code;
-
- if (nc->ctx.scope == KHUI_SCOPE_CRED &&
- nc->ctx.cred != NULL) {
-
- /* get the expiration time for the identity first. */
- cb = sizeof(ftidexp);
-#ifdef DEBUG
- assert(nc->ctx.identity != NULL);
-#endif
- kcdb_identity_get_attr(nc->ctx.identity,
- KCDB_ATTR_EXPIRE,
- NULL,
- &ftidexp,
- &cb);
-
- code = khm_krb5_renew_cred(nc->ctx.cred);
-
- } else if (nc->ctx.scope == KHUI_SCOPE_IDENT &&
- nc->ctx.identity != 0) {
- /* get the current identity expiration time */
- cb = sizeof(ftidexp);
-
- kcdb_identity_get_attr(nc->ctx.identity,
- KCDB_ATTR_EXPIRE,
- NULL,
- &ftidexp,
- &cb);
-
- code = khm_krb5_renew_ident(nc->ctx.identity);
- } else {
-
- _reportf(L"No identity specified. Can't renew Kerberos tickets");
-
- code = 1; /* it just has to be non-zero */
- }
-
- if (code == 0) {
- _reportf(L"Tickets successfully renewed");
-
- 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 if (CompareFileTime(&ftcurrent, &ftidexp) < 0) {
- wchar_t tbuf[1024];
- DWORD suggestion;
- kherr_suggestion sug_id;
-
- /* if we failed to get new tickets, but the
- identity is still valid, then we assume that
- the current tickets are still good enough
- for other credential types to obtain their
- credentials. */
-
- khm_err_describe(code, tbuf, sizeof(tbuf),
- &suggestion, &sug_id);
-
- _report_cs0(KHERR_WARNING, tbuf);
- if (suggestion)
- _suggest_mr(suggestion, sug_id);
-
- _resolve();
-
- khui_cw_set_response(nc, credtype_id_krb5,
- KHUI_NC_RESPONSE_EXIT |
- KHUI_NC_RESPONSE_SUCCESS);
- } 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_PROCESS) {
-
- change_password:
- /* we jump here if there was a password change forced */
-
- _begin_task(0);
- _report_mr0(KHERR_NONE, MSG_CTX_PASSWD);
- _describe();
-
- khui_cw_lock_nc(nc);
-
- if (nc->result == KHUI_NC_RESULT_CANCEL) {
-
- khui_cw_set_response(nc, credtype_id_krb5,
- KHUI_NC_RESPONSE_SUCCESS |
- KHUI_NC_RESPONSE_EXIT);
-
- } else 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_PARAM;
- _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_PARAM;
- _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;
- else {
- khm_handle csp_idcfg = NULL;
- krb5_context ctx = NULL;
-
- /* we set a new password. now we need to get
- initial credentials. */
-
- d = (k5_dlg_data *) nct->aux;
-
- if (d == NULL) {
- rv = KHM_ERROR_UNKNOWN;
- goto _pwd_exit;
- }
-
- if (nc->subtype == KMSG_CRED_PASSWORD) {
- /* since this was just a password change,
- we need to load new credentials options
- from the configuration store. */
-
- k5_read_dlg_params(d, nc->identities[0]);
- }
-
- /* the password change phase is now done */
- d->pwd_change = FALSE;
-
-#ifdef DEBUG
- _reportf(L"Calling khm_krb5_kinit()");
-#endif
- code = khm_krb5_kinit(NULL, /* context (create one) */
- idname, /* principal_name */
- npwd, /* new password */
- NULL, /* ccache name (figure out the identity cc)*/
- (krb5_deltat) d->tc_lifetime.current,
- d->forwardable,
- d->proxiable,
- (krb5_deltat)((d->renewable)?d->tc_renew.current:0),
- d->addressless, /* addressless */
- d->publicIP, /* public IP */
- NULL, /* prompter */
- NULL /* prompter data */);
-
- if (code) {
- rv = KHM_ERROR_UNKNOWN;
- goto _pwd_exit;
- }
-
- /* save the settings that we used for
- obtaining the ticket. */
- if (nc->subtype == KMSG_CRED_NEW_CREDS) {
-
- k5_write_dlg_params(d, nc->identities[0]);
-
- /* and then update the LRU too */
- k5_update_LRU(nc->identities[0]);
- }
-
- /* and do a quick refresh of the krb5 tickets
- so that other plug-ins that depend on krb5
- can look up tickets inside NetIDMgr */
- khm_krb5_list_tickets(&ctx);
-
- /* if there was no default identity, we make
- this one the default. */
- kcdb_identity_refresh(nc->identities[0]);
- {
- khm_handle tdefault = NULL;
-
- if (KHM_SUCCEEDED(kcdb_identity_get_default(&tdefault))) {
- kcdb_identity_release(tdefault);
- } else {
- _reportf(L"There was no default identity. Setting defualt");
- kcdb_identity_set_default(nc->identities[0]);
- }
- }
-
- if (ctx != NULL)
- pkrb5_free_context(ctx);
-
- if (nc->subtype == KMSG_CRED_PASSWORD) {
- /* if we obtained new credentials as a
- result of successfully changing the
- password, we also schedule an identity
- renewal for this identity. This allows
- the other credential types to obtain
- credentials for this identity. */
- khui_action_context ctx;
-
- _reportf(L"Scheduling renewal of [%s] after password change",
- widname);
-
- khui_context_create(&ctx,
- KHUI_SCOPE_IDENT,
- nc->identities[0],
- KCDB_CREDTYPE_INVALID,
- NULL);
- khui_action_trigger(KHUI_ACTION_RENEW_CRED,
- &ctx);
-
- khui_context_release(&ctx);
- }
- }
-
- /* result is only set when code != 0 */
- if (code && result) {
- size_t len;
-
- StringCchLengthA(result, KHERR_MAXCCH_STRING,
- &len);
- wresult = PMALLOC((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();
-
- PFREE(result);
- PFREE(wresult);
-
- /* 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)
- PFREE(nct->name);
- if (nct->credtext)
- PFREE(nct->credtext);
-
- PFREE(nct);
-
- k5_free_kinit_job();
- }
- break;
-
- case KMSG_CRED_IMPORT:
- {
- khm_int32 t = 0;
-
-#ifdef DEBUG
- assert(csp_params);
-#endif
- khc_read_int32(csp_params, L"MsLsaImport", &t);
-
- if (t != K5_LSAIMPORT_NEVER) {
- krb5_context ctx = NULL;
- khm_handle id_default = NULL;
- khm_handle id_imported = NULL;
- BOOL imported;
-
- imported = khm_krb5_ms2mit(NULL, (t == K5_LSAIMPORT_MATCH), TRUE,
- &id_imported);
- if (imported) {
- khm_krb5_list_tickets(&ctx);
-
- if (ctx)
- pkrb5_free_context(ctx);
-
- kcdb_identity_refresh(id_imported);
-
- if (KHM_SUCCEEDED(kcdb_identity_get_default(&id_default))) {
- kcdb_identity_release(id_default);
- id_default = NULL;
- } else {
- _reportf(L"There was no default identity. Setting default");
- kcdb_identity_set_default(id_imported);
- }
-
- /* and update the LRU */
- k5_update_LRU(id_imported);
- }
-
- if (id_imported)
- kcdb_identity_release(id_imported);
- }
- }
- break;
- }
-
- return rv;
-}
+/* + * Copyright (c) 2006 Secure Endpoints Inc. + * + * 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<commctrl.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; /* is the data in sync with the + configuration store? */ + BOOL sync; /* is the data in sync with the kinit + request? */ + DWORD renewable; + DWORD forwardable; + DWORD proxiable; + DWORD addressless; + DWORD publicIP; + + wchar_t * cred_message; /* overrides the credential text, if + non-NULL */ + BOOL pwd_change; /* force a password change */ +} 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 = PMALLOC(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); + + if (!d) + return TRUE; + + 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); + } + + PFREE(d); + + return TRUE; +} + +LRESULT +k5_force_password_change(k5_dlg_data * d) { + /* we are turning this dialog into a change password dialog... */ + wchar_t wbuf[KHUI_MAXCCH_BANNER]; + + khui_cw_clear_prompts(d->nc); + + LoadString(hResModule, IDS_NC_PWD_BANNER, + wbuf, ARRAYLENGTH(wbuf)); + khui_cw_begin_custom_prompts(d->nc, 3, NULL, wbuf); + + LoadString(hResModule, IDS_NC_PWD_PWD, + wbuf, ARRAYLENGTH(wbuf)); + khui_cw_add_prompt(d->nc, KHUI_NCPROMPT_TYPE_PASSWORD, + wbuf, NULL, KHUI_NCPROMPT_FLAG_HIDDEN); + + LoadString(hResModule, IDS_NC_PWD_NPWD, + wbuf, ARRAYLENGTH(wbuf)); + khui_cw_add_prompt(d->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(d->nc, KHUI_NCPROMPT_TYPE_NEW_PASSWORD_AGAIN, + wbuf, NULL, KHUI_NCPROMPT_FLAG_HIDDEN); + + d->pwd_change = TRUE; + + if (is_k5_identpro && + d->nc->n_identities > 0 && + d->nc->identities[0]) { + + kcdb_identity_set_flags(d->nc->identities[0], + KCDB_IDENT_FLAG_VALID, + KCDB_IDENT_FLAG_VALID); + + } + + PostMessage(d->nc->hwnd, KHUI_WM_NC_NOTIFY, + MAKEWPARAM(0, WMNC_UPDATE_CREDTEXT), + (LPARAM) d->nc); + + 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; + BOOL old_sync; + + d = (k5_dlg_data *)(LONG_PTR) + GetWindowLongPtr(hwnd, DWLP_USER); + + if (d->nc->subtype == KMSG_CRED_PASSWORD) + return TRUE; + + /* we save the value of the 'sync' field here because some + of the notifications that are generated while setting + the controls overwrite the field. */ + old_sync = d->sync; + + /* need to update the controls with d->* */ + SendDlgItemMessage(hwnd, IDC_NCK5_RENEWABLE, + BM_SETCHECK, + (d->renewable? BST_CHECKED : BST_UNCHECKED), + 0); + EnableWindow(GetDlgItem(hwnd, IDC_NCK5_RENEW_EDIT), + !!d->renewable); + + khui_tracker_refresh(&d->tc_lifetime); + khui_tracker_refresh(&d->tc_renew); + + SendDlgItemMessage(hwnd, IDC_NCK5_FORWARDABLE, + BM_SETCHECK, + (d->forwardable ? BST_CHECKED : BST_UNCHECKED), + 0); + + SendDlgItemMessage(hwnd, IDC_NCK5_ADDRESS, + BM_SETCHECK, + (d->addressless ? BST_CHECKED : BST_UNCHECKED), + 0); + + SendDlgItemMessage(hwnd, IDC_NCK5_PUBLICIP, + IPM_SETADDRESS, + 0, d->publicIP); + + EnableWindow(GetDlgItem(hwnd, IDC_NCK5_PUBLICIP), !d->addressless); + + d->sync = old_sync; + } + break; + + case WMNC_CREDTEXT_LINK: + { + k5_dlg_data * d; + khui_htwnd_link * l; + khui_new_creds * nc; + wchar_t linktext[128]; + + d = (k5_dlg_data *)(LONG_PTR) + GetWindowLongPtr(hwnd, DWLP_USER); + nc = d->nc; + l = (khui_htwnd_link *) lParam; + + if (!l) + break; + + StringCchCopyN(linktext, ARRAYLENGTH(linktext), + l->id, l->id_len); + + if (!wcscmp(linktext, L"Krb5Cred:!Passwd")) { + return k5_force_password_change(d); + } + } + 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) + PFREE(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 && + !d->pwd_change) { + + 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 = PMALLOC(cbsize); + + StringCbCopy(nct->credtext, cbsize, sbuf); + } else if (nc->n_identities > 0 && + (nc->subtype == KMSG_CRED_PASSWORD || + (nc->subtype == KMSG_CRED_NEW_CREDS && d->pwd_change))) { + 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 = PMALLOC(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 = PMALLOC(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->sync && d->nc->result == KHUI_NC_RESULT_PROCESS) { + kmq_post_sub_msg(k5_sub, KMSG_CRED, + KMSG_CRED_DIALOG_NEW_OPTIONS, + 0, (void *) d->nc); + } + } + break; + + case K5_SET_CRED_MSG: + { + k5_dlg_data * d; + khm_size cb; + wchar_t * msg; + + d = (k5_dlg_data *) (LONG_PTR) + GetWindowLongPtr(hwnd, DWLP_USER); + + msg = (wchar_t *) lParam; + + if (d->cred_message) { + PFREE(d->cred_message); + d->cred_message = NULL; + } + + if (msg && + SUCCEEDED(StringCbLength(msg, + KHUI_MAXCB_MESSAGE, + &cb))) { + cb += sizeof(wchar_t); + d->cred_message = PMALLOC(cb); +#ifdef DEBUG + assert(d->cred_message); +#endif + StringCbCopy(d->cred_message, cb, msg); + } + } + break; + } + + return 0; +} + +INT_PTR +k5_handle_wm_notify(HWND hwnd, + WPARAM wParam, + LPARAM lParam) { + LPNMHDR pnmh; + k5_dlg_data * d; + + pnmh = (LPNMHDR) lParam; + if (pnmh->idFrom == IDC_NCK5_PUBLICIP && + pnmh->code == IPN_FIELDCHANGED) { + + d = (k5_dlg_data *) (LONG_PTR) GetWindowLongPtr(hwnd, DWLP_USER); + + SendDlgItemMessage(hwnd, IDC_NCK5_PUBLICIP, + IPM_GETADDRESS, + 0, (LPARAM) &d->publicIP); + + d->dirty = TRUE; + d->sync = FALSE; + + return TRUE; + } + + 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; + d->sync = FALSE; + } else if(notif == BN_CLICKED && cid == IDC_NCK5_FORWARDABLE) { + int c; + c = (int) SendDlgItemMessage(hwnd, IDC_NCK5_FORWARDABLE, + BM_GETCHECK, 0, 0); + if(c==BST_CHECKED) { + d->forwardable = TRUE; + } else { + d->forwardable = FALSE; + } + d->dirty = TRUE; + d->sync = FALSE; + } else if (notif == BN_CLICKED && cid == IDC_NCK5_ADDRESS) { + int c; + + c = (int) SendDlgItemMessage(hwnd, IDC_NCK5_ADDRESS, + BM_GETCHECK, 0, 0); + + if (c==BST_CHECKED) { + d->addressless = TRUE; + } else { + d->addressless = FALSE; + } + d->dirty = TRUE; + d->sync = FALSE; + + EnableWindow(GetDlgItem(hwnd, IDC_NCK5_PUBLICIP), !d->addressless); + } else if (notif == EN_CHANGE && (cid == IDC_NCK5_RENEW_EDIT || + cid == IDC_NCK5_LIFETIME_EDIT)) { + d->dirty = TRUE; + d->sync = FALSE; + } 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_NOTIFY: + return k5_handle_wm_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()) { + g_fjob.code = KRB5KRB_AP_ERR_BAD_INTEGRITY; + goto _switch_to_main; + } + } + +#ifdef DEBUG + /* log the state of g_fjob.* */ + _reportf(L"g_fjob state prior to calling khm_krb5_kinit() :"); + _reportf(L" g_fjob.principal = [%S]", g_fjob.principal); + _reportf(L" g_fjob.code = %d", g_fjob.code); + _reportf(L" g_fjob.state = %d", g_fjob.state); + _reportf(L" g_fjob.prompt_set= %d", g_fjob.prompt_set); + _reportf(L" g_fjob.valid_principal = %d", (int) g_fjob.valid_principal); +#endif + + /* If we don't know if we have a valid principal, we + restrict the options that are set when we call kinit. + This way we will be able to use the response from the + KDC to verify the principal. */ + + g_fjob.retry_if_valid_principal = (g_fjob.forwardable || + g_fjob.proxiable || + g_fjob.renewable); + + retry_kinit: + g_fjob.code = + khm_krb5_kinit(0, + g_fjob.principal, + g_fjob.password, + g_fjob.ccache, + g_fjob.lifetime, + g_fjob.valid_principal ? g_fjob.forwardable : 0, + g_fjob.valid_principal ? g_fjob.proxiable : 0, + (g_fjob.valid_principal && g_fjob.renewable ? g_fjob.renew_life : 0), + g_fjob.addressless, + g_fjob.publicIP, + k5_kinit_prompter, + &g_fjob); + + /* If the principal was found to be valid, and if we + restricted the options that were being passed to kinit, + then we need to retry the kinit call. This time we use + the real options. */ + if (g_fjob.state == FIBER_STATE_RETRY_KINIT) { +#ifdef DEBUG + assert(g_fjob.valid_principal); +#endif + g_fjob.state = FIBER_STATE_KINIT; + goto retry_kinit; + } + } + + _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; + khm_int64 iexpiry; + FILETIME expiry; + FILETIME current; + +#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; + + if (KHM_SUCCEEDED(khc_read_int64(csp_prcache, L"ExpiresOn", &iexpiry))) { + /* has the cache expired? */ + expiry = IntToFt(iexpiry); + GetSystemTimeAsFileTime(¤t); + + if (CompareFileTime(&expiry, ¤t) < 0) + /* already expired */ + goto _cleanup; + } else { + /* if there is no value for ExpiresOn, we assume the prompts + have already expired. */ + goto _cleanup; + } + + /* we found a prompt cache. We take this to imply that the + principal is valid. */ + g_fjob.valid_principal = TRUE; + + /* 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; + +#ifdef DEBUG + _reportf(L"k5_kinit_prompter() received %d prompts with name=[%S] banner=[%S]", + num_prompts, + name, banner); + for (i=0; i < num_prompts; i++) { + _reportf(L"Prompt[%d]: string[%S]", i, prompts[i].prompt); + } +#endif + + /* we got prompts? Then we assume that the principal is valid */ + + if (!g_fjob.valid_principal) { + g_fjob.valid_principal = TRUE; + + /* if the flags that were used to call kinit were restricted + because we didn't know the validity of the principal, then + we need to go back and retry the call with the correct + flags. */ + if (g_fjob.retry_if_valid_principal) { + _reportf(L"Retrying kinit call due to restricted flags on first call."); + g_fjob.state = FIBER_STATE_RETRY_KINIT; + return KRB5_LIBOS_PWDINTR; + } + } + + 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]; + FILETIME current; + FILETIME lifetime; + FILETIME expiry; + khm_int64 iexpiry; + khm_int32 t = 0; + + 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 (csp_prcache) { + + if (banner) + khc_write_string(csp_prcache, + L"Banner", + wbanner); + else + khc_write_string(csp_prcache, + L"Banner", + L""); + + if (name) + khc_write_string(csp_prcache, + L"Name", + wname); + else if (csp_prcache) + khc_write_string(csp_prcache, + L"Name", + L""); + + khc_write_int32(csp_prcache, + L"PromptCount", + (khm_int32) num_prompts); + + GetSystemTimeAsFileTime(¤t); +#ifdef USE_PROMPT_CACHE_LIFETIME + khc_read_int32(csp_params, L"PromptCacheLifetime", &t); + if (t == 0) + t = 172800; /* 48 hours */ +#else + khc_read_int32(csp_params, L"MaxRenewLifetime", &t); + if (t == 0) + t = 2592000; /* 30 days */ + t += 604800; /* + 7 days */ +#endif + TimetToFileTimeInterval(t, &lifetime); + expiry = FtAdd(¤t, &lifetime); + iexpiry = FtToInt(&expiry); + + khc_write_int64(csp_prcache, L"ExpiresOn", iexpiry); + } + } + + 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 = KRB5_LIBOS_PWDINTR; + 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 KRB5_LIBOS_PWDINTR; + else + return code; +} + + +void +k5_read_dlg_params(k5_dlg_data * d, khm_handle identity) +{ + k5_params p; + + khm_krb5_get_identity_params(identity, &p); + + d->renewable = p.renewable; + d->forwardable = p.forwardable; + d->proxiable = p.proxiable; + d->addressless = p.addressless; + d->publicIP = p.publicIP; + + d->tc_lifetime.current = p.lifetime; + d->tc_lifetime.max = p.lifetime_max; + d->tc_lifetime.min = p.lifetime_min; + + d->tc_renew.current = p.renew_life; + d->tc_renew.max = p.renew_life_max; + d->tc_renew.min = p.renew_life_min; + + /* 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; + d->sync = FALSE; +} + +void +k5_write_dlg_params(k5_dlg_data * d, khm_handle identity) +{ + + k5_params p; + + ZeroMemory(&p, sizeof(p)); + + p.source_reg = K5PARAM_FM_ALL; /* we want to write all the + settings to the registry, if + necessary. */ + + p.renewable = d->renewable; + p.forwardable = d->forwardable; + p.proxiable = d->proxiable; + p.addressless = d->addressless; + p.publicIP = d->publicIP; + + p.lifetime = (krb5_deltat) d->tc_lifetime.current; + p.lifetime_max = (krb5_deltat) d->tc_lifetime.max; + p.lifetime_min = (krb5_deltat) d->tc_lifetime.min; + + p.renew_life = (krb5_deltat) d->tc_renew.current; + p.renew_life_max = (krb5_deltat) d->tc_renew.max; + p.renew_life_min = (krb5_deltat) d->tc_renew.min; + + khm_krb5_set_identity_params(identity, &p); + + /* as in k5_read_dlg_params, once we write the data in, the local + data is no longer dirty */ + d->dirty = FALSE; +} + +void +k5_free_kinit_job(void) +{ + if (g_fjob.principal) + PFREE(g_fjob.principal); + + if (g_fjob.password) + PFREE(g_fjob.password); + + if (g_fjob.identity) + kcdb_identity_release(g_fjob.identity); + + if (g_fjob.ccache) + PFREE(g_fjob.ccache); + + ZeroMemory(&g_fjob, sizeof(g_fjob)); +} + +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); + + if (!d) + return; + + 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++; + + k5_free_kinit_job(); + + g_fjob.command = FIBER_CMD_KINIT; + g_fjob.nc = nc; + g_fjob.nct = nct; + g_fjob.dialog = nct->hwnd_panel; + g_fjob.principal = PMALLOC(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 = d->publicIP; + g_fjob.code = 0; + g_fjob.identity = ident; + g_fjob.prompt_set = 0; + g_fjob.valid_principal = FALSE; + g_fjob.retry_if_valid_principal = FALSE; + + /* the value for + retry_if_valid_principal is not + necessarily the correct value here, + but the correct value will be + assigned k5_kinit_fiber_proc(). */ + + /* 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 = PMALLOC(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 */ +} + +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) && + !(f & KCDB_CRED_FLAG_EXPIRED)) + rv = 1; + else + rv = 0; + + if (cident) + kcdb_identity_release(cident); + + return rv; +} + +khm_int32 +k5_remove_from_LRU(khm_handle identity) +{ + wchar_t * wbuf = NULL; + wchar_t idname[KCDB_IDENT_MAXCCH_NAME]; + khm_size cb; + khm_size cb_ms; + khm_int32 rv = KHM_ERROR_SUCCESS; + + cb = sizeof(idname); + rv = kcdb_identity_get_name(identity, idname, &cb); + assert(rv == KHM_ERROR_SUCCESS); + + rv = khc_read_multi_string(csp_params, L"LRUPrincipals", NULL, &cb_ms); + if (rv != KHM_ERROR_TOO_LONG) + cb_ms = sizeof(wchar_t) * 2; + + wbuf = PMALLOC(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) { + multi_string_delete(wbuf, idname, KHM_CASE_SENSITIVE); + } + } else { + multi_string_init(wbuf, cb_ms); + } + + rv = khc_write_multi_string(csp_params, L"LRUPrincipals", wbuf); + + if (wbuf) + PFREE(wbuf); + + return rv; +} + +khm_int32 +k5_update_LRU(khm_handle identity) +{ + wchar_t * wbuf = NULL; + wchar_t * idname = NULL; + wchar_t * realm = NULL; + khm_size cb; + khm_size cb_ms; + khm_int32 rv = KHM_ERROR_SUCCESS; + + rv = kcdb_identity_get_name(identity, NULL, &cb); + assert(rv == KHM_ERROR_TOO_LONG); + + idname = PMALLOC(cb); + assert(idname); + + rv = kcdb_identity_get_name(identity, 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 = PMALLOC(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. We remove it here and add it at + the top of the LRU list. */ + multi_string_delete(wbuf, idname, KHM_CASE_SENSITIVE); + } + } 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); + + realm = khm_get_realm_from_princ(idname); + if (realm == NULL || *realm == L'\0') + goto _done_with_LRU; + + cb = cb_ms; + rv = khc_read_multi_string(csp_params, L"LRURealms", wbuf, &cb); + + if (rv == KHM_ERROR_TOO_LONG) { + PFREE(wbuf); + wbuf = PMALLOC(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, realm, KHM_CASE_SENSITIVE) != NULL) { + /* remove the realm and add it at the top later. */ + multi_string_delete(wbuf, realm, KHM_CASE_SENSITIVE); + } + } else { + multi_string_init(wbuf, cb_ms); + } + + cb = cb_ms; + rv = multi_string_prepend(wbuf, &cb, realm); + + if (rv == KHM_ERROR_TOO_LONG) { + wbuf = PREALLOC(wbuf, cb); + + rv = multi_string_prepend(wbuf, &cb, realm); + + assert(KHM_SUCCEEDED(rv)); + } + + rv = khc_write_multi_string(csp_params, L"LRURealms", wbuf); + + assert(KHM_SUCCEEDED(rv)); + + _done_with_LRU: + + if (wbuf) + PFREE(wbuf); + if (idname) + PFREE(idname); + + 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 = PMALLOC(sizeof(*nct)); + ZeroMemory(nct, sizeof(*nct)); + + nct->type = credtype_id_krb5; + nct->ordinal = 1; + + LoadString(hResModule, IDS_KRB5_NC_NAME, + wbuf, ARRAYLENGTH(wbuf)); + StringCbLength(wbuf, sizeof(wbuf), &cbsize); + cbsize += sizeof(wchar_t); + + nct->name = PMALLOC(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 = PMALLOC(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); + + /* this can be NULL if the dialog was closed while the + plug-in thread was processing. */ + if (d == NULL) + break; + + 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) { + for (t = realms; t && *t; t = multi_string_next(t)) { + SendDlgItemMessage(hwnd, IDC_NCK5_REALM, + CB_ADDSTRING, + 0, (LPARAM) t); + } + PFREE(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); + PFREE(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(d, NULL); + } + + 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); + + if (d == NULL) + break; + + /* we only load the identity specific defaults if the user + hasn't changed the options */ + khui_cw_lock_nc(nc); + + /* ?: It might be better to not load identity defaults if + the user has already changed options in the dialog. */ + if(/* !d->dirty && */ nc->n_identities > 0 && + nc->subtype == KMSG_CRED_NEW_CREDS) { + + k5_read_dlg_params(d, nc->identities[0]); + + PostMessage(nct->hwnd_panel, KHUI_WM_NC_NOTIFY, + MAKEWPARAM(0,WMNC_DIALOG_SETUP), 0); + } + + khui_cw_unlock_nc(nc); + + /* reset the force-password-change flag if this is a new + identity. */ + d->pwd_change = FALSE; + } + + /* 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 (d == NULL) + break; + + 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 we are forcing a password change, then we don't do + anything here. Note that if the identity changed, then + this field would have been reset, so we would proceed + as usual. */ + if (d->pwd_change) + return KHM_ERROR_SUCCESS; + +#if 0 + /* Clearing the prompts at this point is a bad idea since + the prompter depends on the prompts to know if this set + of prompts is the same as the new set and if so, use + the values entered in the old prompts as responses to + the new one. */ + khui_cw_clear_prompts(nc); +#endif + + /* 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); + + /* after the switch to the fiber, the dialog will be + back in sync with the kinit thread. */ + d->sync = TRUE; + + 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; + + /* Special case. If the users' password has + expired, we force a password change dialog on + top of the new credentials dialog using a set + of custom prompts, but only if we are the + identity provider. */ + if (g_fjob.code == KRB5KDC_ERR_KEY_EXP && + is_k5_identpro) { + + k5_force_password_change(d); + goto done_with_bad_princ; + + } + + /* we can't possibly have succeeded without a + password */ + if(g_fjob.code == KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN && + is_k5_identpro) { + kcdb_identity_set_flags(ident, + KCDB_IDENT_FLAG_INVALID, + KCDB_IDENT_FLAG_INVALID); + + khui_cw_clear_prompts(nc); + } + + if (d->cred_message) { + PFREE(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 = PMALLOC(cb); + StringCbCopy(d->cred_message, cb, msg); + } + + done_with_bad_princ: + + k5_free_kinit_job(); + + if (is_k5_identpro) + kcdb_identity_set_flags(ident, + KCDB_IDENT_FLAG_UNKNOWN, + KCDB_IDENT_FLAG_UNKNOWN); + + + } 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, + 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 = 0; + + 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; + if (d == NULL) + break; + + if (d->pwd_change) { + /* we are forcing a password change */ + goto change_password; + } + + _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; + + _reportf(L"Cancelling"); + } else if (nc->result == KHUI_NC_RESULT_PROCESS) { + 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_PROCESS) { + /* 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)))) { + _reportf(L"No password entered, but a valid TGT exists. Continuing"); + g_fjob.code = 0; + } else if (g_fjob.state == FIBER_STATE_NONE && + g_fjob.code == 0 && + nc->n_identities > 0 && + nc->identities[0] != NULL) { + + /* we had a password and we used it to get + tickets. We should reset the IMPORTED flag now + since the tickets are not imported. */ + + khm_krb5_set_identity_flags(nc->identities[0], + K5IDFLAG_IMPORTED, + 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 + + if (g_fjob.valid_principal && + nc->n_identities > 0 && + nc->identities[0]) { + /* the principal was valid, so we can go ahead + and update the LRU */ + k5_update_LRU(nc->identities[0]); + } + + } else if (nc->result == KHUI_NC_RESULT_PROCESS && + g_fjob.state == FIBER_STATE_NONE) { + krb5_context ctx = NULL; + + _reportf(L"Tickets successfully acquired"); + + 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]); + + k5_write_dlg_params(d, nc->identities[0]); + + /* 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); + + if (nc->set_default) { + _reportf(L"Setting default identity"); + kcdb_identity_set_default(nc->identities[0]); + } + + /* If there is no default identity, then make this the default */ + kcdb_identity_refresh(nc->identities[0]); + { + khm_handle tdefault = NULL; + + if (KHM_SUCCEEDED(kcdb_identity_get_default(&tdefault))) { + kcdb_identity_release(tdefault); + } else { + _reportf(L"There was no default identity. Setting default"); + kcdb_identity_set_default(nc->identities[0]); + } + } + + /* and update the LRU */ + k5_update_LRU(nc->identities[0]); + + if (ctx != NULL) + pkrb5_free_context(ctx); + } 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) { + + FILETIME ftidexp = {0,0}; + FILETIME ftcurrent; + khm_size cb; + + GetSystemTimeAsFileTime(&ftcurrent); + + _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) || + (nc->ctx.scope == KHUI_SCOPE_CRED && + nc->ctx.cred_type == credtype_id_krb5)) { + int code; + + if (nc->ctx.scope == KHUI_SCOPE_CRED && + nc->ctx.cred != NULL) { + + /* get the expiration time for the identity first. */ + cb = sizeof(ftidexp); +#ifdef DEBUG + assert(nc->ctx.identity != NULL); +#endif + kcdb_identity_get_attr(nc->ctx.identity, + KCDB_ATTR_EXPIRE, + NULL, + &ftidexp, + &cb); + + code = khm_krb5_renew_cred(nc->ctx.cred); + + } else if (nc->ctx.scope == KHUI_SCOPE_IDENT && + nc->ctx.identity != 0) { + /* get the current identity expiration time */ + cb = sizeof(ftidexp); + + kcdb_identity_get_attr(nc->ctx.identity, + KCDB_ATTR_EXPIRE, + NULL, + &ftidexp, + &cb); + + code = khm_krb5_renew_ident(nc->ctx.identity); + } else { + + _reportf(L"No identity specified. Can't renew Kerberos tickets"); + + code = 1; /* it just has to be non-zero */ + } + + if (code == 0) { + _reportf(L"Tickets successfully renewed"); + + 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 if (CompareFileTime(&ftcurrent, &ftidexp) < 0) { + wchar_t tbuf[1024]; + DWORD suggestion; + kherr_suggestion sug_id; + + /* if we failed to get new tickets, but the + identity is still valid, then we assume that + the current tickets are still good enough + for other credential types to obtain their + credentials. */ + + khm_err_describe(code, tbuf, sizeof(tbuf), + &suggestion, &sug_id); + + _report_cs0(KHERR_WARNING, tbuf); + if (suggestion) + _suggest_mr(suggestion, sug_id); + + _resolve(); + + khui_cw_set_response(nc, credtype_id_krb5, + KHUI_NC_RESPONSE_EXIT | + KHUI_NC_RESPONSE_SUCCESS); + } 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_PROCESS) { + + change_password: + /* we jump here if there was a password change forced */ + + _begin_task(0); + _report_mr0(KHERR_NONE, MSG_CTX_PASSWD); + _describe(); + + khui_cw_lock_nc(nc); + + if (nc->result == KHUI_NC_RESULT_CANCEL) { + + khui_cw_set_response(nc, credtype_id_krb5, + KHUI_NC_RESPONSE_SUCCESS | + KHUI_NC_RESPONSE_EXIT); + + } else 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_PARAM; + _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_PARAM; + _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; + else { + khm_handle csp_idcfg = NULL; + krb5_context ctx = NULL; + + /* we set a new password. now we need to get + initial credentials. */ + + d = (k5_dlg_data *) nct->aux; + + if (d == NULL) { + rv = KHM_ERROR_UNKNOWN; + goto _pwd_exit; + } + + if (nc->subtype == KMSG_CRED_PASSWORD) { + /* since this was just a password change, + we need to load new credentials options + from the configuration store. */ + + k5_read_dlg_params(d, nc->identities[0]); + } + + /* the password change phase is now done */ + d->pwd_change = FALSE; + +#ifdef DEBUG + _reportf(L"Calling khm_krb5_kinit()"); +#endif + code = khm_krb5_kinit(NULL, /* context (create one) */ + idname, /* principal_name */ + npwd, /* new password */ + NULL, /* ccache name (figure out the identity cc)*/ + (krb5_deltat) d->tc_lifetime.current, + d->forwardable, + d->proxiable, + (krb5_deltat)((d->renewable)?d->tc_renew.current:0), + d->addressless, /* addressless */ + d->publicIP, /* public IP */ + NULL, /* prompter */ + NULL /* prompter data */); + + if (code) { + rv = KHM_ERROR_UNKNOWN; + goto _pwd_exit; + } + + /* save the settings that we used for + obtaining the ticket. */ + if (nc->subtype == KMSG_CRED_NEW_CREDS) { + + k5_write_dlg_params(d, nc->identities[0]); + + /* and then update the LRU too */ + k5_update_LRU(nc->identities[0]); + } + + /* and do a quick refresh of the krb5 tickets + so that other plug-ins that depend on krb5 + can look up tickets inside NetIDMgr */ + khm_krb5_list_tickets(&ctx); + + /* if there was no default identity, we make + this one the default. */ + kcdb_identity_refresh(nc->identities[0]); + { + khm_handle tdefault = NULL; + + if (KHM_SUCCEEDED(kcdb_identity_get_default(&tdefault))) { + kcdb_identity_release(tdefault); + } else { + _reportf(L"There was no default identity. Setting defualt"); + kcdb_identity_set_default(nc->identities[0]); + } + } + + if (ctx != NULL) + pkrb5_free_context(ctx); + + if (nc->subtype == KMSG_CRED_PASSWORD) { + /* if we obtained new credentials as a + result of successfully changing the + password, we also schedule an identity + renewal for this identity. This allows + the other credential types to obtain + credentials for this identity. */ + khui_action_context ctx; + + _reportf(L"Scheduling renewal of [%s] after password change", + widname); + + khui_context_create(&ctx, + KHUI_SCOPE_IDENT, + nc->identities[0], + KCDB_CREDTYPE_INVALID, + NULL); + khui_action_trigger(KHUI_ACTION_RENEW_CRED, + &ctx); + + khui_context_release(&ctx); + } + } + + /* result is only set when code != 0 */ + if (code && result) { + size_t len; + + StringCchLengthA(result, KHERR_MAXCCH_STRING, + &len); + wresult = PMALLOC((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(); + + PFREE(result); + PFREE(wresult); + + /* 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) + PFREE(nct->name); + if (nct->credtext) + PFREE(nct->credtext); + + PFREE(nct); + + k5_free_kinit_job(); + } + break; + + case KMSG_CRED_IMPORT: + { + khm_int32 t = 0; + +#ifdef DEBUG + assert(csp_params); +#endif + khc_read_int32(csp_params, L"MsLsaImport", &t); + + if (t != K5_LSAIMPORT_NEVER) { + krb5_context ctx = NULL; + khm_handle id_default = NULL; + khm_handle id_imported = NULL; + BOOL imported; + + imported = khm_krb5_ms2mit(NULL, (t == K5_LSAIMPORT_MATCH), TRUE, + &id_imported); + if (imported) { + khm_krb5_list_tickets(&ctx); + + if (ctx) + pkrb5_free_context(ctx); + + kcdb_identity_refresh(id_imported); + + if (KHM_SUCCEEDED(kcdb_identity_get_default(&id_default))) { + kcdb_identity_release(id_default); + id_default = NULL; + } else { + _reportf(L"There was no default identity. Setting default"); + kcdb_identity_set_default(id_imported); + } + + /* and update the LRU */ + k5_update_LRU(id_imported); + } + + if (id_imported) + kcdb_identity_release(id_imported); + } + } + break; + } + + return rv; +} diff --git a/src/windows/identity/plugins/krb5/krb5plugin.c b/src/windows/identity/plugins/krb5/krb5plugin.c index bb481e0fb..61331f384 100644 --- a/src/windows/identity/plugins/krb5/krb5plugin.c +++ b/src/windows/identity/plugins/krb5/krb5plugin.c @@ -1,265 +1,265 @@ -/*
- * Copyright (c) 2005 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>
-
-#ifdef DEBUG
-#include<assert.h>
-#endif
-
-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 = PMALLOC(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 = PMALLOC(cbsize);
- StringCbCopy(ct.long_desc, cbsize, buf);
- }
-
- ct.icon = NULL; /* TODO: set a proper icon */
-
- kmq_create_subscription(k5_msg_callback, &ct.sub);
-
- ct.is_equal = khm_krb5_creds_is_equal;
-
- rv = kcdb_credtype_register(&ct, &credtype_id_krb5);
-
- if(KHM_SUCCEEDED(rv))
- rv = kcdb_credset_create(&krb5_credset);
-
- if(ct.short_desc)
- PFREE(ct.short_desc);
-
- if(ct.long_desc)
- PFREE(ct.long_desc);
-
- if(KHM_SUCCEEDED(rv)) {
- krb5_context ctx = NULL;
-
- krb5_initialized = TRUE;
-
- /* 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);
-
- k5_register_config_panels();
-
- khm_krb5_list_tickets(&ctx);
-
- if(ctx != NULL)
- pkrb5_free_context(ctx);
- }
- }
- 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) {
- if (k5_kinit_fiber) {
-#ifdef DEBUG
- assert(k5_kinit_fiber != GetCurrentFiber());
-#endif
-#ifdef CLEANUP_FIBERS_ON_EXIT
- DeleteFiber(k5_kinit_fiber);
- CloseHandle(k5_kinit_fiber);
-#endif
- k5_kinit_fiber = NULL;
- }
-
- k5_main_fiber = NULL;
- }
-
- if(k5_sub != NULL) {
- kmq_delete_subscription(k5_sub);
- k5_sub = NULL;
- }
-
- break;
- }
-
- return rv;
-}
-
-khm_int32 KHMAPI
-k5_msg_kcdb(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_KCDB_IDENT:
- if (uparam == KCDB_OP_DELCONFIG) {
- k5_remove_from_LRU((khm_handle) vparam);
- }
- 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) {
- _begin_task(0);
- _report_mr0(KHERR_INFO, MSG_ERR_CTX_DESTROY_CREDS);
- _describe();
-
- khm_krb5_destroy_by_credset(ctx->credset);
-
- _end_task();
- }
- }
- 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_KCDB:
- return k5_msg_kcdb(msg_type, msg_subtype, uparam, vparam);
- }
- return KHM_ERROR_SUCCESS;
-}
+/* + * Copyright (c) 2005 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> + +#ifdef DEBUG +#include<assert.h> +#endif + +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 = PMALLOC(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 = PMALLOC(cbsize); + StringCbCopy(ct.long_desc, cbsize, buf); + } + + ct.icon = NULL; /* TODO: set a proper icon */ + + kmq_create_subscription(k5_msg_callback, &ct.sub); + + ct.is_equal = khm_krb5_creds_is_equal; + + rv = kcdb_credtype_register(&ct, &credtype_id_krb5); + + if(KHM_SUCCEEDED(rv)) + rv = kcdb_credset_create(&krb5_credset); + + if(ct.short_desc) + PFREE(ct.short_desc); + + if(ct.long_desc) + PFREE(ct.long_desc); + + if(KHM_SUCCEEDED(rv)) { + krb5_context ctx = NULL; + + krb5_initialized = TRUE; + + /* 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); + + k5_register_config_panels(); + + khm_krb5_list_tickets(&ctx); + + if(ctx != NULL) + pkrb5_free_context(ctx); + } + } + 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) { + if (k5_kinit_fiber) { +#ifdef DEBUG + assert(k5_kinit_fiber != GetCurrentFiber()); +#endif +#ifdef CLEANUP_FIBERS_ON_EXIT + DeleteFiber(k5_kinit_fiber); + CloseHandle(k5_kinit_fiber); +#endif + k5_kinit_fiber = NULL; + } + + k5_main_fiber = NULL; + } + + if(k5_sub != NULL) { + kmq_delete_subscription(k5_sub); + k5_sub = NULL; + } + + break; + } + + return rv; +} + +khm_int32 KHMAPI +k5_msg_kcdb(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_KCDB_IDENT: + if (uparam == KCDB_OP_DELCONFIG) { + k5_remove_from_LRU((khm_handle) vparam); + } + 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) { + _begin_task(0); + _report_mr0(KHERR_INFO, MSG_ERR_CTX_DESTROY_CREDS); + _describe(); + + khm_krb5_destroy_by_credset(ctx->credset); + + _end_task(); + } + } + 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_KCDB: + return k5_msg_kcdb(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 index 0d8d27276..312b576fd 100644 --- a/src/windows/identity/plugins/krb5/krb5props.c +++ b/src/windows/identity/plugins/krb5/krb5props.c @@ -1,176 +1,176 @@ -/*
- * Copyright (c) 2005 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>
-#ifdef DEBUG
-#include<assert.h>
-#endif
-
-/* 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];
- wchar_t unavailable[64];
- khm_size cbsize;
- khm_int32 rv;
- khm_int32 tflags;
-
- 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)
-
- LoadString(hResModule, IDS_UNAVAILABLE,
- unavailable, ARRAYLENGTH(unavailable));
-
- if(s->cred) {
- cbsize = sizeof(buf);
- kcdb_cred_get_name(s->cred, buf, &cbsize);
- SetDlgItemText(hwnd, IDC_PPK5_NAME, buf);
-
- cbsize = sizeof(buf);
- rv = kcdb_cred_get_attr_string(s->cred,
- KCDB_ATTR_ISSUE,
- buf, &cbsize, 0);
- if (KHM_SUCCEEDED(rv))
- SetDlgItemText(hwnd, IDC_PPK5_ISSUE, buf);
- else
- SetDlgItemText(hwnd, IDC_PPK5_ISSUE, unavailable);
-
- cbsize = sizeof(buf);
- rv = kcdb_cred_get_attr_string(s->cred,
- KCDB_ATTR_EXPIRE,
- buf, &cbsize, 0);
- if (KHM_SUCCEEDED(rv))
- SetDlgItemText(hwnd, IDC_PPK5_VALID, buf);
- else
- SetDlgItemText(hwnd, IDC_PPK5_VALID, unavailable);
-
- cbsize = sizeof(buf);
- rv = kcdb_cred_get_attr_string(s->cred,
- KCDB_ATTR_RENEW_EXPIRE,
- buf, &cbsize, 0);
- if (KHM_SUCCEEDED(rv))
- SetDlgItemText(hwnd, IDC_PPK5_RENEW, buf);
- else
- SetDlgItemText(hwnd, IDC_PPK5_RENEW, unavailable);
-
- tflags = 0;
- cbsize = sizeof(tflags);
- rv = kcdb_cred_get_attr(s->cred,
- attr_id_krb5_flags,
- NULL,
- &tflags,
- &cbsize);
- if (KHM_SUCCEEDED(rv)) {
-
-#define ADDBITFLAG(f,s) \
- if (tflags & f) { \
- LoadString(hResModule, s, buf, ARRAYLENGTH(buf)); \
- SendDlgItemMessage(hwnd, IDC_PPK5_FLAGS, LB_ADDSTRING, 0, (LPARAM) buf); \
- }
-
- ADDBITFLAG(TKT_FLG_FORWARDABLE, IDS_FLG_FORWARDABLE);
- ADDBITFLAG(TKT_FLG_FORWARDED, IDS_FLG_FORWARDED);
- ADDBITFLAG(TKT_FLG_PROXIABLE, IDS_FLG_PROXIABLE);
- ADDBITFLAG(TKT_FLG_PROXY, IDS_FLG_PROXY);
- ADDBITFLAG(TKT_FLG_MAY_POSTDATE, IDS_FLG_MAY_POSTDATE);
- ADDBITFLAG(TKT_FLG_POSTDATED, IDS_FLG_POSTDATED);
- ADDBITFLAG(TKT_FLG_INVALID, IDS_FLG_INVALID);
- ADDBITFLAG(TKT_FLG_RENEWABLE, IDS_FLG_RENEWABLE);
- ADDBITFLAG(TKT_FLG_INITIAL, IDS_FLG_INITIAL);
- ADDBITFLAG(TKT_FLG_PRE_AUTH, IDS_FLG_PRE_AUTH);
- ADDBITFLAG(TKT_FLG_HW_AUTH, IDS_FLG_HW_AUTH);
- ADDBITFLAG(TKT_FLG_TRANSIT_POLICY_CHECKED, IDS_FLG_TRANSIT_POL);
- ADDBITFLAG(TKT_FLG_OK_AS_DELEGATE, IDS_FLG_OK_DELEGATE);
- ADDBITFLAG(TKT_FLG_ANONYMOUS, IDS_FLG_ANONYMOUS);
-
-#undef ADDBITFLAG
-
- }
- } else {
-#ifdef DEBUG
- assert(FALSE);
-#endif
- }
- }
- return FALSE;
- }
-
- return FALSE;
-}
-
-void k5_pp_begin(khui_property_sheet * s)
-{
- PROPSHEETPAGE *p;
-
- if(s->credtype == credtype_id_krb5 &&
- s->cred) {
- p = PMALLOC(sizeof(*p));
- ZeroMemory(p, sizeof(*p));
-
- p->dwSize = sizeof(*p);
- p->dwFlags = 0;
- p->hInstance = hResModule;
- p->pszTemplate = MAKEINTRESOURCE(IDD_PP_KRB5C);
- 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)
- PFREE(p->p_page);
- p->p_page = NULL;
- }
-}
-
+/* + * Copyright (c) 2005 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> +#ifdef DEBUG +#include<assert.h> +#endif + +/* 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]; + wchar_t unavailable[64]; + khm_size cbsize; + khm_int32 rv; + khm_int32 tflags; + + 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) + + LoadString(hResModule, IDS_UNAVAILABLE, + unavailable, ARRAYLENGTH(unavailable)); + + if(s->cred) { + cbsize = sizeof(buf); + kcdb_cred_get_name(s->cred, buf, &cbsize); + SetDlgItemText(hwnd, IDC_PPK5_NAME, buf); + + cbsize = sizeof(buf); + rv = kcdb_cred_get_attr_string(s->cred, + KCDB_ATTR_ISSUE, + buf, &cbsize, 0); + if (KHM_SUCCEEDED(rv)) + SetDlgItemText(hwnd, IDC_PPK5_ISSUE, buf); + else + SetDlgItemText(hwnd, IDC_PPK5_ISSUE, unavailable); + + cbsize = sizeof(buf); + rv = kcdb_cred_get_attr_string(s->cred, + KCDB_ATTR_EXPIRE, + buf, &cbsize, 0); + if (KHM_SUCCEEDED(rv)) + SetDlgItemText(hwnd, IDC_PPK5_VALID, buf); + else + SetDlgItemText(hwnd, IDC_PPK5_VALID, unavailable); + + cbsize = sizeof(buf); + rv = kcdb_cred_get_attr_string(s->cred, + KCDB_ATTR_RENEW_EXPIRE, + buf, &cbsize, 0); + if (KHM_SUCCEEDED(rv)) + SetDlgItemText(hwnd, IDC_PPK5_RENEW, buf); + else + SetDlgItemText(hwnd, IDC_PPK5_RENEW, unavailable); + + tflags = 0; + cbsize = sizeof(tflags); + rv = kcdb_cred_get_attr(s->cred, + attr_id_krb5_flags, + NULL, + &tflags, + &cbsize); + if (KHM_SUCCEEDED(rv)) { + +#define ADDBITFLAG(f,s) \ + if (tflags & f) { \ + LoadString(hResModule, s, buf, ARRAYLENGTH(buf)); \ + SendDlgItemMessage(hwnd, IDC_PPK5_FLAGS, LB_ADDSTRING, 0, (LPARAM) buf); \ + } + + ADDBITFLAG(TKT_FLG_FORWARDABLE, IDS_FLG_FORWARDABLE); + ADDBITFLAG(TKT_FLG_FORWARDED, IDS_FLG_FORWARDED); + ADDBITFLAG(TKT_FLG_PROXIABLE, IDS_FLG_PROXIABLE); + ADDBITFLAG(TKT_FLG_PROXY, IDS_FLG_PROXY); + ADDBITFLAG(TKT_FLG_MAY_POSTDATE, IDS_FLG_MAY_POSTDATE); + ADDBITFLAG(TKT_FLG_POSTDATED, IDS_FLG_POSTDATED); + ADDBITFLAG(TKT_FLG_INVALID, IDS_FLG_INVALID); + ADDBITFLAG(TKT_FLG_RENEWABLE, IDS_FLG_RENEWABLE); + ADDBITFLAG(TKT_FLG_INITIAL, IDS_FLG_INITIAL); + ADDBITFLAG(TKT_FLG_PRE_AUTH, IDS_FLG_PRE_AUTH); + ADDBITFLAG(TKT_FLG_HW_AUTH, IDS_FLG_HW_AUTH); + ADDBITFLAG(TKT_FLG_TRANSIT_POLICY_CHECKED, IDS_FLG_TRANSIT_POL); + ADDBITFLAG(TKT_FLG_OK_AS_DELEGATE, IDS_FLG_OK_DELEGATE); + ADDBITFLAG(TKT_FLG_ANONYMOUS, IDS_FLG_ANONYMOUS); + +#undef ADDBITFLAG + + } + } else { +#ifdef DEBUG + assert(FALSE); +#endif + } + } + return FALSE; + } + + return FALSE; +} + +void k5_pp_begin(khui_property_sheet * s) +{ + PROPSHEETPAGE *p; + + if(s->credtype == credtype_id_krb5 && + s->cred) { + p = PMALLOC(sizeof(*p)); + ZeroMemory(p, sizeof(*p)); + + p->dwSize = sizeof(*p); + p->dwFlags = 0; + p->hInstance = hResModule; + p->pszTemplate = MAKEINTRESOURCE(IDD_PP_KRB5C); + 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) + PFREE(p->p_page); + p->p_page = NULL; + } +} + diff --git a/src/windows/identity/plugins/krb5/krbcred.h b/src/windows/identity/plugins/krb5/krbcred.h index d552fd0c8..0048f7185 100644 --- a/src/windows/identity/plugins/krb5/krbcred.h +++ b/src/windows/identity/plugins/krb5/krbcred.h @@ -1,244 +1,244 @@ -/*
- * Copyright (c) 2005 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<netidmgr.h>
-
-#include<krb5funcs.h>
-#include<krb5common.h>
-#include<errorfuncs.h>
-#include<dynimport.h>
-
-#include<langres.h>
-#include<datarep.h>
-#include<krb5_msgs.h>
-
-typedef enum tag_k5_lsa_import {
- K5_LSAIMPORT_NEVER = 0,
- K5_LSAIMPORT_ALWAYS = 1,
- K5_LSAIMPORT_MATCH = 2, /* only when the principal name matches */
-} k5_lsa_import;
-
-#define TYPENAME_ENCTYPE L"EncType"
-#define TYPENAME_ADDR_LIST L"AddrList"
-#define TYPENAME_KRB5_FLAGS L"Krb5Flags"
-#define TYPENAME_KRB5_PRINC L"Krb5Principal"
-#define TYPENAME_KVNO L"Kvno"
-
-#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"
-#define ATTRNAME_KVNO L"Kvno"
-#define ATTRNAME_KRB5_IDFLAGS L"Krb5IDFlags"
-
-/* Flag bits for Krb5IDFlags property */
-
-/* identity was imported from MSLSA: */
-#define K5IDFLAG_IMPORTED 0x00000001
-
-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 type_id_krb5_princ;
-extern khm_int32 type_id_kvno;
-
-extern BOOL type_regd_krb5_princ;
-
-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;
-extern khm_int32 attr_id_kvno;
-extern khm_int32 attr_id_krb5_idflags;
-
-extern khm_ui_4 k5_commctl_version;
-
-#define IS_COMMCTL6() (k5_commctl_version >= 0x60000)
-
-/* Configuration spaces */
-#define CSNAME_KRB5CRED L"Krb5Cred"
-#define CSNAME_PARAMS L"Parameters"
-#define CSNAME_PROMPTCACHE L"PromptCache"
-#define CSNAME_REALMS L"Realms"
-
-/* plugin constants */
-#define KRB5_PLUGIN_NAME L"Krb5Cred"
-#define KRB5_IDENTPRO_NAME L"Krb5Ident"
-
-#define KRB5_CREDTYPE_NAME L"Krb5Cred"
-
-/* limits */
-/* maximum number of characters in a realm name */
-#define K5_MAXCCH_REALM 256
-
-/* maximum number of characters in a host name */
-#define K5_MAXCCH_HOST 128
-
-/* maximum number of KDC's per realm */
-#define K5_MAX_KDC 64
-
-/* maximum number of domains that map to a realm */
-#define K5_MAX_DOMAIN_MAPPINGS 32
-
-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);
-khm_int32 KHMAPI k5_ident_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;
- BOOL valid_principal;
- BOOL retry_if_valid_principal;
-} 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
-#define FIBER_STATE_RETRY_KINIT 2
-
-#define K5_SET_CRED_MSG WMNC_USER
-
-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);
-
-khm_int32
-k5_remove_from_LRU(khm_handle identity);
-
-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);
-
-INT_PTR CALLBACK
-k5_ccconfig_dlgproc(HWND hwnd,
- UINT uMsg,
- WPARAM wParam,
- LPARAM lParam);
-
-INT_PTR CALLBACK
-k5_id_tab_dlgproc(HWND hwndDlg,
- UINT uMsg,
- WPARAM wParam,
- LPARAM lParam);
-
-INT_PTR CALLBACK
-k5_ids_tab_dlgproc(HWND hwnd,
- UINT uMsg,
- WPARAM wParam,
- LPARAM lParam);
-
-#endif
+/* + * Copyright (c) 2005 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<netidmgr.h> + +#include<krb5funcs.h> +#include<krb5common.h> +#include<errorfuncs.h> +#include<dynimport.h> + +#include<langres.h> +#include<datarep.h> +#include<krb5_msgs.h> + +typedef enum tag_k5_lsa_import { + K5_LSAIMPORT_NEVER = 0, + K5_LSAIMPORT_ALWAYS = 1, + K5_LSAIMPORT_MATCH = 2, /* only when the principal name matches */ +} k5_lsa_import; + +#define TYPENAME_ENCTYPE L"EncType" +#define TYPENAME_ADDR_LIST L"AddrList" +#define TYPENAME_KRB5_FLAGS L"Krb5Flags" +#define TYPENAME_KRB5_PRINC L"Krb5Principal" +#define TYPENAME_KVNO L"Kvno" + +#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" +#define ATTRNAME_KVNO L"Kvno" +#define ATTRNAME_KRB5_IDFLAGS L"Krb5IDFlags" + +/* Flag bits for Krb5IDFlags property */ + +/* identity was imported from MSLSA: */ +#define K5IDFLAG_IMPORTED 0x00000001 + +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 type_id_krb5_princ; +extern khm_int32 type_id_kvno; + +extern BOOL type_regd_krb5_princ; + +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; +extern khm_int32 attr_id_kvno; +extern khm_int32 attr_id_krb5_idflags; + +extern khm_ui_4 k5_commctl_version; + +#define IS_COMMCTL6() (k5_commctl_version >= 0x60000) + +/* Configuration spaces */ +#define CSNAME_KRB5CRED L"Krb5Cred" +#define CSNAME_PARAMS L"Parameters" +#define CSNAME_PROMPTCACHE L"PromptCache" +#define CSNAME_REALMS L"Realms" + +/* plugin constants */ +#define KRB5_PLUGIN_NAME L"Krb5Cred" +#define KRB5_IDENTPRO_NAME L"Krb5Ident" + +#define KRB5_CREDTYPE_NAME L"Krb5Cred" + +/* limits */ +/* maximum number of characters in a realm name */ +#define K5_MAXCCH_REALM 256 + +/* maximum number of characters in a host name */ +#define K5_MAXCCH_HOST 128 + +/* maximum number of KDC's per realm */ +#define K5_MAX_KDC 64 + +/* maximum number of domains that map to a realm */ +#define K5_MAX_DOMAIN_MAPPINGS 32 + +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); +khm_int32 KHMAPI k5_ident_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; + BOOL valid_principal; + BOOL retry_if_valid_principal; +} 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 +#define FIBER_STATE_RETRY_KINIT 2 + +#define K5_SET_CRED_MSG WMNC_USER + +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); + +khm_int32 +k5_remove_from_LRU(khm_handle identity); + +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); + +INT_PTR CALLBACK +k5_ccconfig_dlgproc(HWND hwnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam); + +INT_PTR CALLBACK +k5_id_tab_dlgproc(HWND hwndDlg, + UINT uMsg, + WPARAM wParam, + LPARAM lParam); + +INT_PTR CALLBACK +k5_ids_tab_dlgproc(HWND hwnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam); + +#endif diff --git a/src/windows/identity/plugins/krb5/langres.h b/src/windows/identity/plugins/krb5/langres.h index 0e62ecda1..117754b3e 100644 --- a/src/windows/identity/plugins/krb5/langres.h +++ b/src/windows/identity/plugins/krb5/langres.h @@ -1,216 +1,216 @@ -//{{NO_DEPENDENCIES}}
-// Microsoft Visual C++ generated include file.
-// Used by C:\work\pismere\athena\auth\krb5\src\windows\identity\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 IDD_CFG_CACHES 111
-#define IDS_ETYPE_DES_CBC_MD4 112
-#define IDI_PLUGIN 112
-#define IDS_ETYPE_DES_CBC_MD5 113
-#define IDI_DELETED 113
-#define IDS_ETYPE_DES_CBC_RAW 114
-#define IDI_NEW 114
-#define IDS_ETYPE_DES3_CBC_SHA 115
-#define IDI_NORMAL 115
-#define IDS_ETYPE_DES3_CBC_RAW 116
-#define IDI_MODIFIED 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 IDS_IDENTPRO_DESC 158
-#define IDS_K5CCC_SHORT_DESC 159
-#define IDS_K5CCC_LONG_DESC 160
-#define IDS_CFG_FCTITLE 161
-#define IDS_CFG_FCN_WARNING 162
-#define IDS_CFG_FCN_W_NOTFOUND 163
-#define IDS_CFG_FCN_W_RELATIVE 164
-#define IDS_CFG_FCOPENTITLE 165
-#define IDS_UNAVAILABLE 166
-#define IDS_FLG_FORWARDABLE 167
-#define IDS_FLG_FORWARDED 168
-#define IDS_FLG_PROXIABLE 169
-#define IDS_FLG_PROXY 170
-#define IDS_FLG_MAY_POSTDATE 171
-#define IDS_FLG_POSTDATED 172
-#define IDS_FLG_INVALID 173
-#define IDS_FLG_RENEWABLE 174
-#define IDS_FLG_INITIAL 175
-#define IDS_FLG_PRE_AUTH 176
-#define IDS_FLG_HW_AUTH 177
-#define IDS_FLG_TRANSIT_POL 178
-#define IDS_FLG_OK_DELEGATE 179
-#define IDS_FLG_ANONYMOUS 180
-#define IDS_K5ERR_CANTWRITEPROFILE 181
-#define IDS_K5ERR_PROFNOWRITE 182
-#define IDS_K5ERR_PROFUSETEMP 183
-#define IDS_K5ERR_PROFSUGGEST 184
-#define IDS_CFG_RE_REALMS 185
-#define IDS_CFG_RE_KDCS 186
-#define IDS_CFG_RE_DMAPS 187
-#define IDS_CFG_RE_KDCS_R 188
-#define IDS_CFG_RE_DMAPS_R 189
-#define IDS_CFG_RE_HEAD_SVR 190
-#define IDS_CFG_RE_HEAD_ADMIN 191
-#define IDS_CFG_RE_HEAD_MASTER 192
-#define IDS_CFG_RE_HEAD_DOMAIN 193
-#define IDS_CFG_RE_NEWREALM 194
-#define IDS_YES 195
-#define IDS_NO 196
-#define IDS_CFG_RE_NEWSERVER 197
-#define IDS_CFG_RE_NEWDMAP 198
-#define IDS_KRB5_NC_NAME 199
-#define IDS_NCERR_IDENT_TOO_LONG 200
-#define IDS_NCERR_IDENT_INVALID 201
-#define IDS_NCERR_IDENT_UNKNOWN 202
-#define IDS_CFG_RE_ARNUT 203
-#define IDS_CFG_RE_ARNUM 204
-#define IDS_CFG_RE_ASNUT 205
-#define IDS_CFG_RE_ASNUM 206
-#define IDS_CFG_RE_DMNUT 207
-#define IDS_CFG_RE_DMNUM 208
-#define IDS_CFG_RE_MNR 209
-#define IDS_CFG_RE_MDR 210
-#define IDS_CFG_RE_MNK 211
-#define IDS_CFG_RE_MDK 212
-#define IDS_CFG_RE_MAK 213
-#define IDS_CFG_RE_MMK 214
-#define IDS_CFG_RE_MND 215
-#define IDS_CFG_RE_MDD 216
-#define IDS_KVNO_SHORT_DESC 217
-#define IDS_KVNO_LONG_DESC 218
-#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_BROWSE2 1042
-#define IDC_CFG_REALMS 1044
-#define IDC_CFG_DOMAINGRP 1045
-#define IDC_CFG_SERVERSGRP 1046
-#define IDC_LIST3 1047
-#define IDC_CFG_KDC 1047
-#define IDC_LIST4 1048
-#define IDC_CFG_DMAP 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
-#define IDC_CFG_FCGRP 1059
-#define IDC_CFG_FCLIST 1060
-#define IDC_CFG_FCNAME 1062
-#define IDC_CFG_ADD 1064
-#define IDC_CFG_REMOVE 1065
-#define IDC_CFG_INCAPI 1066
-#define IDC_CFG_INCMSLSA 1067
-#define IDC_PPK5_FLAGS 1072
-#define IDC_CFG_INCREALMS 1073
-#define IDC_NCK5_ADDRESS 1074
-#define IDC_IPADDRESS1 1075
-#define IDC_NCK5_PUBLICIP 1075
-#define IDC_CFG_PUBLICIP 1075
-#define IDC_CFG_RENEW 1076
-#define IDC_CHECK3 1077
-#define IDC_CFG_ADDRESSLESS 1077
-#define IDC_CFG_FORWARD 1078
-#define IDC_CHECK1 1079
-#define ID_FOO_BAR 40001
-
-// Next default values for new objects
-//
-#ifdef APSTUDIO_INVOKED
-#ifndef APSTUDIO_READONLY_SYMBOLS
-#define _APS_NEXT_RESOURCE_VALUE 219
-#define _APS_NEXT_COMMAND_VALUE 40002
-#define _APS_NEXT_CONTROL_VALUE 1080
-#define _APS_NEXT_SYMED_VALUE 101
-#endif
-#endif
+//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by C:\work\pismere\athena\auth\krb5\src\windows\identity\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 IDD_CFG_CACHES 111 +#define IDS_ETYPE_DES_CBC_MD4 112 +#define IDI_PLUGIN 112 +#define IDS_ETYPE_DES_CBC_MD5 113 +#define IDI_DELETED 113 +#define IDS_ETYPE_DES_CBC_RAW 114 +#define IDI_NEW 114 +#define IDS_ETYPE_DES3_CBC_SHA 115 +#define IDI_NORMAL 115 +#define IDS_ETYPE_DES3_CBC_RAW 116 +#define IDI_MODIFIED 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 IDS_IDENTPRO_DESC 158 +#define IDS_K5CCC_SHORT_DESC 159 +#define IDS_K5CCC_LONG_DESC 160 +#define IDS_CFG_FCTITLE 161 +#define IDS_CFG_FCN_WARNING 162 +#define IDS_CFG_FCN_W_NOTFOUND 163 +#define IDS_CFG_FCN_W_RELATIVE 164 +#define IDS_CFG_FCOPENTITLE 165 +#define IDS_UNAVAILABLE 166 +#define IDS_FLG_FORWARDABLE 167 +#define IDS_FLG_FORWARDED 168 +#define IDS_FLG_PROXIABLE 169 +#define IDS_FLG_PROXY 170 +#define IDS_FLG_MAY_POSTDATE 171 +#define IDS_FLG_POSTDATED 172 +#define IDS_FLG_INVALID 173 +#define IDS_FLG_RENEWABLE 174 +#define IDS_FLG_INITIAL 175 +#define IDS_FLG_PRE_AUTH 176 +#define IDS_FLG_HW_AUTH 177 +#define IDS_FLG_TRANSIT_POL 178 +#define IDS_FLG_OK_DELEGATE 179 +#define IDS_FLG_ANONYMOUS 180 +#define IDS_K5ERR_CANTWRITEPROFILE 181 +#define IDS_K5ERR_PROFNOWRITE 182 +#define IDS_K5ERR_PROFUSETEMP 183 +#define IDS_K5ERR_PROFSUGGEST 184 +#define IDS_CFG_RE_REALMS 185 +#define IDS_CFG_RE_KDCS 186 +#define IDS_CFG_RE_DMAPS 187 +#define IDS_CFG_RE_KDCS_R 188 +#define IDS_CFG_RE_DMAPS_R 189 +#define IDS_CFG_RE_HEAD_SVR 190 +#define IDS_CFG_RE_HEAD_ADMIN 191 +#define IDS_CFG_RE_HEAD_MASTER 192 +#define IDS_CFG_RE_HEAD_DOMAIN 193 +#define IDS_CFG_RE_NEWREALM 194 +#define IDS_YES 195 +#define IDS_NO 196 +#define IDS_CFG_RE_NEWSERVER 197 +#define IDS_CFG_RE_NEWDMAP 198 +#define IDS_KRB5_NC_NAME 199 +#define IDS_NCERR_IDENT_TOO_LONG 200 +#define IDS_NCERR_IDENT_INVALID 201 +#define IDS_NCERR_IDENT_UNKNOWN 202 +#define IDS_CFG_RE_ARNUT 203 +#define IDS_CFG_RE_ARNUM 204 +#define IDS_CFG_RE_ASNUT 205 +#define IDS_CFG_RE_ASNUM 206 +#define IDS_CFG_RE_DMNUT 207 +#define IDS_CFG_RE_DMNUM 208 +#define IDS_CFG_RE_MNR 209 +#define IDS_CFG_RE_MDR 210 +#define IDS_CFG_RE_MNK 211 +#define IDS_CFG_RE_MDK 212 +#define IDS_CFG_RE_MAK 213 +#define IDS_CFG_RE_MMK 214 +#define IDS_CFG_RE_MND 215 +#define IDS_CFG_RE_MDD 216 +#define IDS_KVNO_SHORT_DESC 217 +#define IDS_KVNO_LONG_DESC 218 +#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_BROWSE2 1042 +#define IDC_CFG_REALMS 1044 +#define IDC_CFG_DOMAINGRP 1045 +#define IDC_CFG_SERVERSGRP 1046 +#define IDC_LIST3 1047 +#define IDC_CFG_KDC 1047 +#define IDC_LIST4 1048 +#define IDC_CFG_DMAP 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 +#define IDC_CFG_FCGRP 1059 +#define IDC_CFG_FCLIST 1060 +#define IDC_CFG_FCNAME 1062 +#define IDC_CFG_ADD 1064 +#define IDC_CFG_REMOVE 1065 +#define IDC_CFG_INCAPI 1066 +#define IDC_CFG_INCMSLSA 1067 +#define IDC_PPK5_FLAGS 1072 +#define IDC_CFG_INCREALMS 1073 +#define IDC_NCK5_ADDRESS 1074 +#define IDC_IPADDRESS1 1075 +#define IDC_NCK5_PUBLICIP 1075 +#define IDC_CFG_PUBLICIP 1075 +#define IDC_CFG_RENEW 1076 +#define IDC_CHECK3 1077 +#define IDC_CFG_ADDRESSLESS 1077 +#define IDC_CFG_FORWARD 1078 +#define IDC_CHECK1 1079 +#define ID_FOO_BAR 40001 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 219 +#define _APS_NEXT_COMMAND_VALUE 40002 +#define _APS_NEXT_CONTROL_VALUE 1080 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif |
