summaryrefslogtreecommitdiffstats
path: root/src/windows/identity/plugins
diff options
context:
space:
mode:
authorJeffrey Altman <jaltman@secure-endpoints.com>2006-03-08 15:36:15 +0000
committerJeffrey Altman <jaltman@secure-endpoints.com>2006-03-08 15:36:15 +0000
commit063485f259058548f6353f48de10ec2313af04d6 (patch)
treec4ecc3889cc5d9ebc830a95ab5690fabd31d0cc9 /src/windows/identity/plugins
parent6484932e11311f2ae85bfe03bb29a78e7a3f925a (diff)
downloadkrb5-063485f259058548f6353f48de10ec2313af04d6.tar.gz
krb5-063485f259058548f6353f48de10ec2313af04d6.tar.xz
krb5-063485f259058548f6353f48de10ec2313af04d6.zip
2006-03-07 Jeffrey Altman <jaltman@mit.edu>
nidmgr32.dll (1.0.2.1) - Attempting to obtain new credentials for a principal name that contains numbers may result in a 'Identity not specified' error. Fixed. - If an invalid identity name was specified, an 'Identity not specified' error is reported without specifying that the cause was an invalid name. Fixed: reports proper error. - Identity names were being validated at the application layer before being sent to the identity provider. This may cause valid names to be marked as invalid if the identity provider and the application disagree on what a valid name is. Fixed: identity name validation is solely a function of the identity provider. - Canonicalizing an identity name that contained certain characters failed due to a validation error. Fixed. - Possible deadlock in the new credentials dialog. (If one plugin tries to synchronize custom prompter values from the plugin thread, while the UI thread tries to obtain a lock on the new credentials data, a deadlock occurs.) Fixed. - State information for configuration panels may persist between two invocations of the configuration window. Fixed to clean up state information properly. - The UI library now has full support for custom actions and custom menus. - When there are queued alerts and a normal alert is shown, a 'next alert...' button appears in the alert which lets the user view the next queued alert. However, if the alert which is displayed requires the user to select a command button, selecting the 'next' button would be the equivalent of cancelling out of the alert and viewing the next one. The library was updated to not show the 'next' button if the alert requires user interaction. - Credential renewal on half-lifes is now supported as a configurable option. - Destroying all credentials on exiting netidmgr is a configurable option. - Debug logging to a file has been added netidmgr.exe (1.0.2.1) - Selecting 'Ok' in the configuration window didn't notify all the configuration panels to apply the changes. Fixed. - PgUp / PgDn / Shift+PgUp / Shift+PgDn keys now work as expected. - Root level configuration nodes in the Options dialog now also appear on the Options menu. Configuration nodes that are registered at the root level are automatically added to the menu. - The UI now has full support for custom actions and custom menus. - The UI does not automatically add submenus for actions which are associated with menus unless the declaration specifies that it should be rendered as a submenu. - When displaying alerts, the first button of the alert is always made the default. - 'Change summary' button in the configuration dialog was removed, since it was unused and unnecessary. - Ticket icons are displayed in the status column for all credentials. Clicking an icon opens the properties dialog for that credential. - The UI now has View by Type functionality - The UI now has Column selection and reorganization. The choice of columns and their order are preserved between restarts. - Handle multiple copies of NetIDMgr.exe being started with different version numbers. Higher version number wins. krb4cred.dll (1.0.2.1) - During new credentials acquisition, under some circumstances, the Kerberos 4 plugin would not notify NetIDMgr about the state of the Kerberos 4 ticket acquisition. This results in other plugins (such as AFS) which are depending on the feedback to fail. Fixed. krb5cred.dll (1.0.2.1) - If no password is entered while obtaining new credentials, a new TGT will not be obtained, but the new credentials operation will not fail if there already is a TGT. Added check to see if the TGT is expired and fail the operation if no valid TGT is found. - The identity provider can set the Krb5 CCName property for an identity incorrectly if there is more than one credential cache containing tickets for the same principal. Fixed. - When enumerating ccaches, krb5_cc_resolve was being called with the name of the ccache without a type prefix. Fixed. - Tracker control usability issues due to loss of focus. Fixed. - Realm Editor added. - Addressed tickets can be requested as in Leash All modules: - removed grayed out UI components that are not being backed by current functionality. - new icons - support for 64-bit Windows builds under Visual Studio 8 - proper versioning for language resources ticket: new git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@17712 dc483132-0cff-0310-8789-dd5450dbe970
Diffstat (limited to 'src/windows/identity/plugins')
-rw-r--r--src/windows/identity/plugins/common/dynimport.c45
-rw-r--r--src/windows/identity/plugins/krb4/Makefile182
-rw-r--r--src/windows/identity/plugins/krb4/krb4funcs.c76
-rw-r--r--src/windows/identity/plugins/krb4/krb4funcs.h4
-rw-r--r--src/windows/identity/plugins/krb4/krb4main.c12
-rw-r--r--src/windows/identity/plugins/krb4/krb4newcreds.c186
-rw-r--r--src/windows/identity/plugins/krb4/krb4plugin.c1
-rw-r--r--src/windows/identity/plugins/krb4/krbcred.h1
-rw-r--r--src/windows/identity/plugins/krb4/lang/en_us/langres.rc19
-rw-r--r--src/windows/identity/plugins/krb4/lang/krb4_msgs.mc57
-rw-r--r--src/windows/identity/plugins/krb4/langres.h7
-rw-r--r--src/windows/identity/plugins/krb4/version.rc31
-rw-r--r--src/windows/identity/plugins/krb5/Makefile208
-rw-r--r--src/windows/identity/plugins/krb5/datarep.c166
-rw-r--r--src/windows/identity/plugins/krb5/datarep.h42
-rw-r--r--src/windows/identity/plugins/krb5/krb5configdlg.c4602
-rw-r--r--src/windows/identity/plugins/krb5/krb5configid.c97
-rw-r--r--src/windows/identity/plugins/krb5/krb5funcs.c289
-rw-r--r--src/windows/identity/plugins/krb5/krb5funcs.h5
-rw-r--r--src/windows/identity/plugins/krb5/krb5identpro.c90
-rw-r--r--src/windows/identity/plugins/krb5/krb5main.c21
-rw-r--r--src/windows/identity/plugins/krb5/krb5newcreds.c234
-rw-r--r--src/windows/identity/plugins/krb5/krb5plugin.c32
-rw-r--r--src/windows/identity/plugins/krb5/krbconfig.csv3
-rw-r--r--src/windows/identity/plugins/krb5/krbcred.h2
-rw-r--r--src/windows/identity/plugins/krb5/lang/en_us/langres.rc71
-rw-r--r--src/windows/identity/plugins/krb5/lang/krb5_msgs.mc5
-rw-r--r--src/windows/identity/plugins/krb5/langres.h35
-rw-r--r--src/windows/identity/plugins/krb5/version.rc30
29 files changed, 4231 insertions, 2322 deletions
diff --git a/src/windows/identity/plugins/common/dynimport.c b/src/windows/identity/plugins/common/dynimport.c
index b906b6ae9..016af86e9 100644
--- a/src/windows/identity/plugins/common/dynimport.c
+++ b/src/windows/identity/plugins/common/dynimport.c
@@ -360,15 +360,33 @@ FUNC_INFO toolhelp_fi[] = {
khm_int32 init_imports(void) {
OSVERSIONINFO osvi;
+ int imp_rv = 1;
- LoadFuncs(KRB4_DLL, k4_fi, &hKrb4, 0, 1, 0, 0);
- LoadFuncs(KRB5_DLL, k5_fi, &hKrb5, 0, 1, 0, 0);
- LoadFuncs(COMERR_DLL, ce_fi, &hComErr, 0, 0, 1, 0);
- LoadFuncs(SERVICE_DLL, service_fi, &hService, 0, 1, 0, 0);
- LoadFuncs(SECUR32_DLL, lsa_fi, &hSecur32, 0, 1, 1, 1);
- LoadFuncs(KRB524_DLL, k524_fi, &hKrb524, 0, 1, 1, 1);
- LoadFuncs(PROFILE_DLL, profile_fi, &hProfile, 0, 1, 0, 0);
- LoadFuncs(CCAPI_DLL, ccapi_fi, &hCCAPI, 0, 1, 0, 0);
+#define CKRV if(!imp_rv) goto _err_ret
+
+ imp_rv = LoadFuncs(KRB4_DLL, k4_fi, &hKrb4, 0, 1, 0, 0);
+ CKRV;
+
+ imp_rv = LoadFuncs(KRB5_DLL, k5_fi, &hKrb5, 0, 1, 0, 0);
+ CKRV;
+
+ imp_rv = LoadFuncs(COMERR_DLL, ce_fi, &hComErr, 0, 0, 1, 0);
+ CKRV;
+
+ imp_rv = LoadFuncs(SERVICE_DLL, service_fi, &hService, 0, 1, 0, 0);
+ CKRV;
+
+ imp_rv = LoadFuncs(SECUR32_DLL, lsa_fi, &hSecur32, 0, 1, 1, 1);
+ CKRV;
+
+ imp_rv = LoadFuncs(KRB524_DLL, k524_fi, &hKrb524, 0, 1, 1, 1);
+ CKRV;
+
+ imp_rv = LoadFuncs(PROFILE_DLL, profile_fi, &hProfile, 0, 1, 0, 0);
+ CKRV;
+
+ imp_rv = LoadFuncs(CCAPI_DLL, ccapi_fi, &hCCAPI, 0, 1, 0, 0);
+ CKRV;
memset(&osvi, 0, sizeof(OSVERSIONINFO));
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
@@ -382,19 +400,26 @@ khm_int32 init_imports(void) {
if(osvi.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)
{
// Windows 9x
- LoadFuncs(TOOLHELPDLL, toolhelp_fi, &hToolHelp32, 0, 1, 0, 0);
+ imp_rv = LoadFuncs(TOOLHELPDLL, toolhelp_fi, &hToolHelp32, 0, 1, 0, 0);
+ CKRV;
+
hPsapi = 0;
}
else if(osvi.dwPlatformId == VER_PLATFORM_WIN32_NT)
{
// Windows NT
- LoadFuncs(PSAPIDLL, psapi_fi, &hPsapi, 0, 1, 0, 0);
+ imp_rv = LoadFuncs(PSAPIDLL, psapi_fi, &hPsapi, 0, 1, 0, 0);
+ CKRV;
+
hToolHelp32 = 0;
}
AfsAvailable = TRUE; //afscompat_init();
return KHM_ERROR_SUCCESS;
+
+ _err_ret:
+ return KHM_ERROR_NOT_FOUND;
}
khm_int32 exit_imports(void) {
diff --git a/src/windows/identity/plugins/krb4/Makefile b/src/windows/identity/plugins/krb4/Makefile
index 2385e6179..b1ad963f0 100644
--- a/src/windows/identity/plugins/krb4/Makefile
+++ b/src/windows/identity/plugins/krb4/Makefile
@@ -1,81 +1,101 @@
-#
-# Copyright (c) 2004 Massachusetts Institute of Technology
-#
-# Permission is hereby granted, free of charge, to any person
-# obtaining a copy of this software and associated documentation files
-# (the "Software"), to deal in the Software without restriction,
-# including without limitation the rights to use, copy, modify, merge,
-# publish, distribute, sublicense, and/or sell copies of the Software,
-# and to permit persons to whom the Software is furnished to do so,
-# subject to the following conditions:
-#
-# The above copyright notice and this permission notice shall be
-# included in all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
-# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
-# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-# SOFTWARE.
-
-
-MODULE=plugins\krb4
-!include <../../config/Makefile.w32>
-
-DLLFILE=$(BINDIR)\krb4cred.dll
-
-LIBFILE=$(LIBDIR)\krb4cred.lib
-
-OBJFILES= \
- $(LIBDIR)\dynimport.obj \
- $(LIBDIR)\krb5common.obj \
- $(OBJ)\krb4main.obj \
- $(OBJ)\krb4plugin.obj \
- $(OBJ)\krb4funcs.obj \
- $(OBJ)\errorfuncs.obj \
- $(OBJ)\krb4config.obj \
- $(OBJ)\krb4configdlg.obj \
- $(OBJ)\krb4newcreds.obj
-
-LIBFILES= \
- $(LIBDIR)\nidmgr32.lib \
- $(KFWLIBDIR)\loadfuncs.lib
-
-SDKLIBFILES=
-
-VERRESFILE=$(OBJ)\version.res
-
-$(OBJ)\krb4config.c: krbconfig.csv $(CONFDIR)\csvschema.cfg
- $(CCSV) $** $@
-
-$(DLLFILE): $(OBJFILES) $(VERRESFILE)
- $(DLLGUILINK) $(LIBFILES) $(SDKLIBFILES)
-
-all: mkdirs $(DLLFILE) lang
-
-lang::
-
-# Repeat this block as necessary redefining LANG for additional
-# languages.
-
-# Begin language block
-LANG=en_us
-
-LANGDLL=$(BINDIR)\krb4cred_$(LANG).dll
-
-lang:: $(LANGDLL)
-
-$(LANGDLL): $(OBJ)\langres_$(LANG).res
- $(DLLRESLINK)
-
-$(OBJ)\langres_$(LANG).res: lang\$(LANG)\langres.rc
- $(RC2RES)
-# End language block
-
-clean::
-!if defined(INCFILES)
- $(RM) $(INCFILES)
-!endif
+#
+# Copyright (c) 2004 Massachusetts Institute of Technology
+#
+# Permission is hereby granted, free of charge, to any person
+# obtaining a copy of this software and associated documentation files
+# (the "Software"), to deal in the Software without restriction,
+# including without limitation the rights to use, copy, modify, merge,
+# publish, distribute, sublicense, and/or sell copies of the Software,
+# and to permit persons to whom the Software is furnished to do so,
+# subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+
+
+MODULE=plugins\krb4
+!include <../../config/Makefile.w32>
+
+DLLFILE=$(BINDIR)\krb4cred.dll
+
+LIBFILE=$(LIBDIR)\krb4cred.lib
+
+OBJFILES= \
+ $(LIBDIR)\dynimport.obj \
+ $(LIBDIR)\krb5common.obj \
+ $(OBJ)\krb4main.obj \
+ $(OBJ)\krb4plugin.obj \
+ $(OBJ)\krb4funcs.obj \
+ $(OBJ)\errorfuncs.obj \
+ $(OBJ)\krb4config.obj \
+ $(OBJ)\krb4configdlg.obj \
+ $(OBJ)\krb4newcreds.obj
+
+
+
+SDKLIBFILES=
+
+!if ("$(CPU)" == "IA64" ) || ("$(CPU)" == "AMD64" ) || ("$(CPU)" == "ALPHA64" )
+SCLIB=bufferoverflowu.lib
+LIBFILES= \
+ $(LIBDIR)\nidmgr64.lib \
+ $(KFWLIBDIR)\loadfuncs.lib
+!else
+SCLIB=
+LIBFILES= \
+ $(LIBDIR)\nidmgr32.lib \
+ $(KFWLIBDIR)\loadfuncs.lib
+!endif
+
+VERRESFILE=$(OBJ)\version.res
+
+MSGRESFILE=$(OBJ)\krb4_msgs.res
+
+$(MSGRESFILE): $(OBJ)\krb4_msgs.rc
+
+$(OBJ)\krb4_msgs.rc: lang\krb4_msgs.mc
+ $(MC2RC)
+
+$(OBJ)\krb4config.c: krbconfig.csv $(CONFDIR)\csvschema.cfg
+ $(CCSV) $** $@
+
+$(DLLFILE): $(OBJFILES) $(VERRESFILE) $(MSGRESFILE)
+ $(DLLGUILINK) $(LIBFILES) $(SDKLIBFILES) $(SCLIB)
+
+all: mkdirs $(MSGRESFILE) $(DLLFILE) lang
+
+lang::
+
+# Repeat this block as necessary redefining LANG for additional
+# languages.
+
+# Begin language block
+LANG=en_us
+
+LANGDLL=$(BINDIR)\krb4cred_$(LANG).dll
+
+lang:: $(LANGDLL)
+
+$(LANGDLL): $(OBJ)\langres_$(LANG).res $(OBJ)\langres_ver_$(LANG).res
+ $(DLLRESLINK)
+
+$(OBJ)\langres_$(LANG).res: lang\$(LANG)\langres.rc
+ $(RC2RES)
+
+$(OBJ)\langres_ver_$(LANG).res: version.rc
+ $(RC) $(RFLAGS) $(rincflags) /d LANGVER /d LANG_$(LANG) /fo $@ $**
+# End language block
+
+clean::
+!if defined(INCFILES)
+ $(RM) $(INCFILES)
+!endif
diff --git a/src/windows/identity/plugins/krb4/krb4funcs.c b/src/windows/identity/plugins/krb4/krb4funcs.c
index 7798e5c9e..8928f71fd 100644
--- a/src/windows/identity/plugins/krb4/krb4funcs.c
+++ b/src/windows/identity/plugins/krb4/krb4funcs.c
@@ -182,15 +182,16 @@ khm_krb4_list_tickets(void)
kcdb_credset_add_cred(krb4_credset, cred, -1);
+ kcdb_cred_release(cred);
} // while
-cleanup:
+ cleanup:
if (ptf_close == NULL)
return(KSUCCESS);
if (open)
(*ptf_close)(); //close ticket file
-
+
if (k_errno == EOF)
k_errno = 0;
@@ -601,6 +602,76 @@ khm_krb4_changepwd(char * principal,
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)
{
@@ -677,6 +748,7 @@ khm_convert524(khm_handle identity)
!= KSUCCESS)) {
goto cleanup;
}
+
/* stash ticket, session key, etc. for future use */
if ((icode = pkrb_save_credentials(v4creds->service,
v4creds->instance,
diff --git a/src/windows/identity/plugins/krb4/krb4funcs.h b/src/windows/identity/plugins/krb4/krb4funcs.h
index 742036878..8abb7ac33 100644
--- a/src/windows/identity/plugins/krb4/krb4funcs.h
+++ b/src/windows/identity/plugins/krb4/krb4funcs.h
@@ -64,6 +64,10 @@ 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,
diff --git a/src/windows/identity/plugins/krb4/krb4main.c b/src/windows/identity/plugins/krb4/krb4main.c
index b83cd5eb4..57e33a8d8 100644
--- a/src/windows/identity/plugins/krb4/krb4main.c
+++ b/src/windows/identity/plugins/krb4/krb4main.c
@@ -74,7 +74,8 @@ KHMEXP khm_int32 KHMAPI init_module(kmm_module h_module) {
ZeroMemory(&pi, sizeof(pi));
pi.name = KRB4_PLUGIN_NAME;
pi.type = KHM_PITYPE_CRED;
- pi.icon = NULL; /*TODO: Assign icon */
+ 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;
@@ -101,7 +102,7 @@ KHMEXP khm_int32 KHMAPI init_module(kmm_module h_module) {
rv = khc_open_space(csp_krbcred, CSNAME_PARAMS, 0, &csp_params);
if(KHM_FAILED(rv)) goto _exit;
-_exit:
+ _exit:
return rv;
}
@@ -114,17 +115,19 @@ KHMEXP khm_int32 KHMAPI exit_module(kmm_module h_module) {
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 */
+ return KHM_ERROR_SUCCESS; /* the return code is ignored */
}
BOOL WINAPI DllMain(
@@ -138,11 +141,14 @@ BOOL WINAPI DllMain(
hInstance = hinstDLL;
init_krb();
break;
+
case DLL_PROCESS_DETACH:
exit_krb();
break;
+
case DLL_THREAD_ATTACH:
break;
+
case DLL_THREAD_DETACH:
break;
}
diff --git a/src/windows/identity/plugins/krb4/krb4newcreds.c b/src/windows/identity/plugins/krb4/krb4newcreds.c
index 28ae71a1f..3a1a72bfa 100644
--- a/src/windows/identity/plugins/krb4/krb4newcreds.c
+++ b/src/windows/identity/plugins/krb4/krb4newcreds.c
@@ -55,6 +55,7 @@ typedef struct tag_k4_dlg_data {
} k4_dlg_data;
void k4_update_display(k4_dlg_data * d) {
+
CheckDlgButton(d->hwnd, IDC_NCK4_OBTAIN,
(d->k4_enabled)?BST_CHECKED: BST_UNCHECKED);
@@ -68,8 +69,11 @@ void k4_update_display(k4_dlg_data * d) {
EnableWindow(GetDlgItem(d->hwnd, IDC_NCK4_K524), FALSE);
}
- CheckRadioButton(d->hwnd, IDC_NCK4_AUTO, IDC_NCK4_PWD,
- method_to_id[d->method]);
+#ifdef DEBUG
+ assert(d->method >= 0 && d->method < ARRAYLENGTH(method_to_id));
+#endif
+
+ CheckDlgButton(d->hwnd, method_to_id[d->method], BST_CHECKED);
khui_cw_enable_type(d->nc, credtype_id_krb4, d->k4_enabled);
}
@@ -103,6 +107,9 @@ void k4_update_data(k4_dlg_data * d) {
khm_boolean k4_should_identity_get_k4(khm_handle ident) {
khm_int32 idflags = 0;
+ khm_handle csp_ident = NULL;
+ khm_handle csp_k4 = NULL;
+ khm_boolean get_k4 = TRUE;
if (KHM_FAILED(kcdb_identity_get_flags(ident, &idflags)))
return FALSE;
@@ -122,7 +129,20 @@ khm_boolean k4_should_identity_get_k4(khm_handle ident) {
}
}
- return TRUE;
+ 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)) &&
+ !t)
+ get_k4 = FALSE;
+
+ khc_close_space(csp_k4);
+ }
+ khc_close_space(csp_ident);
+ }
+
+ return get_k4;
}
void k4_read_identity_data(k4_dlg_data * d) {
@@ -433,9 +453,6 @@ krb4_msg_newcred(khm_int32 msg_type, khm_int32 msg_subtype,
if (!nc->ctx.identity)
break;
- if (!k4_should_identity_get_k4(nc->ctx.identity))
- break;
-
nct = PMALLOC(sizeof(*nct));
#ifdef DEBUG
assert(nct);
@@ -469,6 +486,8 @@ krb4_msg_newcred(khm_int32 msg_type, khm_int32 msg_subtype,
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)))
@@ -484,17 +503,33 @@ krb4_msg_newcred(khm_int32 msg_type, khm_int32 msg_subtype,
if (!d ||
nc->n_identities == 0 ||
nc->identities[0] == NULL ||
- nc->result != KHUI_NC_RESULT_GET_CREDS)
+ 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 &&
@@ -511,12 +546,30 @@ krb4_msg_newcred(khm_int32 msg_type, khm_int32 msg_subtype,
ident = nc->ctx.identity;
+ if (!k4_should_identity_get_k4(ident)) {
+ khui_cw_set_response(nc, credtype_id_krb4,
+ KHUI_NC_RESPONSE_FAILED |
+ KHUI_NC_RESPONSE_EXIT);
+ break;
+ }
+
} else {
+ 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);
}
@@ -525,8 +578,29 @@ krb4_msg_newcred(khm_int32 msg_type, khm_int32 msg_subtype,
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 |
@@ -536,13 +610,92 @@ krb4_msg_newcred(khm_int32 msg_type, khm_int32 msg_subtype,
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;
+
}
}
@@ -564,6 +717,8 @@ krb4_msg_newcred(khm_int32 msg_type, khm_int32 msg_subtype,
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);
@@ -581,16 +736,20 @@ krb4_msg_newcred(khm_int32 msg_type, khm_int32 msg_subtype,
break;
}
- if (idx >= n_prompts)
+ 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)))
+ &cb))) {
+ _reportf(L"Failed to obtain password value");
goto _skip_pwd;
+ }
UnicodeStrToAnsi(pwd, sizeof(pwd), wpwd);
@@ -605,8 +764,10 @@ krb4_msg_newcred(khm_int32 msg_type, khm_int32 msg_subtype,
char * atsign;
atsign = strchr(idname, '@');
- if (atsign == NULL)
+ if (atsign == NULL) {
+ _reportf(L"Identity name does not contain an '@'");
goto _skip_pwd;
+ }
*atsign++ = 0;
@@ -629,6 +790,9 @@ krb4_msg_newcred(khm_int32 msg_type, khm_int32 msg_subtype,
code = khm_krb4_kinit(aname, inst, realm,
(long) d->lifetime, pwd);
+
+ _reportf(L"khm_krb4_kinit returns code %d", code);
+
_skip_pwd:
if (code) {
@@ -649,6 +813,8 @@ krb4_msg_newcred(khm_int32 msg_type, khm_int32 msg_subtype,
}
}
}
+
+ _end_task();
}
}
break;
diff --git a/src/windows/identity/plugins/krb4/krb4plugin.c b/src/windows/identity/plugins/krb4/krb4plugin.c
index 23f913bd9..972ed4a01 100644
--- a/src/windows/identity/plugins/krb4/krb4plugin.c
+++ b/src/windows/identity/plugins/krb4/krb4plugin.c
@@ -200,7 +200,6 @@ krb4_msg_system(khm_int32 msg_type, khm_int32 msg_subtype,
&attr_id_krb5_flags))) {
rv = KHM_ERROR_UNKNOWN;
}
-
}
break;
diff --git a/src/windows/identity/plugins/krb4/krbcred.h b/src/windows/identity/plugins/krb4/krbcred.h
index 9f5d3c932..f31c4a4d3 100644
--- a/src/windows/identity/plugins/krb4/krbcred.h
+++ b/src/windows/identity/plugins/krb4/krbcred.h
@@ -41,6 +41,7 @@
#include<dynimport.h>
#include<langres.h>
+#include<krb4_msgs.h>
#define TYPENAME_ENCTYPE L"EncType"
#define TYPENAME_ADDR_LIST L"AddrList"
diff --git a/src/windows/identity/plugins/krb4/lang/en_us/langres.rc b/src/windows/identity/plugins/krb4/lang/en_us/langres.rc
index a07dc4b30..d9114e5b6 100644
--- a/src/windows/identity/plugins/krb4/lang/en_us/langres.rc
+++ b/src/windows/identity/plugins/krb4/lang/en_us/langres.rc
@@ -61,14 +61,14 @@ BEGIN
SS_LEFTNOWORDWRAP | SS_SUNKEN | WS_GROUP,7,7,286,11
CONTROL "Obtain Kerberos 4 tickets",IDC_NCK4_OBTAIN,"Button",
BS_AUTOCHECKBOX | WS_TABSTOP,7,26,97,10
+ GROUPBOX "Obtain Kerberos 4 tickets using",IDC_STATIC,7,43,286,72,
+ WS_GROUP
CONTROL "Automatically determine method",IDC_NCK4_AUTO,"Button",
BS_AUTORADIOBUTTON | WS_GROUP | WS_TABSTOP,23,58,119,10
CONTROL "Kerberos 5 to 4 translation",IDC_NCK4_K524,"Button",
- BS_AUTORADIOBUTTON | WS_TABSTOP,23,76,101,10
- CONTROL "Password",IDC_NCK4_PWD,"Button",BS_AUTORADIOBUTTON |
- WS_TABSTOP,23,94,47,10
- GROUPBOX "Obtain Kerberos 4 tickets using",IDC_STATIC,7,43,286,72,
- WS_GROUP
+ BS_AUTORADIOBUTTON,23,76,101,10
+ CONTROL "Password",IDC_NCK4_PWD,"Button",BS_AUTORADIOBUTTON,23,
+ 94,47,10
END
IDD_CFG_KRB4 DIALOGEX 0, 0, 255, 182
@@ -156,6 +156,15 @@ END
/////////////////////////////////////////////////////////////////////////////
//
+// Icon
+//
+
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+IDI_PLUGIN ICON "..\\..\\images\\plugin.ico"
+
+/////////////////////////////////////////////////////////////////////////////
+//
// String Table
//
diff --git a/src/windows/identity/plugins/krb4/lang/krb4_msgs.mc b/src/windows/identity/plugins/krb4/lang/krb4_msgs.mc
new file mode 100644
index 000000000..9fa410f2f
--- /dev/null
+++ b/src/windows/identity/plugins/krb4/lang/krb4_msgs.mc
@@ -0,0 +1,57 @@
+; // ** krb5_msgs.mc
+
+; /* Since .mc files can contain strings from any language, we define
+; all our messages in one file in the /lang/ directory instead of
+; language specific subdirectories. */
+
+; /* The type is set to (wchar_t *) because that's what we will be
+; feeding kherr_report() function. */
+
+; // MessageIdTypedef=LPWSTR
+
+; /* Severity values as defined in the message definition file are
+; currently ignored. */
+
+SeverityNames=(
+ Success=0x0
+)
+
+LanguageNames=(
+ English=0x409:MSG_ENU
+)
+
+OutputBase=16
+
+; /* Actual messages start here */
+
+MessageId=1
+Severity=Success
+SymbolicName=MSG_INITIAL
+Language=English
+Initial placeholder message
+.
+
+MessageId=
+SymbolicName=MSG_K4_NEW_CREDS
+Language=English
+Getting new Krb4 credentials for [%1!s!] using method [%2!d!]
+.
+
+MessageId=
+SymbolicName=MSG_K4_RENEW_CREDS
+Language=English
+Renewing Krb4 credentials for [%1!s!] using method [%2!d!]
+.
+
+MessageId=
+SymbolicName=MSG_K4_TRY_K524
+Language=English
+Trying Krb524 ...
+.
+
+MessageId=
+SymbolicName=MSG_K4_TRY_PASSWORD
+Language=English
+Trying Password ...
+.
+
diff --git a/src/windows/identity/plugins/krb4/langres.h b/src/windows/identity/plugins/krb4/langres.h
index ceb236007..2cf0de137 100644
--- a/src/windows/identity/plugins/krb4/langres.h
+++ b/src/windows/identity/plugins/krb4/langres.h
@@ -1,6 +1,6 @@
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
-// Used by D:\work\pismere\athena\auth\krb5\src\windows\identity\plugins\krb4\lang\en_us\langres.rc
+// Used by C:\work\pismere\athena\auth\krb5\src\windows\identity\plugins\krb4\lang\en_us\langres.rc
//
#define IDS_UNK_ADDR_FMT 101
#define IDS_KRB5_CREDTEXT_0 102
@@ -17,6 +17,8 @@
#define IDD_CFG_ID_KRB4 106
#define IDS_TKT_ENCTYPE_LONG_DESC 107
#define IDS_ERR_INVINST 107
+#define IDI_ICON1 107
+#define IDI_PLUGIN 107
#define IDS_ADDR_LIST_SHORT_DESC 108
#define IDS_ERR_PWINTKT 108
#define IDS_ADDR_LIST_LONG_DESC 109
@@ -83,13 +85,12 @@
#define IDC_NCK4_K524 1035
#define IDC_NCK4_AUTO 1036
#define IDC_CFG_GETTIX 1037
-#define IDC_CHECK1 1038
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
-#define _APS_NEXT_RESOURCE_VALUE 107
+#define _APS_NEXT_RESOURCE_VALUE 108
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1039
#define _APS_NEXT_SYMED_VALUE 101
diff --git a/src/windows/identity/plugins/krb4/version.rc b/src/windows/identity/plugins/krb4/version.rc
index 3ca6b1cb9..90105f827 100644
--- a/src/windows/identity/plugins/krb4/version.rc
+++ b/src/windows/identity/plugins/krb4/version.rc
@@ -26,6 +26,28 @@
#include<netidmgr_intver.h>
+#ifndef LANGVER
+
+#define STR_FILEDESC "Kerberos 4 Plugin for NetIDMgr"
+#define STR_INTNAME "krb4cred"
+#define STR_ORIGNAME "krb4cred.dll"
+
+#else
+
+#ifdef LANG_en_us
+
+#define STR_FILEDESC "English(US) language resources for the Keberos 4 plugin"
+#define STR_INTNAME "krb4cred_en_us"
+#define STR_ORIGNAME "krb4cred_en_us.dll"
+
+#else
+
+#error Unknown langugae
+
+#endif
+
+#endif
+
1 VERSIONINFO
FILEVERSION KH_VERSION_LIST
PRODUCTVERSION KH_VERSION_LIST
@@ -41,20 +63,22 @@
BLOCK "040904b0"
{
VALUE "CompanyName", KH_VERSTR_COMPANY_1033
- VALUE "FileDescription", "Kerberos 4 plugin for NetIDMgr"
+ VALUE "FileDescription", STR_FILEDESC
VALUE "FileVersion", KH_VERSTR_VERSION_1033
- VALUE "InternalName", "krb4cred"
+ VALUE "InternalName", STR_INTNAME
VALUE "LegalCopyright", KH_VERSTR_COPYRIGHT_1033
- VALUE "OriginalFilename", "krb4cred.dll"
+ VALUE "OriginalFilename", STR_ORIGNAME
VALUE "ProductName", "NetIDMgr"
VALUE "ProductVersion", KH_VERSTR_PRODUCT_1033
#ifdef KH_VERSTR_COMMENT_1033
VALUE "Comment", KH_VERSTR_COMMENT_1033
#endif
+#ifndef LANGVER
VALUE NIMV_MODULE, "MITKrb4"
VALUE NIMV_PLUGINS, "Krb4Cred"
VALUE NIMV_APIVER, KH_VERSION_STRINGAPI
VALUE NIMV_SUPPORT, "http://web.mit.edu/kerberos"
+#endif
}
}
@@ -62,5 +86,4 @@
{
VALUE "Translation", 0x409, 1200
}
-
}
diff --git a/src/windows/identity/plugins/krb5/Makefile b/src/windows/identity/plugins/krb5/Makefile
index e0553d846..67475ee01 100644
--- a/src/windows/identity/plugins/krb5/Makefile
+++ b/src/windows/identity/plugins/krb5/Makefile
@@ -1,98 +1,110 @@
-#
-# Copyright (c) 2004 Massachusetts Institute of Technology
-#
-# Permission is hereby granted, free of charge, to any person
-# obtaining a copy of this software and associated documentation files
-# (the "Software"), to deal in the Software without restriction,
-# including without limitation the rights to use, copy, modify, merge,
-# publish, distribute, sublicense, and/or sell copies of the Software,
-# and to permit persons to whom the Software is furnished to do so,
-# subject to the following conditions:
-#
-# The above copyright notice and this permission notice shall be
-# included in all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
-# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
-# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-# SOFTWARE.
-
-
-MODULE=plugins\krb5
-!include <../../config/Makefile.w32>
-
-DLLFILE=$(BINDIR)\krb5cred.dll
-
-LIBFILE=$(LIBDIR)\krb5cred.lib
-
-OBJFILES= \
- $(LIBDIR)\dynimport.obj \
- $(LIBDIR)\krb5common.obj \
- $(OBJ)\krb5main.obj \
- $(OBJ)\datarep.obj \
- $(OBJ)\errorfuncs.obj \
- $(OBJ)\krb5plugin.obj \
- $(OBJ)\krb5props.obj \
- $(OBJ)\krb5newcreds.obj \
- $(OBJ)\krb5funcs.obj \
- $(OBJ)\krb5config.obj \
- $(OBJ)\krb5identpro.obj \
- $(OBJ)\krb5configdlg.obj \
- $(OBJ)\krb5configcc.obj \
- $(OBJ)\krb5configid.obj \
- $(OBJ)\krb5configids.obj
-
-LIBFILES= \
- $(LIBDIR)\nidmgr32.lib \
- $(KFWLIBDIR)\loadfuncs.lib
-
-SDKLIBFILES= \
- netapi32.lib \
- shlwapi.lib \
- comctl32.lib
-
-MSGRESFILE=$(OBJ)\krb5_msgs.res
-
-VERRESFILE=$(OBJ)\version.res
-
-$(OBJ)\krb5config.c: krbconfig.csv $(CONFDIR)\csvschema.cfg
- $(CCSV) $** $@
-
-$(DLLFILE): $(MSGRESFILE) $(VERRESFILE) $(OBJFILES)
- $(DLLGUILINK) $(LIBFILES) $(SDKLIBFILES)
-
-$(MSGRESFILE): $(OBJ)\krb5_msgs.rc
-
-$(OBJ)\krb5_msgs.rc: lang\krb5_msgs.mc
- $(MC2RC)
-
-all: mkdirs $(DLLFILE) lang
-
-lang::
-
-# Repeat this block as necessary redefining LANG for additional
-# languages.
-
-# Begin language block
-LANG=en_us
-
-LANGDLL=$(BINDIR)\krb5cred_$(LANG).dll
-
-lang:: $(LANGDLL)
-
-$(LANGDLL): $(OBJ)\langres_$(LANG).res
- $(DLLRESLINK)
-
-$(OBJ)\langres_$(LANG).res: lang\$(LANG)\langres.rc
- $(RC2RES)
-
-# End language block
-
-clean::
-!if defined(INCFILES)
- $(RM) $(INCFILES)
-!endif
+#
+# Copyright (c) 2004 Massachusetts Institute of Technology
+#
+# Permission is hereby granted, free of charge, to any person
+# obtaining a copy of this software and associated documentation files
+# (the "Software"), to deal in the Software without restriction,
+# including without limitation the rights to use, copy, modify, merge,
+# publish, distribute, sublicense, and/or sell copies of the Software,
+# and to permit persons to whom the Software is furnished to do so,
+# subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+
+
+MODULE=plugins\krb5
+!include <../../config/Makefile.w32>
+
+DLLFILE=$(BINDIR)\krb5cred.dll
+
+LIBFILE=$(LIBDIR)\krb5cred.lib
+
+OBJFILES= \
+ $(LIBDIR)\dynimport.obj \
+ $(LIBDIR)\krb5common.obj \
+ $(OBJ)\krb5main.obj \
+ $(OBJ)\datarep.obj \
+ $(OBJ)\errorfuncs.obj \
+ $(OBJ)\krb5plugin.obj \
+ $(OBJ)\krb5props.obj \
+ $(OBJ)\krb5newcreds.obj \
+ $(OBJ)\krb5funcs.obj \
+ $(OBJ)\krb5config.obj \
+ $(OBJ)\krb5identpro.obj \
+ $(OBJ)\krb5configdlg.obj \
+ $(OBJ)\krb5configcc.obj \
+ $(OBJ)\krb5configid.obj \
+ $(OBJ)\krb5configids.obj
+
+
+
+SDKLIBFILES= \
+ netapi32.lib \
+ shlwapi.lib \
+ comctl32.lib
+
+!if ("$(CPU)" == "IA64" ) || ("$(CPU)" == "AMD64" ) || ("$(CPU)" == "ALPHA64" )
+SCLIB=bufferoverflowu.lib
+LIBFILES= \
+ $(LIBDIR)\nidmgr64.lib \
+ $(KFWLIBDIR)\loadfuncs.lib
+!else
+SCLIB=
+LIBFILES= \
+ $(LIBDIR)\nidmgr32.lib \
+ $(KFWLIBDIR)\loadfuncs.lib
+!endif
+
+MSGRESFILE=$(OBJ)\krb5_msgs.res
+
+VERRESFILE=$(OBJ)\version.res
+
+$(OBJ)\krb5config.c: krbconfig.csv $(CONFDIR)\csvschema.cfg
+ $(CCSV) $** $@
+
+$(DLLFILE): $(OBJFILES) $(VERRESFILE)
+ $(DLLGUILINK) $(MSGRESFILE) $(LIBFILES) $(SDKLIBFILES) $(SCLIB)
+
+$(MSGRESFILE): $(OBJ)\krb5_msgs.rc
+
+$(OBJ)\krb5_msgs.rc: lang\krb5_msgs.mc
+ $(MC2RC)
+
+all: mkdirs $(MSGRESFILE) $(DLLFILE) lang
+
+lang::
+
+# Repeat this block as necessary redefining LANG for additional
+# languages.
+
+# Begin language block
+LANG=en_us
+
+LANGDLL=$(BINDIR)\krb5cred_$(LANG).dll
+
+lang:: $(LANGDLL)
+
+$(LANGDLL): $(OBJ)\langres_$(LANG).res $(OBJ)\langres_ver_$(LANG).res
+ $(DLLRESLINK)
+
+$(OBJ)\langres_$(LANG).res: lang\$(LANG)\langres.rc
+ $(RC2RES)
+
+$(OBJ)\langres_ver_$(LANG).res: version.rc
+ $(RC) $(RFLAGS) $(rincflags) /d LANGVER /d LANG_$(LANG) /fo $@ $**
+# End language block
+
+clean::
+!if defined(INCFILES)
+ $(RM) $(INCFILES)
+!endif
diff --git a/src/windows/identity/plugins/krb5/datarep.c b/src/windows/identity/plugins/krb5/datarep.c
index 2c4036083..97d629eb4 100644
--- a/src/windows/identity/plugins/krb5/datarep.c
+++ b/src/windows/identity/plugins/krb5/datarep.c
@@ -26,12 +26,17 @@
/* 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)
+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;
@@ -130,17 +135,90 @@ khm_int32 KHMAPI enctype_toString(const void * data, khm_size cbdata, wchar_t *d
}
}
-khm_int32 KHMAPI addr_list_toString(const void *d, khm_size cb_d, wchar_t *buf, khm_size *pcb_buf, khm_int32 flags)
+khm_int32 KHMAPI
+addr_list_comp(const void *d1, khm_size cb_d1,
+ const void *d2, khm_size cb_d2)
{
- /*TODO: implement this */
- return KHM_ERROR_NOT_IMPLEMENTED;
+ if (cb_d1 < cb_d2)
+ return -1;
+ if (cb_d1 > cb_d2)
+ return 1;
+ return memcmp(d1, d2, cb_d1);
}
-khm_int32 KHMAPI krb5flags_toString(const void *d,
- khm_size cb_d,
- wchar_t *buf,
- khm_size *pcb_buf,
- khm_int32 f)
+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;
@@ -196,19 +274,42 @@ khm_int32 KHMAPI krb5flags_toString(const void *d,
}
}
-khm_int32 serialize_krb5_addresses(krb5_address ** a, void ** buf, size_t * pcbbuf)
+khm_int32
+serialize_krb5_addresses(krb5_address ** a, void * buf, size_t * pcbbuf)
{
- /*TODO: implement this */
- return KHM_ERROR_NOT_IMPLEMENTED;
-}
+ 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;
+ }
+ }
-#if 0
+ *pcbbuf = cb_req;
-wchar_t *
-one_addr(krb5_address *a)
+ return (overflow)?KHM_ERROR_TOO_LONG: KHM_ERROR_SUCCESS;
+}
+
+void
+one_addr(k5_serial_address *a, wchar_t * buf, khm_size cbbuf)
{
- static wchar_t retstr[256];
- struct hostent *h;
+ wchar_t retstr[256];
+ struct hostent *h = NULL;
int no_resolve = 1;
retstr[0] = L'\0';
@@ -227,43 +328,50 @@ one_addr(krb5_address *a)
if (!no_resolve) {
#ifdef HAVE_GETIPNODEBYADDR
int err;
- h = getipnodebyaddr(a->contents, a->length, af, &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->contents, a->length, af);
+ else
+ h = gethostbyaddr(&a->data, a->length, af);
if (h) {
StringCbPrintf(retstr, sizeof(retstr), L"%S", h->h_name);
}
#endif
if (h)
- return(retstr);
+ goto _copy_string;
}
if (no_resolve || !h) {
#ifdef HAVE_INET_NTOP
char buf[46];
- const char *name = inet_ntop(a->addrtype, a->contents, buf, sizeof(buf));
+ const char *name = inet_ntop(a->addrtype, &a->data, buf, sizeof(buf));
if (name) {
StringCbPrintf(retstr, sizeof(retstr), L"%S", name);
- return;
+ goto _copy_string;
}
#else
if (a->addrtype == ADDRTYPE_INET) {
+ khm_ui_4 addr = a->data;
StringCbPrintf(retstr, sizeof(retstr),
- L"%d.%d.%d.%d", a->contents[0], a->contents[1],
- a->contents[2], a->contents[3]);
- return(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);
}
- return(retstr);
+
+ _copy_string:
+ StringCbCopy(buf, cbbuf, retstr);
}
-#endif
+
diff --git a/src/windows/identity/plugins/krb5/datarep.h b/src/windows/identity/plugins/krb5/datarep.h
index ac6771cb9..eeb6970da 100644
--- a/src/windows/identity/plugins/krb5/datarep.h
+++ b/src/windows/identity/plugins/krb5/datarep.h
@@ -27,11 +27,45 @@
#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;
-khm_int32 KHMAPI enctype_toString(const void * data, khm_size cbdata, wchar_t *destbuf, khm_size *pcbdestbuf, khm_int32 flags);
-khm_int32 KHMAPI addr_list_toString(const void *, khm_size, wchar_t *, khm_size *, khm_int32);
-khm_int32 KHMAPI krb5flags_toString(const void *, khm_size, wchar_t *, khm_size *, khm_int32);
-khm_int32 KHMAPI renew_for_cb(khm_handle cred, khm_int32 id, void * buffer, khm_size * pcbsize);
+#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
+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/krb5configdlg.c b/src/windows/identity/plugins/krb5/krb5configdlg.c
index 8cf89c7cd..0cb8b2ab7 100644
--- a/src/windows/identity/plugins/krb5/krb5configdlg.c
+++ b/src/windows/identity/plugins/krb5/krb5configdlg.c
@@ -1,1856 +1,2746 @@
-/*
- * 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>
-
-#pragma warning(push)
-#pragma warning(disable: 4995)
-#include<shlwapi.h>
-#pragma warning(pop)
-
-
-typedef struct tag_k5_realm_kdc {
- wchar_t name[K5_MAXCCH_HOST];
- khm_boolean admin; /* admin server? */
- khm_boolean master; /* master kdc? */
- khm_int32 flags;
-} k5_realm_kdc;
-
-#define K5_RKFLAG_DELETED 1
-#define K5_RKFLAG_NEW 2
-#define K5_RKFLAG_MOD_ADMIN 4
-#define K5_RKFLAG_MOD_MASTER 8
-
-typedef struct tag_k5_domain_map {
- wchar_t name[K5_MAXCCH_HOST]; /* name of host that maps to a
- realm */
- khm_int32 flags;
-} k5_domain_map;
-
-#define K5_DMFLAG_DELETED 1
-#define K5_DMFLAG_NEW 2
-
-typedef struct tag_k5_realm_data {
- wchar_t realm[K5_MAXCCH_REALM];
- k5_realm_kdc kdcs[K5_MAX_KDC];
- khm_size n_kdcs;
- k5_domain_map domain_maps[K5_MAX_DOMAIN_MAPPINGS];
- khm_size n_domain_maps;
-
- khm_int32 flags;
-} k5_realm_data;
-
-#define K5_RDFLAG_DELETED 1
-#define K5_RDFLAG_NEW 2
-#define K5_RDFLAG_MODIFED 4
-
-#define K5_REALMS_ALLOC_INCR 8
-
-typedef struct tag_k5_config_data {
- wchar_t def_realm[K5_MAXCCH_REALM]; /* default realm */
-
- wchar_t config_file[MAX_PATH]; /* path to configuration file */
- khm_boolean create_config_file; /* create config_file if missing? */
- khm_boolean inc_realms; /* include full realm list in new
- credentials dialog? */
-
- /* [libdefaults] */
- khm_boolean dns_lookup_kdc;
- khm_boolean dns_lookup_realm;
- khm_boolean dns_fallback;
-
- khm_boolean noaddresses;
-
- k5_lsa_import lsa_import; /* import mslsa creds? */
-
- /* [realms] */
- k5_realm_data *realms;
- khm_size n_realms;
- khm_size nc_realms;
- khm_size c_realm;
-
- khui_config_node node_main;
- khui_config_node node_realm;
-
- khm_int32 flags;
-} k5_config_data;
-
-#define K5_CDFLAG_MOD_DEF_REALM 0x00000001
-#define K5_CDFLAG_MOD_CONF_FILE 0x00000002
-#define K5_CDFLAG_MOD_DNS_LOOKUP_KDC 0x00000004
-#define K5_CDFLAG_MOD_DNS_LOOKUP_RLM 0x00000008
-#define K5_CDFLAG_MOD_DNS_FALLBACK 0x00000010
-#define K5_CDFLAG_MOD_NOADDRESSES 0x00000020
-#define K5_CDFLAG_MOD_LSA_IMPORT 0x00000040
-#define K5_CDFLAG_MOD_CREATE_CONF 0x00000080
-#define K5_CDFLAG_MOD_INC_REALMS 0x00000100
-#define K5_CDFLAG_MOD_REALMS 0x00001000
-
-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
-k5_parse_boolean(const char *s)
-{
- const char *const *p;
-
- for(p=conf_yes; *p; p++) {
- if (!stricmp(*p,s))
- return 1;
- }
-
- for(p=conf_no; *p; p++) {
- if (!stricmp(*p,s))
- return 0;
- }
-
- /* Default to "no" */
- return 0;
-}
-
-void
-k5_init_config_data(k5_config_data * d) {
- ZeroMemory(d, sizeof(*d));
-}
-
-void
-k5_free_config_data(k5_config_data * d) {
- if (d->realms)
- PFREE(d->realms);
-
- k5_init_config_data(d);
-}
-
-static void
-k5_assert_n_realms(k5_config_data * d, khm_size n) {
- khm_size nc_realms;
-
- if (n <= d->nc_realms)
- return;
-
- nc_realms = UBOUNDSS(n, K5_REALMS_ALLOC_INCR, K5_REALMS_ALLOC_INCR);
- assert(nc_realms > d->nc_realms);
-
- d->realms = PREALLOC(d->realms, nc_realms * sizeof(*(d->realms)));
- d->nc_realms = nc_realms;
-
- ZeroMemory(&d->realms[d->n_realms],
- (d->nc_realms - d->n_realms) * sizeof(*(d->realms)));
-}
-
-void
-k5_purge_config_data(k5_config_data * d,
- khm_boolean purge_realms,
- khm_boolean purge_kdcs,
- khm_boolean purge_dmap) {
- khm_size r;
- khm_size k;
- khm_size m;
-
- for (r=0; r < d->n_realms; r++) {
- if (purge_realms &&
- (d->realms[r].flags & K5_RDFLAG_NEW) &&
- (d->realms[r].flags & K5_RDFLAG_DELETED)) {
-
- if (d->n_realms > r+1)
- MoveMemory(&d->realms[r], &d->realms[r+1],
- sizeof(d->realms[0]) * (d->n_realms - (r+1)));
- r--;
- d->n_realms--;
- continue;
- }
-
- for (k=0; k < d->realms[r].n_kdcs; k++) {
- if (purge_kdcs &&
- (d->realms[r].kdcs[k].flags & K5_RKFLAG_NEW) &&
- (d->realms[r].kdcs[k].flags & K5_RKFLAG_DELETED)) {
- if (d->realms[r].n_kdcs > k + 1)
- MoveMemory(&d->realms[r].kdcs[k],
- &d->realms[r].kdcs[k+1],
- sizeof(d->realms[0].kdcs[0]) *
- (d->realms[r].n_kdcs - (k+1)));
- k--;
- d->realms[r].n_kdcs--;
- continue;
- }
- }
-
- if (K5_MAX_KDC > k+1)
- ZeroMemory(&d->realms[r].kdcs[k],
- sizeof(d->realms[0].kdcs[0]) *
- (K5_MAX_KDC - (k + 1)));
-
- for (m=0; m < d->realms[r].n_domain_maps; m++) {
- if (purge_dmap &&
- (d->realms[r].domain_maps[m].flags & K5_DMFLAG_NEW) &&
- (d->realms[r].domain_maps[m].flags & K5_DMFLAG_DELETED)) {
- if (d->realms[r].n_domain_maps > m + 1)
- MoveMemory(&d->realms[r].domain_maps[m],
- &d->realms[r].domain_maps[m+1],
- sizeof(d->realms[0].domain_maps[0]) *
- (d->realms[r].n_domain_maps - (m+1)));
- m--;
- d->realms[r].n_domain_maps--;
- continue;
- }
- }
-
- if (K5_MAX_DOMAIN_MAPPINGS > m+1)
- ZeroMemory(&d->realms[r].domain_maps[m],
- sizeof(d->realms[0].domain_maps[0]) *
- (K5_MAX_DOMAIN_MAPPINGS - (m+1)));
- }
-
- if (d->nc_realms > r + 1)
- ZeroMemory(&d->realms[r],
- sizeof(d->realms[0]) *
- (d->nc_realms - (r + 1)));
-}
-
-static khm_boolean
-k5_is_profile_loaded(void) {
-#ifdef DEBUG
- assert(pprofile_init);
- assert(pprofile_get_subsection_names);
- assert(pprofile_get_values);
- assert(pprofile_get_string);
- assert(pprofile_get_relation_names);
- assert(pprofile_free_list);
- assert(pprofile_release_string);
- assert(pprofile_release);
- assert(pprofile_clear_relation);
- assert(pprofile_add_relation);
- assert(pprofile_update_relation);
- assert(pprofile_flush);
-#endif
-
- if (!pprofile_init ||
- !pprofile_get_subsection_names ||
- !pprofile_get_values ||
- !pprofile_get_string ||
- !pprofile_get_relation_names ||
- !pprofile_free_list ||
- !pprofile_release_string ||
- !pprofile_release ||
- !pprofile_clear_relation ||
- !pprofile_add_relation ||
- !pprofile_update_relation ||
- !pprofile_flush)
-
- return FALSE;
-
- return TRUE;
-}
-
-void
-k5_read_config_data(k5_config_data * d) {
- wchar_t * defrealm;
- char config_file[MAX_PATH];
- profile_t profile = NULL;
- const char *filenames[2];
- long rv;
- khm_size s;
-
- if (!k5_is_profile_loaded())
- return;
-
- defrealm = khm_krb5_get_default_realm();
-
- if (defrealm) {
- StringCbCopy(d->def_realm, sizeof(d->def_realm), defrealm);
- PFREE(defrealm);
- } else {
- StringCbCopy(d->def_realm, sizeof(d->def_realm), L"");
- }
-
- khm_krb5_get_profile_file(config_file, ARRAYLENGTH(config_file));
-
- AnsiStrToUnicode(d->config_file, sizeof(d->config_file), config_file);
-
- filenames[0] = config_file;
- filenames[1] = NULL;
-
- rv = pprofile_init(filenames, &profile);
-
- if (!rv) {
- const char * sec_realms[] = { "realms", NULL };
- const char * sec_domain_realm[] = { "domain_realm", NULL };
- char ** sections;
- char ** dr_from;
- char * boolv;
-
- /* first fish out a few values from [libdefaults] */
-
- rv = pprofile_get_string(profile, "libdefaults", "dns_lookup_kdc",
- NULL, NULL, &boolv);
- if (!rv && boolv) {
- d->dns_lookup_kdc = k5_parse_boolean(boolv);
- pprofile_release_string(boolv);
- } else
- d->dns_lookup_kdc = FALSE;
-
- rv = pprofile_get_string(profile, "libdefaults", "dns_lookup_realm",
- NULL, NULL, &boolv);
- if (!rv && boolv) {
- d->dns_lookup_realm = k5_parse_boolean(boolv);
- pprofile_release_string(boolv);
- } else
- d->dns_lookup_realm = FALSE;
-
- rv = pprofile_get_string(profile, "libdefaults", "dns_fallback",
- NULL, NULL, &boolv);
- if (!rv && boolv) {
- d->dns_fallback = k5_parse_boolean(boolv);
- pprofile_release_string(boolv);
- } else
- d->dns_fallback = FALSE;
-
- rv = pprofile_get_string(profile, "libdefaults", "noaddresses",
- NULL, NULL, &boolv);
- if (!rv && boolv) {
- d->noaddresses = k5_parse_boolean(boolv);
- pprofile_release_string(boolv);
- } else
- d->noaddresses = TRUE;
-
- /* now we look at the [realms] section */
- rv = pprofile_get_subsection_names(profile, sec_realms, &sections);
-
- /* what? no realms? whatever */
- if (rv) goto _skip_realms;
-
- /* get a count first */
- for (s=0; sections[s] && sections[s][0]; s++);
-
- k5_assert_n_realms(d, s);
- d->n_realms = s;
-
- /* now go through each and fish out the kdcs, admin_server
- and master_kdc. */
- for (s=0; sections[s] && sections[s][0]; s++) {
- const char * sec_kdcs[] =
- { "realms", sections[s], "kdc", NULL };
-
- const char * sec_admin[] =
- { "realms", sections[s], "admin_server", NULL };
-
- const char * sec_master[] =
- { "realms", sections[s], "master_kdc", NULL };
-
- char ** values;
-
- AnsiStrToUnicode(d->realms[s].realm, sizeof(d->realms[s].realm),
- sections[s]);
- d->realms[s].n_kdcs = 0;
- d->realms[s].n_domain_maps = 0;
-
- rv = pprofile_get_values(profile, sec_kdcs, &values);
- if (!rv) {
- khm_size i;
-
- for (i=0 ; values[i] && values[i][0] && i < K5_MAX_KDC; i++) {
- AnsiStrToUnicode(d->realms[s].kdcs[i].name,
- sizeof(d->realms[s].kdcs[i].name),
- values[i]);
-
- }
- d->realms[s].n_kdcs = i;
-
- pprofile_free_list(values);
- }
-
- rv = pprofile_get_values(profile, sec_admin, &values);
- if (!rv) {
- khm_size i;
- khm_size j;
- wchar_t kdc_name[K5_MAXCCH_HOST];
-
- for (i=0; values[i] && values[i][0]; i++) {
- AnsiStrToUnicode(kdc_name,
- sizeof(kdc_name), values[i]);
-
- for (j=0; j < d->realms[s].n_kdcs; j++)
- if (!wcsicmp(kdc_name, d->realms[s].kdcs[j].name))
- break;
-
- if (j < d->realms[s].n_kdcs) {
- d->realms[s].kdcs[j].admin = TRUE;
- } else if (d->realms[s].n_kdcs < K5_MAX_KDC) {
- j = d->realms[s].n_kdcs;
- StringCbCopy(d->realms[s].kdcs[j].name,
- sizeof(d->realms[s].kdcs[j].name),
- kdc_name);
- d->realms[s].kdcs[j].admin = TRUE;
- d->realms[s].n_kdcs ++;
- }
- }
- pprofile_free_list(values);
- }
-
- rv = pprofile_get_values(profile, sec_master, &values);
- if (!rv) {
- khm_size i;
- khm_size j;
- wchar_t kdc_name[K5_MAXCCH_HOST];
-
- for (i=0; values[i] && values[i][0]; i++) {
- AnsiStrToUnicode(kdc_name, sizeof(kdc_name), values[i]);
-
- for (j=0; j < d->realms[s].n_kdcs; j++)
- if (!wcsicmp(kdc_name, d->realms[s].kdcs[j].name))
- break;
-
- if (j < d->realms[s].n_kdcs) {
- d->realms[s].kdcs[j].master = TRUE;
- } else if (d->realms[s].n_kdcs < K5_MAX_KDC) {
- j = d->realms[s].n_kdcs;
- StringCbCopy(d->realms[s].kdcs[j].name,
- sizeof(d->realms[s].kdcs[j].name),
- kdc_name);
- d->realms[s].kdcs[j].master = TRUE;
- d->realms[s].n_kdcs ++;
- }
- }
-
- pprofile_free_list(values);
- }
- }
- pprofile_free_list(sections);
-
- _skip_realms:
-
- rv = pprofile_get_relation_names(profile, sec_domain_realm, &dr_from);
- if (!rv) {
- khm_size i;
- khm_size j;
- char * dr_to;
- wchar_t wdr_from[K5_MAXCCH_HOST];
- wchar_t wdr_to[K5_MAXCCH_HOST];
-
- for (i=0; dr_from[i] && dr_from[i][0]; i++) {
- AnsiStrToUnicode(wdr_from, sizeof(wdr_from), dr_from[i]);
-
- rv = pprofile_get_string(profile, "domain_realm", dr_from[i],
- NULL, NULL, &dr_to);
-
- if (rv || !dr_to)
- continue;
-
- AnsiStrToUnicode(wdr_to, sizeof(wdr_to), dr_to);
-
- for (j=0; j < d->n_realms; j++) {
- if (!wcsicmp(wdr_to, d->realms[j].realm))
- break;
- }
-
- if (j >= d->n_realms) {
- j = d->n_realms;
- k5_assert_n_realms(d, j + 1);
-
- StringCbCopy(d->realms[j].realm,
- sizeof(d->realms[j].realm),
- wdr_to);
- d->realms[j].n_kdcs = 0;
- d->realms[j].n_domain_maps = 0;
-
- d->n_realms++;
- }
-
- if (d->realms[j].n_domain_maps < K5_MAX_DOMAIN_MAPPINGS) {
- khm_size k;
-
- k = d->realms[j].n_domain_maps;
-
- StringCbCopy(d->realms[j].domain_maps[k].name,
- sizeof(d->realms[j].domain_maps[k].name),
- wdr_from);
-
- d->realms[j].n_domain_maps++;
- }
-
- pprofile_release_string(dr_to);
- }
- pprofile_free_list(dr_from);
- }
- pprofile_release(profile);
- }
-
- {
- khm_int32 t;
-
- /* last, read the MSLSA import setting */
- if (KHM_SUCCEEDED(khc_read_int32(csp_params,
- L"MsLsaImport", &t))) {
- d->lsa_import = t;
- } else {
- d->lsa_import = K5_LSAIMPORT_ALWAYS;
- }
-
- if (KHM_SUCCEEDED(khc_read_int32(csp_params,
- L"UseFullRealmList", &t))) {
- d->inc_realms = !!t;
- } else {
- d->inc_realms = TRUE;
- }
- }
-
- d->flags = 0;
-}
-
-void
-k5_write_config_data(k5_config_data * d) {
- char astr[MAX_PATH * 2];
- char config_file[MAX_PATH];
- profile_t profile = NULL;
- const char *filenames[2];
- long rv;
- khm_size s;
-
- if (d->flags == 0)
- return;
-
- if (!k5_is_profile_loaded())
- return;
-
- if (d->flags & K5_CDFLAG_MOD_DEF_REALM) {
- if (SUCCEEDED(StringCbLength(d->def_realm,
- sizeof(d->def_realm), &s)) &&
- s > 0) {
- khm_krb5_set_default_realm(d->def_realm);
- }
- }
-
- /* write the MSLSA import setting */
- if (d->flags & K5_CDFLAG_MOD_LSA_IMPORT) {
- khc_write_int32(csp_params, L"MsLsaImport", d->lsa_import);
- }
-
- if (d->flags & K5_CDFLAG_MOD_INC_REALMS) {
- khc_write_int32(csp_params, L"UseFullRealmList", d->inc_realms);
- }
-
- if (!(d->flags &
- (K5_CDFLAG_MOD_CONF_FILE |
- K5_CDFLAG_MOD_DNS_FALLBACK |
- K5_CDFLAG_MOD_DNS_LOOKUP_RLM |
- K5_CDFLAG_MOD_DNS_LOOKUP_KDC |
- K5_CDFLAG_MOD_NOADDRESSES |
- K5_CDFLAG_MOD_CREATE_CONF |
- K5_CDFLAG_MOD_REALMS))) {
-
- d->flags = 0;
- return;
-
- }
-
- khm_krb5_get_profile_file(config_file, ARRAYLENGTH(config_file));
-
- UnicodeStrToAnsi(astr, sizeof(astr), d->config_file);
-
- if (stricmp(config_file, astr)) {
- assert(FALSE);
- }
-
- filenames[0] = config_file;
- filenames[1] = NULL;
-
- rv = pprofile_init(filenames, &profile);
-
-#if FAILOVER_TO_TEMPORARY_FILE
- if (rv) {
- char temp_file[MAX_PATH];
-
- khm_krb5_get_temp_profile_file(temp_file,
- ARRAYLENGTH(temp_file));
-
- filenames[0] = temp_file;
-
- rv = pprofile_init(filenames, &profile);
-
- ?? TODO: Also warn if we are doing this
- }
-#endif
-
-
- if (!rv) {
- const char * sec_realms[] = { "realms", NULL };
- const char * sec_domain_realm[] = { "domain_realm", NULL };
- const char * sec_libdefaults[] = { "libdefaults", NULL, NULL };
- khm_size r;
-
- if (d->flags & K5_CDFLAG_MOD_DNS_LOOKUP_KDC) {
-
- sec_libdefaults[1] = "dns_lookup_kdc";
-
- pprofile_clear_relation(profile, sec_libdefaults);
-
- rv = pprofile_add_relation(profile, sec_libdefaults,
- (d->dns_lookup_kdc)?
- conf_yes[0]:
- conf_no[0]);
- }
-
-
- if (d->flags & K5_CDFLAG_MOD_DNS_LOOKUP_RLM) {
-
- sec_libdefaults[1] = "dns_lookup_realm";
-
- pprofile_clear_relation(profile, sec_libdefaults);
-
- rv = pprofile_add_relation(profile, sec_libdefaults,
- (d->dns_lookup_realm)?
- conf_yes[0]:
- conf_no[0]);
-
- }
-
- if (d->flags & K5_CDFLAG_MOD_DNS_FALLBACK) {
-
- sec_libdefaults[1] = "dns_fallback";
-
- pprofile_clear_relation(profile, sec_libdefaults);
-
- rv = pprofile_add_relation(profile, sec_libdefaults,
- (d->dns_fallback)?
- conf_yes[0]:
- conf_no[0]);
- }
-
- if (d->flags & K5_CDFLAG_MOD_NOADDRESSES) {
-
- sec_libdefaults[1] = "noaddresses";
-
- pprofile_clear_relation(profile, sec_libdefaults);
-
- rv = pprofile_add_relation(profile, sec_libdefaults,
- (d->noaddresses)?
- conf_yes[0]:
- conf_no[0]);
- }
-
- /* now we look at the [realms] section */
-
- for (r=0; r < d->n_realms; r++) {
- char realm[K5_MAXCCH_REALM];
- char host[K5_MAXCCH_HOST];
-
- const char * sec_kdcs[] =
- { "realms", realm, "kdc", NULL };
-
- const char * sec_admin[] =
- { "realms", realm, "admin_server", NULL };
-
- const char * sec_master[] =
- { "realms", realm, "master_kdc", NULL };
-
- const char * sec_domain_map[] =
- { "domain_realm", host, NULL };
-
- char ** values;
-
- UnicodeStrToAnsi(realm, sizeof(realm),
- d->realms[r].realm);
-
- if (!(d->realms[r].flags & K5_RDFLAG_DELETED) &&
- (d->realms[r].flags & K5_RDFLAG_NEW)) {
-
- khm_size k;
- khm_size m;
-
- /* this is a new realm */
-
- for (k=0; k < d->realms[r].n_kdcs; k++) {
- if (!(d->realms[r].kdcs[k].flags & K5_RKFLAG_DELETED)) {
- UnicodeStrToAnsi(host, sizeof(host),
- d->realms[r].kdcs[k].name);
-
- if (d->realms[r].kdcs[k].master)
- pprofile_add_relation(profile, sec_master,
- host);
- else
- pprofile_add_relation(profile, sec_kdcs,
- host);
-
- if (d->realms[r].kdcs[k].admin)
- pprofile_add_relation(profile, sec_admin,
- host);
- }
- }
-
- for (m=0; m < d->realms[r].n_domain_maps; m++) {
-
- UnicodeStrToAnsi(host, sizeof(host),
- d->realms[r].domain_maps[m].name);
-
- if ((d->realms[r].domain_maps[m].flags &
- K5_DMFLAG_DELETED) &&
- !(d->realms[r].domain_maps[m].flags &
- K5_DMFLAG_NEW))
- pprofile_clear_relation(profile, sec_domain_map);
- else if (!(d->realms[r].domain_maps[m].flags &
- K5_DMFLAG_DELETED) &&
- (d->realms[r].domain_maps[m].flags &
- K5_DMFLAG_NEW))
- pprofile_add_relation(profile, sec_domain_map,
- realm);
- }
- } else if ((d->realms[r].flags & K5_RDFLAG_DELETED) &&
- !(d->realms[r].flags & K5_RDFLAG_NEW)) {
-
- const char * sec_all[] =
- { "realms", realm, NULL, NULL };
- khm_size v;
-
- /* this realm should be deleted */
-
- rv = pprofile_get_relation_names(profile, sec_all,
- &values);
- if (!rv) {
- for (v=0; values[v] && values[v][0]; v++) {
- sec_all[2] = values[v];
- pprofile_clear_relation(profile, sec_all);
- }
- pprofile_free_list(values);
- }
-
- rv = pprofile_get_relation_names(profile, sec_domain_realm,
- &values);
- if (!rv) {
- char * maprealm;
-
- for (v=0; values[v] && values[v][0]; v++) {
-
- rv = pprofile_get_string(profile, "domain_realm",
- values[v], NULL, NULL,
- &maprealm);
-
- if (!rv) {
- if (!strcmp(maprealm, realm)) {
- StringCbCopyA(host, sizeof(host),
- values[v]);
- pprofile_clear_relation(profile,
- sec_domain_map);
- }
- pprofile_release_string(maprealm);
- }
- }
-
- pprofile_free_list(values);
- }
- } else if (!(d->realms[r].flags & K5_RDFLAG_DELETED)) {
- khm_size k;
- khm_size m;
-
- /* same as before. check if we have to update the kdc
- list or the domain_realm mappings */
-
- for (k=0; k < d->realms[r].n_kdcs; k++) {
- UnicodeStrToAnsi(host, sizeof(host),
- d->realms[r].kdcs[k].name);
- if (d->realms[r].kdcs[k].flags & K5_RKFLAG_DELETED) {
- pprofile_update_relation(profile, sec_kdcs,
- host, NULL);
- pprofile_update_relation(profile, sec_admin,
- host, NULL);
- pprofile_update_relation(profile, sec_master,
- host, NULL);
-
- continue;
- }
-
- if (d->realms[r].kdcs[k].flags & K5_RKFLAG_NEW) {
- if (d->realms[r].kdcs[k].master)
- pprofile_add_relation(profile, sec_master,
- host);
- else
- pprofile_add_relation(profile, sec_kdcs,
- host);
-
- if (d->realms[r].kdcs[k].admin)
- pprofile_add_relation(profile, sec_admin,
- host);
- continue;
- }
-
- if (d->realms[r].kdcs[k].flags & K5_RKFLAG_MOD_MASTER) {
- if (!d->realms[r].kdcs[k].master) {
- pprofile_add_relation(profile, sec_kdcs,
- host);
- pprofile_update_relation(profile, sec_master,
- host, NULL);
- } else {
- pprofile_add_relation(profile, sec_master,
- host);
- pprofile_update_relation(profile, sec_kdcs,
- host, NULL);
- }
- }
-
- if (d->realms[r].kdcs[k].flags & K5_RKFLAG_MOD_ADMIN) {
- if (d->realms[r].kdcs[k].admin)
- pprofile_add_relation(profile, sec_admin,
- host);
- else
- pprofile_update_relation(profile, sec_admin,
- host, NULL);
- }
- }
-
- for (m=0; m < d->realms[r].n_domain_maps; m++) {
-
- UnicodeStrToAnsi(host, sizeof(host),
- d->realms[r].domain_maps[m].name);
-
- if ((d->realms[r].domain_maps[m].flags &
- K5_DMFLAG_DELETED) &&
- !(d->realms[r].domain_maps[m].flags &
- K5_DMFLAG_NEW))
- pprofile_clear_relation(profile, sec_domain_map);
- else if (!(d->realms[r].domain_maps[m].flags &
- K5_DMFLAG_DELETED) &&
- (d->realms[r].domain_maps[m].flags &
- K5_DMFLAG_NEW))
- pprofile_add_relation(profile, sec_domain_map,
- realm);
- }
- }
- }
-
- rv = pprofile_flush(profile);
-
- pprofile_release(profile);
- }
-
- if (rv) {
- khui_alert * alert;
- wchar_t title[KHUI_MAXCCH_TITLE];
- wchar_t fmsg[KHUI_MAXCCH_MESSAGE];
- wchar_t msg[KHUI_MAXCCH_MESSAGE];
- wchar_t sugg[KHUI_MAXCCH_SUGGESTION];
-
- LoadString(hResModule, IDS_K5ERR_CANTWRITEPROFILE,
- title, ARRAYLENGTH(title));
- if (rv)
- LoadString(hResModule, IDS_K5ERR_PROFNOWRITE,
- fmsg, ARRAYLENGTH(fmsg));
-
- LoadString(hResModule, IDS_K5ERR_PROFSUGGEST,
- sugg, ARRAYLENGTH(sugg));
-
- StringCbPrintf(msg, sizeof(msg), fmsg, config_file);
-
- khui_alert_create_empty(&alert);
- khui_alert_set_severity(alert, (rv)?KHERR_ERROR:KHERR_WARNING);
- khui_alert_set_title(alert, title);
- khui_alert_set_message(alert, msg);
- khui_alert_set_suggestion(alert, sugg);
-
- khui_alert_show(alert);
- }
-
- d->flags = 0;
-}
-
-/* actual dialog stuff */
-
-#define IDX_NORMAL 1
-#define IDX_MODIFIED 2
-#define IDX_NEW 3
-#define IDX_DELETED 4
-
-static k5_config_data k5_config_dlg_data;
-static khm_boolean k5_dlg_data_valid = FALSE;
-
-INT_PTR CALLBACK
-k5_config_dlgproc(HWND hwnd,
- UINT uMsg,
- WPARAM wParam,
- LPARAM lParam) {
- switch(uMsg) {
- case WM_INITDIALOG:
- {
- HWND hw;
- khm_size i;
- k5_config_data * d;
-
- wchar_t * t;
- wchar_t importopts[256];
- WKSTA_INFO_100 * winfo100;
-
-#ifdef DEBUG
- assert(!k5_dlg_data_valid);
-#endif
-
- k5_init_config_data(&k5_config_dlg_data);
- k5_read_config_data(&k5_config_dlg_data);
-
- k5_dlg_data_valid = TRUE;
-
- d = &k5_config_dlg_data;
-
- d->node_main = (khui_config_node) lParam;
-
- CheckDlgButton(hwnd, IDC_CFG_INCREALMS,
- (d->inc_realms)? BST_CHECKED: BST_UNCHECKED);
-
- hw = GetDlgItem(hwnd, IDC_CFG_DEFREALM);
-#ifdef DEBUG
- assert(hw);
-#endif
-
- SendMessage(hw, CB_RESETCONTENT, 0, 0);
-
- for (i=0; i < d->n_realms; i++) {
- SendMessage(hw, CB_ADDSTRING, 0,
- (LPARAM) d->realms[i].realm);
- }
-
- SendMessage(hw, CB_SELECTSTRING, -1,
- (LPARAM) d->def_realm);
-
- SetDlgItemText(hwnd, IDC_CFG_CFGFILE, d->config_file);
-
- /* hostname/domain */
- if (NetWkstaGetInfo(NULL, 100, (LPBYTE *) &winfo100) == NERR_Success) {
- SetDlgItemText(hwnd, IDC_CFG_HOSTNAME, winfo100->wki100_computername);
- SetDlgItemText(hwnd, IDC_CFG_DOMAIN, winfo100->wki100_langroup);
- NetApiBufferFree(winfo100);
- }
-
- /* and the import ticket options */
- LoadString(hResModule, IDS_K5CFG_IMPORT_OPTIONS,
- importopts, ARRAYLENGTH(importopts));
-
- hw = GetDlgItem(hwnd, IDC_CFG_IMPORT);
-#ifdef DEBUG
- assert(hw);
-#endif
- SendMessage(hw, CB_RESETCONTENT, 0, 0);
-
- for (t=importopts;
- t && *t && *t != L' ' &&
- t < importopts + ARRAYLENGTH(importopts);
- t = multi_string_next(t)) {
-
- SendMessage(hw, CB_ADDSTRING, 0, (LPARAM) t);
- }
-
- SendMessage(hw, CB_SETCURSEL, 0, d->lsa_import);
- t = importopts;
- SendMessage(hw, CB_GETLBTEXT, d->lsa_import,(LPARAM) t);
- SendMessage(hw, CB_SELECTSTRING, -1, (LPARAM) t);
- }
- break;
-
- case WM_COMMAND:
- {
- k5_config_data * d;
-
- d = &k5_config_dlg_data;
-
- if (wParam == MAKEWPARAM(IDC_CFG_IMPORT, CBN_SELCHANGE)) {
- int idx;
- int modified = FALSE;
-
- idx = (int) SendDlgItemMessage(hwnd, IDC_CFG_IMPORT,
- CB_GETCURSEL, 0, 0);
- if (idx != CB_ERR && idx != d->lsa_import) {
- d->lsa_import = idx;
- d->flags |= K5_CDFLAG_MOD_LSA_IMPORT;
- modified = TRUE;
- }
-
- khui_cfg_set_flags(d->node_main,
- (modified)?KHUI_CNFLAG_MODIFIED:0,
- KHUI_CNFLAG_MODIFIED);
- return TRUE;
- }
-
- if (wParam == MAKEWPARAM(IDC_CFG_INCREALMS, BN_CLICKED)) {
- if (IsDlgButtonChecked(hwnd, IDC_CFG_INCREALMS) ==
- BST_CHECKED) {
- d->inc_realms = TRUE;
- } else {
- d->inc_realms = FALSE;
- }
- d->flags |= K5_CDFLAG_MOD_INC_REALMS;
-
- khui_cfg_set_flags(d->node_main,
- KHUI_CNFLAG_MODIFIED,
- KHUI_CNFLAG_MODIFIED);
- return TRUE;
- }
- }
- break;
-
- case KHUI_WM_CFG_NOTIFY:
- {
- k5_config_data * d;
-
- d = &k5_config_dlg_data;
-
- if (HIWORD(wParam) == WMCFG_APPLY) {
- khm_int32 oflags;
-
- oflags = d->flags;
- k5_write_config_data(d);
-
- if (d->flags != oflags) {
- khui_cfg_set_flags(d->node_main,
- KHUI_CNFLAG_APPLIED,
- KHUI_CNFLAG_APPLIED |
- KHUI_CNFLAG_MODIFIED);
- }
- return TRUE;
- }
- }
- break;
-
- case WM_DESTROY:
- {
- k5_free_config_data(&k5_config_dlg_data);
- k5_dlg_data_valid = FALSE;
- }
- break;
- }
- return FALSE;
-}
-
-static HIMAGELIST
-k5_get_state_image_list(void) {
- HIMAGELIST hil;
- HICON hicon;
-
- hil = ImageList_Create(GetSystemMetrics(SM_CXSMICON),
- GetSystemMetrics(SM_CYSMICON),
- ILC_COLOR | ILC_MASK,
- 4,
- 2);
-
- hicon = LoadImage(hResModule,
- MAKEINTRESOURCE(IDI_NORMAL),
- IMAGE_ICON,
- GetSystemMetrics(SM_CXSMICON),
- GetSystemMetrics(SM_CYSMICON),
- LR_DEFAULTCOLOR);
-
- ImageList_AddIcon(hil, hicon);
-
- DestroyIcon(hicon);
-
- hicon = LoadImage(hResModule,
- MAKEINTRESOURCE(IDI_MODIFIED),
- IMAGE_ICON,
- GetSystemMetrics(SM_CXSMICON),
- GetSystemMetrics(SM_CYSMICON),
- LR_DEFAULTCOLOR);
-
- ImageList_AddIcon(hil, hicon);
-
- DestroyIcon(hicon);
-
- hicon = LoadImage(hResModule,
- MAKEINTRESOURCE(IDI_NEW),
- IMAGE_ICON,
- GetSystemMetrics(SM_CXSMICON),
- GetSystemMetrics(SM_CYSMICON),
- LR_DEFAULTCOLOR);
-
- ImageList_AddIcon(hil, hicon);
-
- DestroyIcon(hicon);
-
- hicon = LoadImage(hResModule,
- MAKEINTRESOURCE(IDI_DELETED),
- IMAGE_ICON,
- GetSystemMetrics(SM_CXSMICON),
- GetSystemMetrics(SM_CYSMICON),
- LR_DEFAULTCOLOR);
-
- ImageList_AddIcon(hil, hicon);
-
- DestroyIcon(hicon);
-
- return hil;
-}
-
-static void
-k5_update_realms_display(HWND hw_list, k5_config_data * d) {
- khm_size i;
- LVITEM lvi;
- wchar_t buf[64];
-
- ListView_DeleteAllItems(hw_list);
-
- for (i=0; i < d->n_realms; i++) {
- if ((d->realms[i].flags & K5_RDFLAG_DELETED) &&
- (d->realms[i].flags & K5_RDFLAG_NEW))
- continue;
-
- ZeroMemory(&lvi, sizeof(lvi));
- lvi.mask = LVIF_PARAM | LVIF_STATE | LVIF_TEXT;
- lvi.iItem = 0;
- lvi.iSubItem = 0;
- lvi.pszText = d->realms[i].realm;
- lvi.lParam = i;
-
- if (d->realms[i].flags & K5_RDFLAG_DELETED) {
- lvi.state = INDEXTOSTATEIMAGEMASK(IDX_DELETED);
- } else if (d->realms[i].flags & K5_RDFLAG_NEW) {
- lvi.state = INDEXTOSTATEIMAGEMASK(IDX_NEW);
- } else if (d->realms[i].flags & K5_RDFLAG_MODIFED) {
- lvi.state = INDEXTOSTATEIMAGEMASK(IDX_MODIFIED);
- } else {
- lvi.state = INDEXTOSTATEIMAGEMASK(IDX_NORMAL);
- }
- lvi.stateMask = LVIS_STATEIMAGEMASK;
-
- ListView_InsertItem(hw_list, &lvi);
- }
-
- ZeroMemory(&lvi, sizeof(lvi));
- lvi.mask = LVIF_PARAM | LVIF_STATE | LVIF_TEXT;
- lvi.iItem = 0;
- lvi.iSubItem = 0;
- lvi.pszText = buf;
- lvi.lParam = (LPARAM) -1;
-
- LoadString(hResModule, IDS_CFG_RE_NEWREALM,
- buf, ARRAYLENGTH(buf));
-
- lvi.state = INDEXTOSTATEIMAGEMASK(IDX_NEW);
- lvi.stateMask = LVIS_STATEIMAGEMASK;
-
- ListView_InsertItem(hw_list, &lvi);
-
- if (d->flags & K5_CDFLAG_MOD_REALMS) {
- khui_cfg_set_flags(d->node_realm, KHUI_CNFLAG_MODIFIED,
- KHUI_CNFLAG_MODIFIED);
- } else {
- khui_cfg_set_flags(d->node_realm, 0,
- KHUI_CNFLAG_MODIFIED);
- }
-}
-
-static void
-k5_update_kdcs_display(HWND hw_kdc, k5_config_data * d, khm_size idx_rlm) {
- khm_size k;
- LVITEM lvi;
- int idx_item;
- k5_realm_kdc * pkdc;
- wchar_t wyes[8];
- wchar_t wno[8];
- wchar_t wbuf[64];
-
- ListView_DeleteAllItems(hw_kdc);
-
- if (d == NULL)
- return;
-
-#ifdef DEBUG
- assert(idx_rlm < d->n_realms);
-#endif
- LoadString(hResModule, IDS_YES, wyes, ARRAYLENGTH(wyes));
- LoadString(hResModule, IDS_NO, wno, ARRAYLENGTH(wno));
-
- for (k=0; k < d->realms[idx_rlm].n_kdcs; k++) {
- if ((d->realms[idx_rlm].kdcs[k].flags & K5_RKFLAG_DELETED) &&
- (d->realms[idx_rlm].kdcs[k].flags & K5_RKFLAG_NEW))
- continue;
-
- pkdc = &(d->realms[idx_rlm].kdcs[k]);
-
- ZeroMemory(&lvi, sizeof(lvi));
- lvi.mask = LVIF_PARAM | LVIF_STATE | LVIF_TEXT;
- lvi.iItem = K5_MAX_KDC;
- lvi.iSubItem = 0;
- lvi.lParam = k;
- lvi.pszText = pkdc->name;
- if (pkdc->flags & K5_RKFLAG_DELETED) {
- lvi.state = INDEXTOSTATEIMAGEMASK(IDX_DELETED);
- } else if (pkdc->flags & K5_RKFLAG_NEW) {
- lvi.state = INDEXTOSTATEIMAGEMASK(IDX_NEW);
- } else if ((pkdc->flags & K5_RKFLAG_MOD_ADMIN) ||
- (pkdc->flags & K5_RKFLAG_MOD_MASTER)) {
- lvi.state = INDEXTOSTATEIMAGEMASK(IDX_MODIFIED);
- } else {
- lvi.state = INDEXTOSTATEIMAGEMASK(IDX_NORMAL);
- }
- lvi.stateMask = LVIS_STATEIMAGEMASK;
-
- idx_item = ListView_InsertItem(hw_kdc, &lvi);
-
- lvi.mask = LVIF_TEXT;
- lvi.iItem = idx_item;
- lvi.iSubItem = 1;
- if (pkdc->admin)
- lvi.pszText = wyes;
- else
- lvi.pszText = wno;
- ListView_SetItem(hw_kdc, &lvi);
-
- lvi.iSubItem = 2;
- if (pkdc->master)
- lvi.pszText = wyes;
- else
- lvi.pszText = wno;
- ListView_SetItem(hw_kdc, &lvi);
- }
-
- ZeroMemory(&lvi, sizeof(lvi));
- lvi.mask = LVIF_TEXT | LVIF_PARAM | LVIF_STATE;
- lvi.iItem = 0;
- lvi.iSubItem = 0;
- lvi.pszText = wbuf;
- lvi.lParam = (LPARAM) -1;
- lvi.state = INDEXTOSTATEIMAGEMASK(IDX_NEW);
- lvi.stateMask = LVIS_STATEIMAGEMASK;
-
- LoadString(hResModule, IDS_CFG_RE_NEWSERVER,
- wbuf, ARRAYLENGTH(wbuf));
-
- ListView_InsertItem(hw_kdc, &lvi);
-}
-
-static void
-k5_update_dmap_display(HWND hw_dm, k5_config_data * d, khm_size idx_rlm) {
- khm_size m;
- LVITEM lvi;
- k5_domain_map * map;
- wchar_t wbuf[64];
-
- ListView_DeleteAllItems(hw_dm);
-
- if (d == NULL)
- return;
-
-#ifdef DEBUG
- assert(idx_rlm < d->n_realms);
-#endif
-
- for (m=0; m < d->realms[idx_rlm].n_domain_maps; m++) {
- map = &(d->realms[idx_rlm].domain_maps[m]);
-
- if ((map->flags & K5_DMFLAG_NEW) &&
- (map->flags & K5_DMFLAG_DELETED))
- continue;
-
- ZeroMemory(&lvi, sizeof(lvi));
-
- lvi.mask = LVIF_TEXT | LVIF_STATE | LVIF_PARAM;
- lvi.pszText = map->name;
- if (map->flags & K5_DMFLAG_DELETED)
- lvi.state = INDEXTOSTATEIMAGEMASK(IDX_DELETED);
- else if (map->flags & K5_DMFLAG_NEW)
- lvi.state = INDEXTOSTATEIMAGEMASK(IDX_NEW);
- else
- lvi.state = INDEXTOSTATEIMAGEMASK(IDX_NORMAL);
- lvi.stateMask = LVIS_STATEIMAGEMASK;
- lvi.lParam = m;
-
- lvi.iItem = K5_MAX_DOMAIN_MAPPINGS;
- lvi.iSubItem = 0;
-
- ListView_InsertItem(hw_dm, &lvi);
- }
-
- ZeroMemory(&lvi, sizeof(lvi));
- lvi.mask = LVIF_PARAM | LVIF_TEXT | LVIF_STATE;
- lvi.pszText = wbuf;
- lvi.lParam = (LPARAM) -1;
- lvi.state = INDEXTOSTATEIMAGEMASK(IDX_NEW);
- lvi.stateMask = LVIS_STATEIMAGEMASK;
- lvi.iItem = 0;
- lvi.iSubItem = 0;
-
- LoadString(hResModule, IDS_CFG_RE_NEWDMAP,
- wbuf, ARRAYLENGTH(wbuf));
-
- ListView_InsertItem(hw_dm, &lvi);
-}
-
-INT_PTR CALLBACK
-k5_realms_dlgproc(HWND hwnd,
- UINT uMsg,
- WPARAM wParam,
- LPARAM lParam) {
- k5_config_data * d;
-
- d = &k5_config_dlg_data;
-
- switch(uMsg) {
- case WM_INITDIALOG:
- {
- LVCOLUMN lvc;
- HWND hw;
- RECT r;
- wchar_t buf[256];
-
- assert(k5_dlg_data_valid);
-
- d->node_realm = (khui_config_node) lParam;
-
- /* set up columns for the Realms list */
- hw = GetDlgItem(hwnd, IDC_CFG_REALMS);
-#ifdef DEBUG
- assert(hw);
-#endif
- GetWindowRect(hw, &r);
- r.right -= 5; /* shave a few pixels off the width */
- ZeroMemory(&lvc, sizeof(lvc));
- lvc.mask = LVCF_TEXT | LVCF_WIDTH;
- lvc.pszText = buf;
- lvc.cx = (r.right - r.left);
- LoadString(hResModule, IDS_CFG_RE_REALMS,
- buf, ARRAYLENGTH(buf));
-
- ListView_InsertColumn(hw, 0, &lvc);
-
- ListView_SetImageList(hw,
- k5_get_state_image_list(),
- LVSIL_STATE);
-
- k5_update_realms_display(hw, d);
-
- /* set up columns for the servers list */
- hw = GetDlgItem(hwnd, IDC_CFG_KDC);
-#ifdef DEBUG
- assert(hw);
-#endif
- GetWindowRect(hw, &r);
- r.right -= 5;
- ZeroMemory(&lvc, sizeof(lvc));
- lvc.mask = LVCF_TEXT | LVCF_WIDTH;
- lvc.pszText = buf;
- lvc.cx = (r.right - r.left) * 2 / 4;
- LoadString(hResModule, IDS_CFG_RE_HEAD_SVR,
- buf, ARRAYLENGTH(buf));
-
- ListView_InsertColumn(hw, 0, &lvc);
-
- lvc.cx = (r.right - r.left) * 1 / 4;
- LoadString(hResModule, IDS_CFG_RE_HEAD_ADMIN,
- buf, ARRAYLENGTH(buf));
- ListView_InsertColumn(hw, 1, &lvc);
-
- LoadString(hResModule, IDS_CFG_RE_HEAD_MASTER,
- buf, ARRAYLENGTH(buf));
- ListView_InsertColumn(hw, 2, &lvc);
-
- ListView_SetImageList(hw,
- k5_get_state_image_list(),
- LVSIL_STATE);
-
- /* set up columns for the domain/host mapping list */
- hw = GetDlgItem(hwnd, IDC_CFG_DMAP);
-#ifdef DEBUG
- assert(hw);
-#endif
- GetWindowRect(hw, &r);
- r.right -= 5;
- ZeroMemory(&lvc, sizeof(lvc));
- lvc.mask = LVCF_TEXT | LVCF_WIDTH;
- lvc.pszText = buf;
- lvc.cx = (r.right - r.left);
- LoadString(hResModule, IDS_CFG_RE_HEAD_DOMAIN,
- buf, ARRAYLENGTH(buf));
-
- ListView_InsertColumn(hw, 0, &lvc);
-
-
- ListView_SetImageList(hw,
- k5_get_state_image_list(),
- LVSIL_STATE);
- }
- break;
-
- case WM_NOTIFY:
- {
- LPNMHDR pnmh;
- HWND hw_rlm = NULL;
- HWND hw_kdc = NULL;
- HWND hw_dmp = NULL;
- int i;
-
- pnmh = (LPNMHDR) lParam;
-
- if (pnmh->idFrom == IDC_CFG_REALMS) {
-
- hw_rlm = pnmh->hwndFrom;
-
- switch(pnmh->code) {
- case LVN_ITEMCHANGED:
- i = ListView_GetSelectedCount(hw_rlm);
- hw_kdc = GetDlgItem(hwnd, IDC_CFG_KDC);
- hw_dmp = GetDlgItem(hwnd, IDC_CFG_DMAP);
-
- d->c_realm = (khm_size) -1;
-
- if (i == 1) {
- LVITEM lvi;
-
- i = ListView_GetNextItem(hw_rlm, -1,
- LVNI_SELECTED);
- if (i == -1)
- goto _no_selection;
-
- ZeroMemory(&lvi, sizeof(lvi));
-
- lvi.iItem = i;
- lvi.iSubItem = 0;
- lvi.mask = LVIF_PARAM;
-
- ListView_GetItem(hw_rlm, &lvi);
-
- if (lvi.lParam == -1)
- goto _no_selection;
-
- d->c_realm = lvi.lParam;
-
- k5_update_kdcs_display(hw_kdc, d, lvi.lParam);
- k5_update_dmap_display(hw_dmp, d, lvi.lParam);
- return TRUE;
- }
-
- _no_selection:
- ListView_DeleteAllItems(hw_kdc);
- ListView_DeleteAllItems(hw_dmp);
- break;
-
- case LVN_BEGINLABELEDIT:
- {
- NMLVDISPINFO * pdisp;
- LVITEM lvi;
-
- pdisp = (NMLVDISPINFO *) lParam;
-
- ZeroMemory(&lvi, sizeof(lvi));
- lvi.iItem = pdisp->item.iItem;
- lvi.mask = LVIF_PARAM;
-
- ListView_GetItem(hw_rlm, &lvi);
-
- if (pdisp->item.iItem == -1 ||
- lvi.lParam != -1) {
- SetWindowLongPtr(hwnd, DWL_MSGRESULT, TRUE);
- } else {
- /* allow editing */
- HWND hw_edit;
-
- hw_edit = ListView_GetEditControl(hw_rlm);
- if (hw_edit != NULL) {
- SendMessage(hw_edit,
- EM_SETLIMITTEXT,
- K5_MAXCCH_REALM - 1,
- 0);
- }
- SetWindowLongPtr(hwnd, DWL_MSGRESULT, FALSE);
- }
-
- return TRUE;
- }
- break;
-
- case LVN_ENDLABELEDIT:
- {
- NMLVDISPINFO * pdisp;
- khm_size n;
-
- pdisp = (NMLVDISPINFO *) lParam;
-
- if (pdisp->item.pszText) {
- n = d->n_realms;
- k5_assert_n_realms(d, n+1);
- StringCbCopy(d->realms[n].realm,
- sizeof(d->realms[n].realm),
- pdisp->item.pszText);
- d->realms[n].flags = K5_RDFLAG_NEW;
- d->n_realms++;
-
- d->flags |= K5_CDFLAG_MOD_REALMS;
-
- k5_update_realms_display(hw_rlm, d);
- }
-
- return TRUE;
- }
- break;
-
- case LVN_KEYDOWN:
- {
- NMLVKEYDOWN * pnmk;
- LVITEM lvi;
- khm_size r;
- int idx;
- BOOL modified = FALSE;
-
- pnmk = (NMLVKEYDOWN *) lParam;
-
- if (pnmk->wVKey == VK_DELETE) {
- idx = -1;
- while((idx = ListView_GetNextItem(hw_rlm, idx,
- LVNI_SELECTED))
- != -1) {
- ZeroMemory(&lvi, sizeof(lvi));
- lvi.iItem = idx;
- lvi.iSubItem = 0;
- lvi.mask = LVIF_PARAM;
-
- ListView_GetItem(hw_rlm, &lvi);
-
- if (lvi.lParam != -1 &&
- (r = lvi.lParam) < d->n_realms) {
- d->realms[r].flags ^= K5_RDFLAG_DELETED;
- modified = TRUE;
- }
- }
-
- if (modified) {
- d->flags |= K5_CDFLAG_MOD_REALMS;
-
- k5_purge_config_data(d, TRUE, TRUE, TRUE);
- k5_update_realms_display(hw_rlm, d);
- k5_update_dmap_display(GetDlgItem(hwnd, IDC_CFG_DMAP), NULL, 0);
- k5_update_kdcs_display(GetDlgItem(hwnd, IDC_CFG_KDC), NULL, 0);
- }
- return TRUE;
- }
- }
- break;
- }
- } else if (pnmh->idFrom == IDC_CFG_KDC) {
- hw_kdc = pnmh->hwndFrom;
-
- switch (pnmh->code) {
- case LVN_BEGINLABELEDIT:
- {
- NMLVDISPINFO * pdisp;
- LVITEM lvi;
-
- pdisp = (NMLVDISPINFO *) lParam;
-
- ZeroMemory(&lvi, sizeof(lvi));
- lvi.iItem = pdisp->item.iItem;
- lvi.mask = LVIF_PARAM;
-
- ListView_GetItem(hw_kdc, &lvi);
-
- if (pdisp->item.iItem == -1 ||
- lvi.lParam != -1) {
- SetWindowLongPtr(hwnd, DWL_MSGRESULT, TRUE);
- } else {
- /* allow editing */
- HWND hw_edit;
-
- hw_edit = ListView_GetEditControl(hw_kdc);
- if (hw_edit != NULL) {
- SendMessage(hw_edit,
- EM_SETLIMITTEXT,
- K5_MAXCCH_HOST - 1,
- 0);
- }
- SetWindowLongPtr(hwnd, DWL_MSGRESULT, FALSE);
- }
- return TRUE;
- }
- break;
-
- case LVN_ENDLABELEDIT:
- {
- NMLVDISPINFO * pdisp;
- khm_size r;
- khm_size k;
-
- r = d->c_realm;
-
- pdisp = (NMLVDISPINFO *) lParam;
-
- if (pdisp->item.pszText) {
- k = d->realms[r].n_kdcs;
-
- if (k >= K5_MAX_KDC) {
- SetWindowLongPtr(hwnd, DWL_MSGRESULT, FALSE);
- /* TODO: show a message box saying
- there are too many KDC's
- already. */
- return TRUE;
- }
-
- StringCbCopy(d->realms[r].kdcs[k].name,
- sizeof(d->realms[0].kdcs[0].name),
- pdisp->item.pszText);
- d->realms[r].kdcs[k].flags = K5_RKFLAG_NEW;
- d->realms[r].n_kdcs++;
-
- d->realms[r].flags |= K5_RDFLAG_MODIFED;
-
- k5_update_kdcs_display(hw_kdc, d, d->c_realm);
- }
- return TRUE;
- }
- break;
-
- case LVN_KEYDOWN:
- {
-#if 0
- NMLVKEYDOWN * pnmk;
- LVITEM lvi;
- khm_size r;
- int idx;
- BOOL modified = FALSE;
-
- pnmk = (NMLVKEYDOWN *) lParam;
-
- if (pnmk->wVKey == VK_DELETE) {
- idx = -1;
- while((idx = ListView_GetNextItem(hw_rlm, idx,
- LVNI_SELECTED))
- != -1) {
- ZeroMemory(&lvi, sizeof(lvi));
- lvi.iItem = idx;
- lvi.iSubItem = 0;
- lvi.mask = LVIF_PARAM;
-
- ListView_GetItem(hw_rlm, &lvi);
-
- if (lvi.lParam != -1 &&
- (r = lvi.lParam) < d->n_realms) {
- d->realms[r].flags ^= K5_RDFLAG_DELETED;
- modified = TRUE;
- }
- }
-
- if (modified) {
- d->flags |= K5_CDFLAG_MOD_REALMS;
-
- k5_purge_config_data(d, TRUE, TRUE, TRUE);
- k5_update_realms_display(hw_rlm, d);
- k5_update_dmap_display(GetDlgItem(hwnd, IDC_CFG_DMAP), NULL, 0);
- k5_update_kdcs_display(GetDlgItem(hwnd, IDC_CFG_KDC), NULL, 0);
- }
- return TRUE;
- }
-#endif
- }
- break;
- }
- }
- }
- break;
-
- case WM_DESTROY:
- break;
- }
- return FALSE;
-}
-
-void
-k5_register_config_panels(void) {
- khui_config_node node;
- khui_config_node_reg reg;
- wchar_t wshort[KHUI_MAXCCH_SHORT_DESC];
- wchar_t wlong[KHUI_MAXCCH_LONG_DESC];
-
- ZeroMemory(&reg, sizeof(reg));
-
- LoadString(hResModule, IDS_K5CFG_SHORT_DESC,
- wshort, ARRAYLENGTH(wshort));
- LoadString(hResModule, IDS_K5CFG_LONG_DESC,
- wlong, ARRAYLENGTH(wlong));
-
- reg.name = L"Kerberos5";
- reg.short_desc = wshort;
- reg.long_desc = wlong;
- reg.h_module = hResModule;
- reg.dlg_template = MAKEINTRESOURCE(IDD_CONFIG);
- reg.dlg_proc = k5_config_dlgproc;
- reg.flags = 0;
-
- khui_cfg_register(NULL, &reg);
-
- if (KHM_FAILED(khui_cfg_open(NULL, L"Kerberos5", &node))) {
- node = NULL;
-#ifdef DEBUG
- assert(FALSE);
-#endif
- }
-
-#ifdef REALM_EDITOR
- ZeroMemory(&reg, sizeof(reg));
-
- LoadString(hResModule, IDS_K5RLM_SHORT_DESC,
- wshort, ARRAYLENGTH(wshort));
- LoadString(hResModule, IDS_K5RLM_LONG_DESC,
- wlong, ARRAYLENGTH(wlong));
-
- reg.name = L"KerberosRealms";
- reg.short_desc = wshort;
- reg.long_desc = wlong;
- reg.h_module = hResModule;
- reg.dlg_template = MAKEINTRESOURCE(IDD_CFG_REALMS);
- reg.dlg_proc = k5_realms_dlgproc;
- reg.flags = 0;
-
- khui_cfg_register(node, &reg);
-#endif
-
- ZeroMemory(&reg, sizeof(reg));
-
- LoadString(hResModule, IDS_K5CCC_SHORT_DESC,
- wshort, ARRAYLENGTH(wshort));
- LoadString(hResModule, IDS_K5CCC_LONG_DESC,
- wlong, ARRAYLENGTH(wlong));
-
- reg.name = L"KerberosCCaches";
- reg.short_desc = wshort;
- reg.long_desc = wlong;
- reg.h_module = hResModule;
- reg.dlg_template = MAKEINTRESOURCE(IDD_CFG_CACHES);
- reg.dlg_proc = k5_ccconfig_dlgproc;
- reg.flags = 0;
-
- khui_cfg_register(node, &reg);
-
- khui_cfg_release(node);
-
- if (KHM_FAILED(khui_cfg_open(NULL, L"KhmIdentities", &node))) {
- node = NULL;
-#ifdef DEBUG
- assert(FALSE);
-#endif
- }
-
- ZeroMemory(&reg, sizeof(reg));
-
- LoadString(hResModule, IDS_K5CFG_IDS_SHORT_DESC,
- wshort, ARRAYLENGTH(wshort));
- LoadString(hResModule, IDS_K5CFG_IDS_LONG_DESC,
- wlong, ARRAYLENGTH(wlong));
-
- reg.name = L"KerberosIdentities";
- reg.short_desc = wshort;
- reg.long_desc = wlong;
- reg.h_module = hResModule;
- reg.dlg_template = MAKEINTRESOURCE(IDD_CFG_IDS_TAB);
- reg.dlg_proc = k5_ids_tab_dlgproc;
- reg.flags = KHUI_CNFLAG_SUBPANEL;
-
- khui_cfg_register(node, &reg);
-
- ZeroMemory(&reg, sizeof(reg));
-
- LoadString(hResModule, IDS_K5CFG_ID_SHORT_DESC,
- wshort, ARRAYLENGTH(wshort));
- LoadString(hResModule, IDS_K5CFG_ID_LONG_DESC,
- wlong, ARRAYLENGTH(wlong));
-
- reg.name = L"KerberosIdentitiesPlural";
- reg.short_desc = wshort;
- reg.long_desc = wlong;
- reg.h_module = hResModule;
- reg.dlg_template = MAKEINTRESOURCE(IDD_CFG_ID_TAB);
- reg.dlg_proc = k5_id_tab_dlgproc;
- reg.flags = KHUI_CNFLAG_SUBPANEL | KHUI_CNFLAG_PLURAL;
-
- khui_cfg_register(node, &reg);
-
- khui_cfg_release(node);
-}
-
-void
-k5_unregister_config_panels(void) {
- khui_config_node node_main;
-#ifdef REALM_EDITOR
- khui_config_node node_realms;
-#endif
- khui_config_node node_ids;
- khui_config_node node_tab;
- khui_config_node node_ccaches;
-
- if (KHM_FAILED(khui_cfg_open(NULL, L"Kerberos5", &node_main))) {
- node_main = NULL;
-#ifdef DEBUG
- assert(FALSE);
-#endif
- }
-
-#ifdef REALM_EDITOR
- if (KHM_SUCCEEDED(khui_cfg_open(node_main, L"KerberosRealms",
- &node_realms))) {
- khui_cfg_remove(node_realms);
- khui_cfg_release(node_realms);
- }
-#ifdef DEBUG
- else
- assert(FALSE);
-#endif
-#endif
-
- if (KHM_SUCCEEDED(khui_cfg_open(node_main, L"KerberosCCaches",
- &node_ccaches))) {
- khui_cfg_remove(node_ccaches);
- khui_cfg_release(node_ccaches);
- }
-#ifdef DEBUG
- else
- assert(FALSE);
-#endif
-
- if (node_main) {
- khui_cfg_remove(node_main);
- khui_cfg_release(node_main);
- }
-
- if (KHM_FAILED(khui_cfg_open(NULL, L"KhmIdentities", &node_ids))) {
- node_ids = NULL;
-#ifdef DEBUG
- assert(FALSE);
-#endif
- }
-
- if (KHM_SUCCEEDED(khui_cfg_open(node_ids, L"KerberosIdentities", &node_tab))) {
- khui_cfg_remove(node_tab);
- khui_cfg_release(node_tab);
- }
- if (KHM_SUCCEEDED(khui_cfg_open(node_ids, L"KerberosIdentitiesPlural", &node_tab))) {
- khui_cfg_remove(node_tab);
- khui_cfg_release(node_tab);
- }
-
- if (node_ids)
- khui_cfg_release(node_ids);
-}
+/*
+ * 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>
+
+#pragma warning(push)
+#pragma warning(disable: 4995)
+#include<shlwapi.h>
+#pragma warning(pop)
+
+
+typedef struct tag_k5_realm_kdc {
+ wchar_t name[K5_MAXCCH_HOST];
+ khm_boolean admin; /* admin server? */
+ khm_boolean master; /* master kdc? */
+ khm_int32 flags;
+} k5_realm_kdc;
+
+#define K5_RKFLAG_DELETED 1
+#define K5_RKFLAG_NEW 2
+#define K5_RKFLAG_MOD_ADMIN 4
+#define K5_RKFLAG_MOD_MASTER 8
+
+typedef struct tag_k5_domain_map {
+ wchar_t name[K5_MAXCCH_HOST]; /* name of host that maps to a
+ realm */
+ khm_int32 flags;
+} k5_domain_map;
+
+#define K5_DMFLAG_DELETED 1
+#define K5_DMFLAG_NEW 2
+
+typedef struct tag_k5_realm_data {
+ wchar_t realm[K5_MAXCCH_REALM];
+ k5_realm_kdc kdcs[K5_MAX_KDC];
+ khm_size n_kdcs;
+ k5_domain_map domain_maps[K5_MAX_DOMAIN_MAPPINGS];
+ khm_size n_domain_maps;
+
+ khm_int32 flags;
+} k5_realm_data;
+
+#define K5_RDFLAG_DELETED 1
+#define K5_RDFLAG_NEW 2
+#define K5_RDFLAG_MODIFED 4
+
+#define K5_REALMS_ALLOC_INCR 8
+
+typedef struct tag_k5_config_data {
+ wchar_t def_realm[K5_MAXCCH_REALM]; /* default realm */
+
+ wchar_t config_file[MAX_PATH]; /* path to configuration file */
+ khm_boolean create_config_file; /* create config_file if missing? */
+ khm_boolean inc_realms; /* include full realm list in new
+ credentials dialog? */
+
+ /* [libdefaults] */
+ khm_boolean dns_lookup_kdc;
+ khm_boolean dns_lookup_realm;
+ khm_boolean dns_fallback;
+
+ khm_boolean noaddresses;
+
+ k5_lsa_import lsa_import; /* import mslsa creds? */
+
+ /* [realms] */
+ k5_realm_data *realms;
+ khm_size n_realms;
+ khm_size nc_realms;
+ khm_size c_realm;
+
+ khui_config_node node_main;
+ khui_config_node node_realm;
+
+ khm_int32 flags;
+
+ /* used by the realm editor */
+ HMENU hm_realms_ctx;
+ HMENU hm_kdc_ctx;
+ HMENU hm_dmap_ctx;
+} k5_config_data;
+
+#define K5_CDFLAG_MOD_DEF_REALM 0x00000001
+#define K5_CDFLAG_MOD_CONF_FILE 0x00000002
+#define K5_CDFLAG_MOD_DNS_LOOKUP_KDC 0x00000004
+#define K5_CDFLAG_MOD_DNS_LOOKUP_RLM 0x00000008
+#define K5_CDFLAG_MOD_DNS_FALLBACK 0x00000010
+#define K5_CDFLAG_MOD_NOADDRESSES 0x00000020
+#define K5_CDFLAG_MOD_LSA_IMPORT 0x00000040
+#define K5_CDFLAG_MOD_CREATE_CONF 0x00000080
+#define K5_CDFLAG_MOD_INC_REALMS 0x00000100
+#define K5_CDFLAG_MOD_REALMS 0x00001000
+
+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
+k5_parse_boolean(const char *s)
+{
+ const char *const *p;
+
+ for(p=conf_yes; *p; p++) {
+ if (!stricmp(*p,s))
+ return 1;
+ }
+
+ for(p=conf_no; *p; p++) {
+ if (!stricmp(*p,s))
+ return 0;
+ }
+
+ /* Default to "no" */
+ return 0;
+}
+
+void
+k5_init_config_data(k5_config_data * d) {
+ ZeroMemory(d, sizeof(*d));
+}
+
+void
+k5_free_config_data(k5_config_data * d) {
+ if (d->realms)
+ PFREE(d->realms);
+
+ k5_init_config_data(d);
+}
+
+static void
+k5_assert_n_realms(k5_config_data * d, khm_size n) {
+ khm_size nc_realms;
+
+ if (n <= d->nc_realms)
+ return;
+
+ nc_realms = UBOUNDSS(n, K5_REALMS_ALLOC_INCR, K5_REALMS_ALLOC_INCR);
+ assert(nc_realms > d->nc_realms);
+
+ d->realms = PREALLOC(d->realms, nc_realms * sizeof(*(d->realms)));
+ d->nc_realms = nc_realms;
+
+ ZeroMemory(&d->realms[d->n_realms],
+ (d->nc_realms - d->n_realms) * sizeof(*(d->realms)));
+}
+
+void
+k5_purge_config_data(k5_config_data * d,
+ khm_boolean purge_realms,
+ khm_boolean purge_kdcs,
+ khm_boolean purge_dmap) {
+ khm_size r;
+ khm_size k;
+ khm_size m;
+
+ for (r=0; r < d->n_realms; r++) {
+ if (purge_realms &&
+ (d->realms[r].flags & K5_RDFLAG_NEW) &&
+ (d->realms[r].flags & K5_RDFLAG_DELETED)) {
+
+ if (d->n_realms > r+1)
+ MoveMemory(&d->realms[r], &d->realms[r+1],
+ sizeof(d->realms[0]) * (d->n_realms - (r+1)));
+ r--;
+ d->n_realms--;
+ continue;
+ }
+
+ for (k=0; k < d->realms[r].n_kdcs; k++) {
+ if (purge_kdcs &&
+ (d->realms[r].kdcs[k].flags & K5_RKFLAG_NEW) &&
+ (d->realms[r].kdcs[k].flags & K5_RKFLAG_DELETED)) {
+ if (d->realms[r].n_kdcs > k + 1)
+ MoveMemory(&d->realms[r].kdcs[k],
+ &d->realms[r].kdcs[k+1],
+ sizeof(d->realms[0].kdcs[0]) *
+ (d->realms[r].n_kdcs - (k+1)));
+ k--;
+ d->realms[r].n_kdcs--;
+ continue;
+ }
+ }
+
+ if (K5_MAX_KDC > k+1)
+ ZeroMemory(&d->realms[r].kdcs[k],
+ sizeof(d->realms[0].kdcs[0]) *
+ (K5_MAX_KDC - (k + 1)));
+
+ for (m=0; m < d->realms[r].n_domain_maps; m++) {
+ if (purge_dmap &&
+ (d->realms[r].domain_maps[m].flags & K5_DMFLAG_NEW) &&
+ (d->realms[r].domain_maps[m].flags & K5_DMFLAG_DELETED)) {
+ if (d->realms[r].n_domain_maps > m + 1)
+ MoveMemory(&d->realms[r].domain_maps[m],
+ &d->realms[r].domain_maps[m+1],
+ sizeof(d->realms[0].domain_maps[0]) *
+ (d->realms[r].n_domain_maps - (m+1)));
+ m--;
+ d->realms[r].n_domain_maps--;
+ continue;
+ }
+ }
+
+ if (K5_MAX_DOMAIN_MAPPINGS > m+1)
+ ZeroMemory(&d->realms[r].domain_maps[m],
+ sizeof(d->realms[0].domain_maps[0]) *
+ (K5_MAX_DOMAIN_MAPPINGS - (m+1)));
+ }
+
+ if (d->nc_realms > r + 1)
+ ZeroMemory(&d->realms[r],
+ sizeof(d->realms[0]) *
+ (d->nc_realms - (r + 1)));
+}
+
+static khm_boolean
+k5_is_profile_loaded(void) {
+#ifdef DEBUG
+ assert(pprofile_init);
+ assert(pprofile_get_subsection_names);
+ assert(pprofile_get_values);
+ assert(pprofile_get_string);
+ assert(pprofile_get_relation_names);
+ assert(pprofile_free_list);
+ assert(pprofile_release_string);
+ assert(pprofile_release);
+ assert(pprofile_clear_relation);
+ assert(pprofile_add_relation);
+ assert(pprofile_update_relation);
+ assert(pprofile_flush);
+#endif
+
+ if (!pprofile_init ||
+ !pprofile_get_subsection_names ||
+ !pprofile_get_values ||
+ !pprofile_get_string ||
+ !pprofile_get_relation_names ||
+ !pprofile_free_list ||
+ !pprofile_release_string ||
+ !pprofile_release ||
+ !pprofile_clear_relation ||
+ !pprofile_add_relation ||
+ !pprofile_update_relation ||
+ !pprofile_flush)
+
+ return FALSE;
+
+ return TRUE;
+}
+
+void
+k5_read_config_data(k5_config_data * d) {
+ wchar_t * defrealm;
+ char config_file[MAX_PATH];
+ profile_t profile = NULL;
+ const char *filenames[2];
+ long rv;
+ khm_size s;
+
+ if (!k5_is_profile_loaded())
+ return;
+
+ defrealm = khm_krb5_get_default_realm();
+
+ if (defrealm) {
+ StringCbCopy(d->def_realm, sizeof(d->def_realm), defrealm);
+ PFREE(defrealm);
+ } else {
+ StringCbCopy(d->def_realm, sizeof(d->def_realm), L"");
+ }
+
+ khm_krb5_get_profile_file(config_file, ARRAYLENGTH(config_file));
+
+ AnsiStrToUnicode(d->config_file, sizeof(d->config_file), config_file);
+
+ filenames[0] = config_file;
+ filenames[1] = NULL;
+
+ rv = pprofile_init(filenames, &profile);
+
+ if (!rv) {
+ const char * sec_realms[] = { "realms", NULL };
+ const char * sec_domain_realm[] = { "domain_realm", NULL };
+ char ** sections;
+ char ** dr_from;
+ char * boolv;
+
+ /* first fish out a few values from [libdefaults] */
+
+ rv = pprofile_get_string(profile, "libdefaults", "dns_lookup_kdc",
+ NULL, NULL, &boolv);
+ if (!rv && boolv) {
+ d->dns_lookup_kdc = k5_parse_boolean(boolv);
+ pprofile_release_string(boolv);
+ } else
+ d->dns_lookup_kdc = FALSE;
+
+ rv = pprofile_get_string(profile, "libdefaults", "dns_lookup_realm",
+ NULL, NULL, &boolv);
+ if (!rv && boolv) {
+ d->dns_lookup_realm = k5_parse_boolean(boolv);
+ pprofile_release_string(boolv);
+ } else
+ d->dns_lookup_realm = FALSE;
+
+ rv = pprofile_get_string(profile, "libdefaults", "dns_fallback",
+ NULL, NULL, &boolv);
+ if (!rv && boolv) {
+ d->dns_fallback = k5_parse_boolean(boolv);
+ pprofile_release_string(boolv);
+ } else
+ d->dns_fallback = FALSE;
+
+ rv = pprofile_get_string(profile, "libdefaults", "noaddresses",
+ NULL, NULL, &boolv);
+ if (!rv && boolv) {
+ d->noaddresses = k5_parse_boolean(boolv);
+ pprofile_release_string(boolv);
+ } else
+ d->noaddresses = TRUE;
+
+ /* now we look at the [realms] section */
+ rv = pprofile_get_subsection_names(profile, sec_realms, &sections);
+
+ /* what? no realms? whatever */
+ if (rv) goto _skip_realms;
+
+ /* get a count first */
+ for (s=0; sections[s] && sections[s][0]; s++);
+
+ k5_assert_n_realms(d, s);
+ d->n_realms = s;
+
+ /* now go through each and fish out the kdcs, admin_server
+ and master_kdc. */
+ for (s=0; sections[s] && sections[s][0]; s++) {
+ const char * sec_kdcs[] =
+ { "realms", sections[s], "kdc", NULL };
+
+ const char * sec_admin[] =
+ { "realms", sections[s], "admin_server", NULL };
+
+ const char * sec_master[] =
+ { "realms", sections[s], "master_kdc", NULL };
+
+ char ** values;
+
+ AnsiStrToUnicode(d->realms[s].realm, sizeof(d->realms[s].realm),
+ sections[s]);
+ d->realms[s].n_kdcs = 0;
+ d->realms[s].n_domain_maps = 0;
+
+ rv = pprofile_get_values(profile, sec_kdcs, &values);
+ if (!rv) {
+ khm_size i;
+
+ for (i=0 ; values[i] && values[i][0] && i < K5_MAX_KDC; i++) {
+ AnsiStrToUnicode(d->realms[s].kdcs[i].name,
+ sizeof(d->realms[s].kdcs[i].name),
+ values[i]);
+
+ }
+ d->realms[s].n_kdcs = i;
+
+ pprofile_free_list(values);
+ }
+
+ rv = pprofile_get_values(profile, sec_admin, &values);
+ if (!rv) {
+ khm_size i;
+ khm_size j;
+ wchar_t kdc_name[K5_MAXCCH_HOST];
+
+ for (i=0; values[i] && values[i][0]; i++) {
+ AnsiStrToUnicode(kdc_name,
+ sizeof(kdc_name), values[i]);
+
+ for (j=0; j < d->realms[s].n_kdcs; j++)
+ if (!wcsicmp(kdc_name, d->realms[s].kdcs[j].name))
+ break;
+
+ if (j < d->realms[s].n_kdcs) {
+ d->realms[s].kdcs[j].admin = TRUE;
+ } else if (d->realms[s].n_kdcs < K5_MAX_KDC) {
+ j = d->realms[s].n_kdcs;
+ StringCbCopy(d->realms[s].kdcs[j].name,
+ sizeof(d->realms[s].kdcs[j].name),
+ kdc_name);
+ d->realms[s].kdcs[j].admin = TRUE;
+ d->realms[s].n_kdcs ++;
+ }
+ }
+ pprofile_free_list(values);
+ }
+
+ rv = pprofile_get_values(profile, sec_master, &values);
+ if (!rv) {
+ khm_size i;
+ khm_size j;
+ wchar_t kdc_name[K5_MAXCCH_HOST];
+
+ for (i=0; values[i] && values[i][0]; i++) {
+ AnsiStrToUnicode(kdc_name, sizeof(kdc_name), values[i]);
+
+ for (j=0; j < d->realms[s].n_kdcs; j++)
+ if (!wcsicmp(kdc_name, d->realms[s].kdcs[j].name))
+ break;
+
+ if (j < d->realms[s].n_kdcs) {
+ d->realms[s].kdcs[j].master = TRUE;
+ } else if (d->realms[s].n_kdcs < K5_MAX_KDC) {
+ j = d->realms[s].n_kdcs;
+ StringCbCopy(d->realms[s].kdcs[j].name,
+ sizeof(d->realms[s].kdcs[j].name),
+ kdc_name);
+ d->realms[s].kdcs[j].master = TRUE;
+ d->realms[s].n_kdcs ++;
+ }
+ }
+
+ pprofile_free_list(values);
+ }
+ }
+ pprofile_free_list(sections);
+
+ _skip_realms:
+
+ rv = pprofile_get_relation_names(profile, sec_domain_realm, &dr_from);
+ if (!rv) {
+ khm_size i;
+ khm_size j;
+ char * dr_to;
+ wchar_t wdr_from[K5_MAXCCH_HOST];
+ wchar_t wdr_to[K5_MAXCCH_HOST];
+
+ for (i=0; dr_from[i] && dr_from[i][0]; i++) {
+ AnsiStrToUnicode(wdr_from, sizeof(wdr_from), dr_from[i]);
+
+ rv = pprofile_get_string(profile, "domain_realm", dr_from[i],
+ NULL, NULL, &dr_to);
+
+ if (rv || !dr_to)
+ continue;
+
+ AnsiStrToUnicode(wdr_to, sizeof(wdr_to), dr_to);
+
+ for (j=0; j < d->n_realms; j++) {
+ if (!wcsicmp(wdr_to, d->realms[j].realm))
+ break;
+ }
+
+ if (j >= d->n_realms) {
+ j = d->n_realms;
+ k5_assert_n_realms(d, j + 1);
+
+ StringCbCopy(d->realms[j].realm,
+ sizeof(d->realms[j].realm),
+ wdr_to);
+ d->realms[j].n_kdcs = 0;
+ d->realms[j].n_domain_maps = 0;
+
+ d->n_realms++;
+ }
+
+ if (d->realms[j].n_domain_maps < K5_MAX_DOMAIN_MAPPINGS) {
+ khm_size k;
+
+ k = d->realms[j].n_domain_maps;
+
+ StringCbCopy(d->realms[j].domain_maps[k].name,
+ sizeof(d->realms[j].domain_maps[k].name),
+ wdr_from);
+
+ d->realms[j].n_domain_maps++;
+ }
+
+ pprofile_release_string(dr_to);
+ }
+ pprofile_free_list(dr_from);
+ }
+ pprofile_release(profile);
+ }
+
+ {
+ khm_int32 t;
+
+ /* last, read the MSLSA import setting */
+ if (KHM_SUCCEEDED(khc_read_int32(csp_params,
+ L"MsLsaImport", &t))) {
+ d->lsa_import = t;
+ } else {
+ d->lsa_import = K5_LSAIMPORT_ALWAYS;
+ }
+
+ if (KHM_SUCCEEDED(khc_read_int32(csp_params,
+ L"UseFullRealmList", &t))) {
+ d->inc_realms = !!t;
+ } else {
+ d->inc_realms = TRUE;
+ }
+ }
+
+ d->flags = 0;
+}
+
+void
+k5_write_config_data(k5_config_data * d) {
+ char astr[MAX_PATH * 2];
+ char config_file[MAX_PATH];
+ profile_t profile = NULL;
+ const char *filenames[2];
+ long rv;
+ khm_size s;
+
+ if (d->flags == 0)
+ return;
+
+ if (!k5_is_profile_loaded())
+ return;
+
+ if (d->flags & K5_CDFLAG_MOD_DEF_REALM) {
+ if (SUCCEEDED(StringCbLength(d->def_realm,
+ sizeof(d->def_realm), &s)) &&
+ s > 0) {
+ khm_krb5_set_default_realm(d->def_realm);
+ }
+ d->flags &= ~K5_CDFLAG_MOD_DEF_REALM;
+ }
+
+ /* write the MSLSA import setting */
+ if (d->flags & K5_CDFLAG_MOD_LSA_IMPORT) {
+ khc_write_int32(csp_params, L"MsLsaImport", d->lsa_import);
+ d->flags &= ~K5_CDFLAG_MOD_LSA_IMPORT;
+ }
+
+ if (d->flags & K5_CDFLAG_MOD_INC_REALMS) {
+ khc_write_int32(csp_params, L"UseFullRealmList", d->inc_realms);
+ d->flags &= ~K5_CDFLAG_MOD_INC_REALMS;
+ }
+
+ if (!(d->flags &
+ (K5_CDFLAG_MOD_CONF_FILE |
+ K5_CDFLAG_MOD_DNS_FALLBACK |
+ K5_CDFLAG_MOD_DNS_LOOKUP_RLM |
+ K5_CDFLAG_MOD_DNS_LOOKUP_KDC |
+ K5_CDFLAG_MOD_NOADDRESSES |
+ K5_CDFLAG_MOD_CREATE_CONF |
+ K5_CDFLAG_MOD_REALMS))) {
+
+ d->flags = 0;
+ return;
+ }
+
+ khm_krb5_get_profile_file(config_file, ARRAYLENGTH(config_file));
+
+ UnicodeStrToAnsi(astr, sizeof(astr), d->config_file);
+
+ if (stricmp(config_file, astr)) {
+ assert(FALSE);
+ }
+
+ filenames[0] = config_file;
+ filenames[1] = NULL;
+
+ rv = pprofile_init(filenames, &profile);
+
+#if FAILOVER_TO_TEMPORARY_FILE
+ if (rv) {
+ char temp_file[MAX_PATH];
+
+ khm_krb5_get_temp_profile_file(temp_file,
+ ARRAYLENGTH(temp_file));
+
+ filenames[0] = temp_file;
+
+ rv = pprofile_init(filenames, &profile);
+
+ ?? TODO: Also warn if we are doing this
+ }
+#endif
+
+ if (!rv) {
+ const char * sec_realms[] = { "realms", NULL };
+ const char * sec_domain_realm[] = { "domain_realm", NULL };
+ const char * sec_libdefaults[] = { "libdefaults", NULL, NULL };
+ khm_size r;
+
+ if (d->flags & K5_CDFLAG_MOD_DNS_LOOKUP_KDC) {
+
+ sec_libdefaults[1] = "dns_lookup_kdc";
+
+ pprofile_clear_relation(profile, sec_libdefaults);
+
+ rv = pprofile_add_relation(profile, sec_libdefaults,
+ (d->dns_lookup_kdc)?
+ conf_yes[0]:
+ conf_no[0]);
+ d->flags &= ~K5_CDFLAG_MOD_DNS_LOOKUP_KDC;
+ }
+
+
+ if (d->flags & K5_CDFLAG_MOD_DNS_LOOKUP_RLM) {
+
+ sec_libdefaults[1] = "dns_lookup_realm";
+
+ pprofile_clear_relation(profile, sec_libdefaults);
+
+ rv = pprofile_add_relation(profile, sec_libdefaults,
+ (d->dns_lookup_realm)?
+ conf_yes[0]:
+ conf_no[0]);
+
+ d->flags &= ~K5_CDFLAG_MOD_DNS_LOOKUP_RLM;
+ }
+
+ if (d->flags & K5_CDFLAG_MOD_DNS_FALLBACK) {
+
+ sec_libdefaults[1] = "dns_fallback";
+
+ pprofile_clear_relation(profile, sec_libdefaults);
+
+ rv = pprofile_add_relation(profile, sec_libdefaults,
+ (d->dns_fallback)?
+ conf_yes[0]:
+ conf_no[0]);
+
+ d->flags &= ~K5_CDFLAG_MOD_DNS_FALLBACK;
+ }
+
+ if (d->flags & K5_CDFLAG_MOD_NOADDRESSES) {
+
+ sec_libdefaults[1] = "noaddresses";
+
+ pprofile_clear_relation(profile, sec_libdefaults);
+
+ rv = pprofile_add_relation(profile, sec_libdefaults,
+ (d->noaddresses)?
+ conf_yes[0]:
+ conf_no[0]);
+
+ d->flags &= ~K5_CDFLAG_MOD_NOADDRESSES;
+ }
+
+ /* now we look at the [realms] section */
+
+ for (r=0; r < d->n_realms; r++) {
+ char realm[K5_MAXCCH_REALM];
+ char host[K5_MAXCCH_HOST];
+
+ const char * sec_kdcs[] =
+ { "realms", realm, "kdc", NULL };
+
+ const char * sec_admin[] =
+ { "realms", realm, "admin_server", NULL };
+
+ const char * sec_master[] =
+ { "realms", realm, "master_kdc", NULL };
+
+ const char * sec_domain_map[] =
+ { "domain_realm", host, NULL };
+
+ char ** values;
+
+ UnicodeStrToAnsi(realm, sizeof(realm),
+ d->realms[r].realm);
+
+ if (!(d->realms[r].flags & K5_RDFLAG_DELETED) &&
+ (d->realms[r].flags & K5_RDFLAG_NEW)) {
+
+ khm_size k;
+ khm_size m;
+
+ /* this is a new realm */
+
+ for (k=0; k < d->realms[r].n_kdcs; k++) {
+ if (!(d->realms[r].kdcs[k].flags & K5_RKFLAG_DELETED)) {
+ UnicodeStrToAnsi(host, sizeof(host),
+ d->realms[r].kdcs[k].name);
+
+ if (d->realms[r].kdcs[k].master)
+ pprofile_add_relation(profile, sec_master,
+ host);
+ else
+ pprofile_add_relation(profile, sec_kdcs,
+ host);
+
+ if (d->realms[r].kdcs[k].admin)
+ pprofile_add_relation(profile, sec_admin,
+ host);
+
+ d->realms[r].kdcs[k].flags &= ~K5_RKFLAG_NEW;
+ }
+ }
+
+ for (m=0; m < d->realms[r].n_domain_maps; m++) {
+
+ UnicodeStrToAnsi(host, sizeof(host),
+ d->realms[r].domain_maps[m].name);
+
+ if ((d->realms[r].domain_maps[m].flags &
+ K5_DMFLAG_DELETED) &&
+ !(d->realms[r].domain_maps[m].flags &
+ K5_DMFLAG_NEW)) {
+ pprofile_clear_relation(profile, sec_domain_map);
+
+ /* setting this flag indicates that the item
+ is deleted and not in the profile file
+ anymore. */
+ d->realms[r].domain_maps[m].flags |= K5_DMFLAG_NEW;
+ } else if (!(d->realms[r].domain_maps[m].flags &
+ K5_DMFLAG_DELETED) &&
+ (d->realms[r].domain_maps[m].flags &
+ K5_DMFLAG_NEW)) {
+ pprofile_add_relation(profile, sec_domain_map,
+ realm);
+
+ d->realms[r].domain_maps[m].flags &= ~K5_DMFLAG_NEW;
+ }
+ }
+
+ d->realms[r].flags &= ~K5_RDFLAG_NEW;
+
+ } else if ((d->realms[r].flags & K5_RDFLAG_DELETED) &&
+ !(d->realms[r].flags & K5_RDFLAG_NEW)) {
+
+ const char * sec_all[] =
+ { "realms", realm, NULL, NULL };
+ khm_size v;
+
+ /* this realm should be deleted */
+
+ rv = pprofile_get_relation_names(profile, sec_all,
+ &values);
+ if (!rv) {
+ for (v=0; values[v] && values[v][0]; v++) {
+ sec_all[2] = values[v];
+ pprofile_clear_relation(profile, sec_all);
+ }
+ pprofile_free_list(values);
+ }
+
+ rv = pprofile_get_relation_names(profile, sec_domain_realm,
+ &values);
+ if (!rv) {
+ char * maprealm;
+
+ for (v=0; values[v] && values[v][0]; v++) {
+
+ rv = pprofile_get_string(profile, "domain_realm",
+ values[v], NULL, NULL,
+ &maprealm);
+
+ if (!rv) {
+ if (!strcmp(maprealm, realm)) {
+ StringCbCopyA(host, sizeof(host),
+ values[v]);
+ pprofile_clear_relation(profile,
+ sec_domain_map);
+ }
+ pprofile_release_string(maprealm);
+ }
+ }
+
+ pprofile_free_list(values);
+ }
+
+ /* setting this flag indicate that the realm is
+ deleted and is not in the profile file. */
+ d->realms[r].flags |= K5_RDFLAG_NEW;
+
+ } else if (!(d->realms[r].flags & K5_RDFLAG_DELETED)) {
+ khm_size k;
+ khm_size m;
+
+ /* same as before. check if we have to update the kdc
+ list or the domain_realm mappings */
+
+ for (k=0; k < d->realms[r].n_kdcs; k++) {
+
+ if ((d->realms[r].kdcs[k].flags & K5_RKFLAG_NEW) &&
+ (d->realms[r].kdcs[k].flags & K5_RKFLAG_DELETED))
+ continue;
+
+ UnicodeStrToAnsi(host, sizeof(host),
+ d->realms[r].kdcs[k].name);
+
+ if (d->realms[r].kdcs[k].flags & K5_RKFLAG_DELETED) {
+ pprofile_update_relation(profile, sec_kdcs,
+ host, NULL);
+ pprofile_update_relation(profile, sec_admin,
+ host, NULL);
+ pprofile_update_relation(profile, sec_master,
+ host, NULL);
+
+ /* as above, setting 'new' flag to indicate
+ that the item does not exist in the profile
+ file. */
+ d->realms[r].kdcs[k].flags |= K5_RKFLAG_NEW;
+ continue;
+ }
+
+ if (d->realms[r].kdcs[k].flags & K5_RKFLAG_NEW) {
+ if (d->realms[r].kdcs[k].master)
+ pprofile_add_relation(profile, sec_master,
+ host);
+ else
+ pprofile_add_relation(profile, sec_kdcs,
+ host);
+
+ if (d->realms[r].kdcs[k].admin)
+ pprofile_add_relation(profile, sec_admin,
+ host);
+
+ d->realms[r].kdcs[k].flags &= ~K5_RKFLAG_NEW;
+ continue;
+ }
+
+ if (d->realms[r].kdcs[k].flags & K5_RKFLAG_MOD_MASTER) {
+ if (!d->realms[r].kdcs[k].master) {
+ pprofile_update_relation(profile, sec_kdcs,
+ host, NULL);
+ pprofile_add_relation(profile, sec_kdcs,
+ host);
+ pprofile_update_relation(profile, sec_master,
+ host, NULL);
+ } else {
+ pprofile_update_relation(profile, sec_master,
+ host, NULL);
+ pprofile_add_relation(profile, sec_master,
+ host);
+ pprofile_update_relation(profile, sec_kdcs,
+ host, NULL);
+ }
+
+ d->realms[r].kdcs[k].flags &= ~K5_RKFLAG_MOD_MASTER;
+ }
+
+ if (d->realms[r].kdcs[k].flags & K5_RKFLAG_MOD_ADMIN) {
+ if (d->realms[r].kdcs[k].admin) {
+ pprofile_update_relation(profile, sec_admin,
+ host, NULL);
+ pprofile_add_relation(profile, sec_admin,
+ host);
+ } else {
+ pprofile_update_relation(profile, sec_admin,
+ host, NULL);
+ }
+
+ d->realms[r].kdcs[k].flags &= ~K5_RKFLAG_MOD_ADMIN;
+ }
+ }
+
+ for (m=0; m < d->realms[r].n_domain_maps; m++) {
+
+ UnicodeStrToAnsi(host, sizeof(host),
+ d->realms[r].domain_maps[m].name);
+
+ if ((d->realms[r].domain_maps[m].flags &
+ K5_DMFLAG_DELETED) &&
+
+ !(d->realms[r].domain_maps[m].flags &
+ K5_DMFLAG_NEW)) {
+
+ pprofile_clear_relation(profile, sec_domain_map);
+ d->realms[r].domain_maps[m].flags |= K5_DMFLAG_NEW;
+
+ } else if (!(d->realms[r].domain_maps[m].flags &
+ K5_DMFLAG_DELETED) &&
+
+ (d->realms[r].domain_maps[m].flags &
+ K5_DMFLAG_NEW)) {
+
+ pprofile_add_relation(profile, sec_domain_map,
+ realm);
+ d->realms[r].domain_maps[m].flags &= ~K5_DMFLAG_NEW;
+ }
+ }
+
+ d->realms[r].flags &= ~K5_RDFLAG_MODIFED;
+ }
+ }
+
+ rv = pprofile_flush(profile);
+
+ pprofile_release(profile);
+ }
+
+ if (rv) {
+ khui_alert * alert;
+ wchar_t title[KHUI_MAXCCH_TITLE];
+ wchar_t fmsg[KHUI_MAXCCH_MESSAGE];
+ wchar_t msg[KHUI_MAXCCH_MESSAGE];
+ wchar_t sugg[KHUI_MAXCCH_SUGGESTION];
+
+ LoadString(hResModule, IDS_K5ERR_CANTWRITEPROFILE,
+ title, ARRAYLENGTH(title));
+ if (rv)
+ LoadString(hResModule, IDS_K5ERR_PROFNOWRITE,
+ fmsg, ARRAYLENGTH(fmsg));
+
+ LoadString(hResModule, IDS_K5ERR_PROFSUGGEST,
+ sugg, ARRAYLENGTH(sugg));
+
+ StringCbPrintf(msg, sizeof(msg), fmsg, config_file);
+
+ khui_alert_create_empty(&alert);
+ khui_alert_set_severity(alert, (rv)?KHERR_ERROR:KHERR_WARNING);
+ khui_alert_set_title(alert, title);
+ khui_alert_set_message(alert, msg);
+ khui_alert_set_suggestion(alert, sugg);
+
+ khui_alert_show(alert);
+ }
+
+ d->flags = 0;
+}
+
+/* actual dialog stuff */
+
+#define IDX_NORMAL 1
+#define IDX_MODIFIED 2
+#define IDX_NEW 3
+#define IDX_DELETED 4
+
+static k5_config_data k5_config_dlg_data;
+static khm_boolean k5_dlg_data_valid = FALSE;
+
+INT_PTR CALLBACK
+k5_config_dlgproc(HWND hwnd,
+ UINT uMsg,
+ WPARAM wParam,
+ LPARAM lParam) {
+ switch(uMsg) {
+ case WM_INITDIALOG:
+ {
+ HWND hw;
+ khm_size i;
+ k5_config_data * d;
+
+ wchar_t * t;
+ wchar_t importopts[256];
+ WKSTA_INFO_100 * winfo100;
+
+#ifdef DEBUG
+ assert(!k5_dlg_data_valid);
+#endif
+
+ k5_init_config_data(&k5_config_dlg_data);
+ k5_read_config_data(&k5_config_dlg_data);
+
+ k5_dlg_data_valid = TRUE;
+
+ d = &k5_config_dlg_data;
+
+ d->node_main = (khui_config_node) lParam;
+
+ CheckDlgButton(hwnd, IDC_CFG_INCREALMS,
+ (d->inc_realms)? BST_CHECKED: BST_UNCHECKED);
+
+ hw = GetDlgItem(hwnd, IDC_CFG_DEFREALM);
+#ifdef DEBUG
+ assert(hw);
+#endif
+
+ SendMessage(hw, CB_RESETCONTENT, 0, 0);
+
+ for (i=0; i < d->n_realms; i++) {
+ SendMessage(hw, CB_ADDSTRING, 0,
+ (LPARAM) d->realms[i].realm);
+ }
+
+ SendMessage(hw, CB_SELECTSTRING, -1,
+ (LPARAM) d->def_realm);
+
+ SetDlgItemText(hwnd, IDC_CFG_CFGFILE, d->config_file);
+
+ /* hostname/domain */
+ if (NetWkstaGetInfo(NULL, 100, (LPBYTE *) &winfo100) == NERR_Success) {
+ SetDlgItemText(hwnd, IDC_CFG_HOSTNAME, winfo100->wki100_computername);
+ SetDlgItemText(hwnd, IDC_CFG_DOMAIN, winfo100->wki100_langroup);
+ NetApiBufferFree(winfo100);
+ }
+
+ /* and the import ticket options */
+ LoadString(hResModule, IDS_K5CFG_IMPORT_OPTIONS,
+ importopts, ARRAYLENGTH(importopts));
+
+ hw = GetDlgItem(hwnd, IDC_CFG_IMPORT);
+#ifdef DEBUG
+ assert(hw);
+#endif
+ SendMessage(hw, CB_RESETCONTENT, 0, 0);
+
+ for (t=importopts;
+ t && *t && *t != L' ' &&
+ t < importopts + ARRAYLENGTH(importopts);
+ t = multi_string_next(t)) {
+
+ SendMessage(hw, CB_ADDSTRING, 0, (LPARAM) t);
+ }
+
+ SendMessage(hw, CB_SETCURSEL, 0, d->lsa_import);
+ t = importopts;
+ SendMessage(hw, CB_GETLBTEXT, d->lsa_import,(LPARAM) t);
+ SendMessage(hw, CB_SELECTSTRING, -1, (LPARAM) t);
+ }
+ break;
+
+ case WM_COMMAND:
+ {
+ k5_config_data * d;
+
+ d = &k5_config_dlg_data;
+
+ if (wParam == MAKEWPARAM(IDC_CFG_IMPORT, CBN_SELCHANGE)) {
+ int idx;
+ int modified = FALSE;
+
+ idx = (int) SendDlgItemMessage(hwnd, IDC_CFG_IMPORT,
+ CB_GETCURSEL, 0, 0);
+ if (idx != CB_ERR && idx != d->lsa_import) {
+ d->lsa_import = idx;
+ d->flags |= K5_CDFLAG_MOD_LSA_IMPORT;
+ modified = TRUE;
+ }
+
+ khui_cfg_set_flags(d->node_main,
+ (modified)?KHUI_CNFLAG_MODIFIED:0,
+ KHUI_CNFLAG_MODIFIED);
+ return TRUE;
+ }
+
+ if (wParam == MAKEWPARAM(IDC_CFG_INCREALMS, BN_CLICKED)) {
+ if (IsDlgButtonChecked(hwnd, IDC_CFG_INCREALMS) ==
+ BST_CHECKED) {
+ d->inc_realms = TRUE;
+ } else {
+ d->inc_realms = FALSE;
+ }
+ d->flags |= K5_CDFLAG_MOD_INC_REALMS;
+
+ khui_cfg_set_flags(d->node_main,
+ KHUI_CNFLAG_MODIFIED,
+ KHUI_CNFLAG_MODIFIED);
+ return TRUE;
+ }
+ }
+ break;
+
+ case KHUI_WM_CFG_NOTIFY:
+ {
+ k5_config_data * d;
+
+ d = &k5_config_dlg_data;
+
+ if (HIWORD(wParam) == WMCFG_APPLY) {
+ khm_int32 oflags;
+
+ oflags = d->flags;
+ k5_write_config_data(d);
+
+ if (d->flags != oflags) {
+ khui_cfg_set_flags(d->node_main,
+ KHUI_CNFLAG_APPLIED,
+ KHUI_CNFLAG_APPLIED |
+ KHUI_CNFLAG_MODIFIED);
+ }
+ return TRUE;
+ }
+ }
+ break;
+
+ case WM_DESTROY:
+ {
+ k5_free_config_data(&k5_config_dlg_data);
+ k5_dlg_data_valid = FALSE;
+ }
+ break;
+ }
+ return FALSE;
+}
+
+static HIMAGELIST
+k5_get_state_image_list(void) {
+ HIMAGELIST hil;
+ HICON hicon;
+
+ hil = ImageList_Create(GetSystemMetrics(SM_CXSMICON),
+ GetSystemMetrics(SM_CYSMICON),
+ ILC_COLOR | ILC_MASK,
+ 4,
+ 2);
+
+ hicon = LoadImage(hResModule,
+ MAKEINTRESOURCE(IDI_NORMAL),
+ IMAGE_ICON,
+ GetSystemMetrics(SM_CXSMICON),
+ GetSystemMetrics(SM_CYSMICON),
+ LR_DEFAULTCOLOR);
+
+ ImageList_AddIcon(hil, hicon);
+
+ DestroyIcon(hicon);
+
+ hicon = LoadImage(hResModule,
+ MAKEINTRESOURCE(IDI_MODIFIED),
+ IMAGE_ICON,
+ GetSystemMetrics(SM_CXSMICON),
+ GetSystemMetrics(SM_CYSMICON),
+ LR_DEFAULTCOLOR);
+
+ ImageList_AddIcon(hil, hicon);
+
+ DestroyIcon(hicon);
+
+ hicon = LoadImage(hResModule,
+ MAKEINTRESOURCE(IDI_NEW),
+ IMAGE_ICON,
+ GetSystemMetrics(SM_CXSMICON),
+ GetSystemMetrics(SM_CYSMICON),
+ LR_DEFAULTCOLOR);
+
+ ImageList_AddIcon(hil, hicon);
+
+ DestroyIcon(hicon);
+
+ hicon = LoadImage(hResModule,
+ MAKEINTRESOURCE(IDI_DELETED),
+ IMAGE_ICON,
+ GetSystemMetrics(SM_CXSMICON),
+ GetSystemMetrics(SM_CYSMICON),
+ LR_DEFAULTCOLOR);
+
+ ImageList_AddIcon(hil, hicon);
+
+ DestroyIcon(hicon);
+
+ return hil;
+}
+
+static void
+k5_update_realms_display(HWND hw_list, k5_config_data * d) {
+ khm_size i;
+ LVITEM lvi;
+ wchar_t buf[64];
+
+ ListView_DeleteAllItems(hw_list);
+
+ for (i=0; i < d->n_realms; i++) {
+ if ((d->realms[i].flags & K5_RDFLAG_DELETED) &&
+ (d->realms[i].flags & K5_RDFLAG_NEW))
+ continue;
+
+ ZeroMemory(&lvi, sizeof(lvi));
+ lvi.mask = LVIF_PARAM | LVIF_STATE | LVIF_TEXT;
+ lvi.iItem = 0;
+ lvi.iSubItem = 0;
+ lvi.pszText = d->realms[i].realm;
+ lvi.lParam = i;
+
+ if (d->realms[i].flags & K5_RDFLAG_DELETED) {
+ lvi.state = INDEXTOSTATEIMAGEMASK(IDX_DELETED);
+ } else if (d->realms[i].flags & K5_RDFLAG_NEW) {
+ lvi.state = INDEXTOSTATEIMAGEMASK(IDX_NEW);
+ } else if (d->realms[i].flags & K5_RDFLAG_MODIFED) {
+ lvi.state = INDEXTOSTATEIMAGEMASK(IDX_MODIFIED);
+ } else {
+ lvi.state = INDEXTOSTATEIMAGEMASK(IDX_NORMAL);
+ }
+ lvi.stateMask = LVIS_STATEIMAGEMASK;
+
+ ListView_InsertItem(hw_list, &lvi);
+ }
+
+ ZeroMemory(&lvi, sizeof(lvi));
+ lvi.mask = LVIF_PARAM | LVIF_STATE | LVIF_TEXT;
+ lvi.iItem = 0;
+ lvi.iSubItem = 0;
+ lvi.pszText = buf;
+ lvi.lParam = (LPARAM) -1;
+
+ LoadString(hResModule, IDS_CFG_RE_NEWREALM,
+ buf, ARRAYLENGTH(buf));
+
+ lvi.state = INDEXTOSTATEIMAGEMASK(IDX_NEW);
+ lvi.stateMask = LVIS_STATEIMAGEMASK;
+
+ ListView_InsertItem(hw_list, &lvi);
+
+ if (d->flags & K5_CDFLAG_MOD_REALMS) {
+ khui_cfg_set_flags(d->node_realm, KHUI_CNFLAG_MODIFIED,
+ KHUI_CNFLAG_MODIFIED);
+ } else {
+ khui_cfg_set_flags(d->node_realm, 0,
+ KHUI_CNFLAG_MODIFIED);
+ }
+}
+
+#define K5_KDCSI_ADMIN 1
+#define K5_KDCSI_MASTER 2
+
+static void
+k5_update_kdcs_display(HWND hw_kdc, k5_config_data * d, khm_size idx_rlm) {
+ khm_size k;
+ LVITEM lvi;
+ int idx_item;
+ k5_realm_kdc * pkdc;
+ wchar_t wyes[8];
+ wchar_t wno[8];
+ wchar_t wbuf[64];
+
+ ListView_DeleteAllItems(hw_kdc);
+
+ if (d == NULL)
+ return;
+
+#ifdef DEBUG
+ assert(idx_rlm < d->n_realms);
+#endif
+ LoadString(hResModule, IDS_YES, wyes, ARRAYLENGTH(wyes));
+ LoadString(hResModule, IDS_NO, wno, ARRAYLENGTH(wno));
+
+ for (k=0; k < d->realms[idx_rlm].n_kdcs; k++) {
+ if ((d->realms[idx_rlm].kdcs[k].flags & K5_RKFLAG_DELETED) &&
+ (d->realms[idx_rlm].kdcs[k].flags & K5_RKFLAG_NEW))
+ continue;
+
+ pkdc = &(d->realms[idx_rlm].kdcs[k]);
+
+ ZeroMemory(&lvi, sizeof(lvi));
+ lvi.mask = LVIF_PARAM | LVIF_STATE | LVIF_TEXT;
+ lvi.iItem = K5_MAX_KDC;
+ lvi.iSubItem = 0;
+ lvi.lParam = k;
+ lvi.pszText = pkdc->name;
+ if (pkdc->flags & K5_RKFLAG_DELETED) {
+ lvi.state = INDEXTOSTATEIMAGEMASK(IDX_DELETED);
+ } else if (pkdc->flags & K5_RKFLAG_NEW) {
+ lvi.state = INDEXTOSTATEIMAGEMASK(IDX_NEW);
+ } else if ((pkdc->flags & K5_RKFLAG_MOD_ADMIN) ||
+ (pkdc->flags & K5_RKFLAG_MOD_MASTER)) {
+ lvi.state = INDEXTOSTATEIMAGEMASK(IDX_MODIFIED);
+ } else {
+ lvi.state = INDEXTOSTATEIMAGEMASK(IDX_NORMAL);
+ }
+ lvi.stateMask = LVIS_STATEIMAGEMASK;
+
+ idx_item = ListView_InsertItem(hw_kdc, &lvi);
+
+ lvi.mask = LVIF_TEXT;
+ lvi.iItem = idx_item;
+ lvi.iSubItem = K5_KDCSI_ADMIN;
+ if (pkdc->admin)
+ lvi.pszText = wyes;
+ else
+ lvi.pszText = wno;
+ ListView_SetItem(hw_kdc, &lvi);
+
+ lvi.iSubItem = K5_KDCSI_MASTER;
+ if (pkdc->master)
+ lvi.pszText = wyes;
+ else
+ lvi.pszText = wno;
+ ListView_SetItem(hw_kdc, &lvi);
+ }
+
+ ZeroMemory(&lvi, sizeof(lvi));
+ lvi.mask = LVIF_TEXT | LVIF_PARAM | LVIF_STATE;
+ lvi.iItem = 0;
+ lvi.iSubItem = 0;
+ lvi.pszText = wbuf;
+ lvi.lParam = (LPARAM) -1;
+ lvi.state = INDEXTOSTATEIMAGEMASK(IDX_NEW);
+ lvi.stateMask = LVIS_STATEIMAGEMASK;
+
+ LoadString(hResModule, IDS_CFG_RE_NEWSERVER,
+ wbuf, ARRAYLENGTH(wbuf));
+
+ ListView_InsertItem(hw_kdc, &lvi);
+}
+
+static void
+k5_update_dmap_display(HWND hw_dm, k5_config_data * d, khm_size idx_rlm) {
+ khm_size m;
+ LVITEM lvi;
+ k5_domain_map * map;
+ wchar_t wbuf[64];
+
+ ListView_DeleteAllItems(hw_dm);
+
+ if (d == NULL)
+ return;
+
+#ifdef DEBUG
+ assert(idx_rlm < d->n_realms);
+#endif
+
+ for (m=0; m < d->realms[idx_rlm].n_domain_maps; m++) {
+ map = &(d->realms[idx_rlm].domain_maps[m]);
+
+ if ((map->flags & K5_DMFLAG_NEW) &&
+ (map->flags & K5_DMFLAG_DELETED))
+ continue;
+
+ ZeroMemory(&lvi, sizeof(lvi));
+
+ lvi.mask = LVIF_TEXT | LVIF_STATE | LVIF_PARAM;
+ lvi.pszText = map->name;
+ if (map->flags & K5_DMFLAG_DELETED)
+ lvi.state = INDEXTOSTATEIMAGEMASK(IDX_DELETED);
+ else if (map->flags & K5_DMFLAG_NEW)
+ lvi.state = INDEXTOSTATEIMAGEMASK(IDX_NEW);
+ else
+ lvi.state = INDEXTOSTATEIMAGEMASK(IDX_NORMAL);
+ lvi.stateMask = LVIS_STATEIMAGEMASK;
+ lvi.lParam = m;
+
+ lvi.iItem = K5_MAX_DOMAIN_MAPPINGS;
+ lvi.iSubItem = 0;
+
+ ListView_InsertItem(hw_dm, &lvi);
+ }
+
+ ZeroMemory(&lvi, sizeof(lvi));
+ lvi.mask = LVIF_PARAM | LVIF_TEXT | LVIF_STATE;
+ lvi.pszText = wbuf;
+ lvi.lParam = (LPARAM) -1;
+ lvi.state = INDEXTOSTATEIMAGEMASK(IDX_NEW);
+ lvi.stateMask = LVIS_STATEIMAGEMASK;
+ lvi.iItem = 0;
+ lvi.iSubItem = 0;
+
+ LoadString(hResModule, IDS_CFG_RE_NEWDMAP,
+ wbuf, ARRAYLENGTH(wbuf));
+
+ ListView_InsertItem(hw_dm, &lvi);
+}
+
+#define CMD_BASE 3000
+#define CMD_NEW_REALM (CMD_BASE + 1)
+#define CMD_DEL_REALM (CMD_BASE + 2)
+#define CMD_NEW_SERVER (CMD_BASE + 3)
+#define CMD_DEL_SERVER (CMD_BASE + 4)
+#define CMD_MAKE_ADMIN (CMD_BASE + 5)
+#define CMD_MAKE_MASTER (CMD_BASE + 6)
+#define CMD_NEW_DMAP (CMD_BASE + 7)
+#define CMD_DEL_DMAP (CMD_BASE + 8)
+
+struct k5_menu_def {
+ UINT string;
+ UINT id;
+ UINT type;
+ UINT state;
+};
+
+struct k5_menu_def k5_menu_realms[] = {
+ {IDS_CFG_RE_MNR, CMD_NEW_REALM, MFT_STRING, 0},
+ {IDS_CFG_RE_MDR, CMD_DEL_REALM, MFT_STRING, 0}
+};
+
+struct k5_menu_def k5_menu_kdc[] = {
+ {IDS_CFG_RE_MNK, CMD_NEW_SERVER, MFT_STRING, 0},
+ {IDS_CFG_RE_MDK, CMD_DEL_SERVER, MFT_STRING, 0},
+ {IDS_CFG_RE_MAK, CMD_MAKE_ADMIN, MFT_STRING, 0},
+ {IDS_CFG_RE_MMK, CMD_MAKE_MASTER, MFT_STRING, 0}
+};
+
+struct k5_menu_def k5_menu_dmap[] = {
+ {IDS_CFG_RE_MND, CMD_NEW_DMAP, MFT_STRING, 0},
+ {IDS_CFG_RE_MDD, CMD_DEL_DMAP, MFT_STRING, 0}
+};
+
+HMENU
+k5_menu_from_def(struct k5_menu_def * def, khm_size n) {
+ HMENU menu;
+ MENUITEMINFO mii;
+ khm_size i;
+ khm_size cch;
+ wchar_t buf[1024];
+
+ menu = CreatePopupMenu();
+
+ for (i=0; i < n; i++) {
+ ZeroMemory(&mii, sizeof(mii));
+
+ mii.cbSize = sizeof(mii);
+
+ if (def[i].type == MFT_STRING) {
+ LoadString(hResModule, def[i].string,
+ buf, ARRAYLENGTH(buf));
+ StringCchLength(buf, ARRAYLENGTH(buf), &cch);
+
+ mii.fMask = MIIM_STRING | MIIM_ID;
+ mii.fType = MFT_STRING;
+
+ mii.fState = def[i].state;
+ mii.wID = def[i].id;
+ mii.cch = (UINT) cch;
+ mii.dwTypeData = buf;
+
+ InsertMenuItem(menu, (UINT) i, TRUE, &mii);
+ } else {
+#ifdef DEBUG
+ assert(FALSE);
+#endif
+ }
+ }
+
+ return menu;
+}
+
+void
+k5_delete_realms(HWND hwnd, k5_config_data * d) {
+ LVITEM lvi;
+ int idx;
+ HWND hw_rlm;
+ BOOL modified = FALSE;
+ khm_size r;
+
+ hw_rlm = GetDlgItem(hwnd, IDC_CFG_REALMS);
+
+ idx = -1;
+ while((idx = ListView_GetNextItem(hw_rlm, idx,
+ LVNI_SELECTED))
+ != -1) {
+ ZeroMemory(&lvi, sizeof(lvi));
+ lvi.iItem = idx;
+ lvi.iSubItem = 0;
+ lvi.mask = LVIF_PARAM;
+
+ ListView_GetItem(hw_rlm, &lvi);
+
+ if (lvi.lParam != -1 &&
+ (r = lvi.lParam) < d->n_realms) {
+ d->realms[r].flags ^= K5_RDFLAG_DELETED;
+ modified = TRUE;
+ }
+ }
+
+ if (modified) {
+ d->flags |= K5_CDFLAG_MOD_REALMS;
+
+ k5_purge_config_data(d, TRUE, TRUE, TRUE);
+ k5_update_realms_display(hw_rlm, d);
+ k5_update_dmap_display(GetDlgItem(hwnd, IDC_CFG_DMAP), NULL, 0);
+ k5_update_kdcs_display(GetDlgItem(hwnd, IDC_CFG_KDC), NULL, 0);
+ }
+}
+
+void
+k5_delete_servers(HWND hwnd, k5_config_data * d) {
+ HWND hw_kdc;
+ LVITEM lvi;
+ khm_size r;
+ khm_size k;
+ int idx;
+ BOOL modified = FALSE;
+
+ hw_kdc = GetDlgItem(hwnd, IDC_CFG_KDC);
+ r = d->c_realm;
+
+ idx = -1;
+ while((idx = ListView_GetNextItem(hw_kdc, idx,
+ LVNI_SELECTED))
+ != -1) {
+ ZeroMemory(&lvi, sizeof(lvi));
+ lvi.iItem = idx;
+ lvi.iSubItem = 0;
+ lvi.mask = LVIF_PARAM;
+
+ ListView_GetItem(hw_kdc, &lvi);
+
+ if (lvi.lParam != -1 &&
+ (k = lvi.lParam) < d->n_realms) {
+ d->realms[r].kdcs[k].flags ^= K5_RKFLAG_DELETED;
+ modified = TRUE;
+ }
+ }
+
+ if (modified) {
+ d->flags |= K5_CDFLAG_MOD_REALMS;
+ d->realms[r].flags |= K5_RDFLAG_MODIFED;
+
+ k5_purge_config_data(d, TRUE, TRUE, TRUE);
+ k5_update_realms_display(GetDlgItem(hwnd, IDC_CFG_REALMS), d);
+ k5_update_kdcs_display(hw_kdc, d, r);
+ }
+}
+
+void
+k5_delete_dmap(HWND hwnd, k5_config_data * d) {
+ HWND hw_dmp;
+ LVITEM lvi;
+ khm_size r;
+ khm_size m;
+ int idx;
+ BOOL modified = FALSE;
+
+ hw_dmp = GetDlgItem(hwnd, IDC_CFG_DMAP);
+ r = d->c_realm;
+
+ idx = -1;
+ while((idx = ListView_GetNextItem(hw_dmp, idx,
+ LVNI_SELECTED))
+ != -1) {
+ ZeroMemory(&lvi, sizeof(lvi));
+ lvi.iItem = idx;
+ lvi.iSubItem = 0;
+ lvi.mask = LVIF_PARAM;
+
+ ListView_GetItem(hw_dmp, &lvi);
+
+ if (lvi.lParam != -1 &&
+ (m = lvi.lParam) < d->n_realms) {
+ d->realms[r].domain_maps[m].flags ^= K5_DMFLAG_DELETED;
+ modified = TRUE;
+ }
+ }
+
+ if (modified) {
+ d->flags |= K5_CDFLAG_MOD_REALMS;
+ k5_purge_config_data(d, FALSE, FALSE, TRUE);
+
+ if (!(d->realms[r].flags & K5_RDFLAG_MODIFED)) {
+ d->realms[r].flags |= K5_RDFLAG_MODIFED;
+
+ k5_update_realms_display(GetDlgItem(hwnd, IDC_CFG_REALMS), d);
+ }
+
+ k5_update_dmap_display(hw_dmp, d, r);
+ }
+}
+
+INT_PTR CALLBACK
+k5_realms_dlgproc(HWND hwnd,
+ UINT uMsg,
+ WPARAM wParam,
+ LPARAM lParam) {
+ k5_config_data * d;
+
+ d = &k5_config_dlg_data;
+
+ switch(uMsg) {
+ case WM_INITDIALOG:
+ {
+ LVCOLUMN lvc;
+ HWND hw;
+ RECT r;
+ wchar_t buf[256];
+
+ assert(k5_dlg_data_valid);
+
+ d->node_realm = (khui_config_node) lParam;
+
+ /* set up columns for the Realms list */
+ hw = GetDlgItem(hwnd, IDC_CFG_REALMS);
+#ifdef DEBUG
+ assert(hw);
+#endif
+ GetWindowRect(hw, &r);
+ r.right -= 5; /* shave a few pixels off the width */
+ ZeroMemory(&lvc, sizeof(lvc));
+ lvc.mask = LVCF_TEXT | LVCF_WIDTH;
+ lvc.pszText = buf;
+ lvc.cx = (r.right - r.left);
+ LoadString(hResModule, IDS_CFG_RE_REALMS,
+ buf, ARRAYLENGTH(buf));
+
+ ListView_InsertColumn(hw, 0, &lvc);
+
+ ListView_SetImageList(hw,
+ k5_get_state_image_list(),
+ LVSIL_STATE);
+
+ k5_update_realms_display(hw, d);
+
+ /* set up columns for the servers list */
+ hw = GetDlgItem(hwnd, IDC_CFG_KDC);
+#ifdef DEBUG
+ assert(hw);
+#endif
+ GetWindowRect(hw, &r);
+ r.right -= 5;
+ ZeroMemory(&lvc, sizeof(lvc));
+ lvc.mask = LVCF_TEXT | LVCF_WIDTH;
+ lvc.pszText = buf;
+ lvc.cx = (r.right - r.left) * 2 / 4;
+ LoadString(hResModule, IDS_CFG_RE_HEAD_SVR,
+ buf, ARRAYLENGTH(buf));
+
+ ListView_InsertColumn(hw, 0, &lvc);
+
+ lvc.cx = (r.right - r.left) * 1 / 4;
+ LoadString(hResModule, IDS_CFG_RE_HEAD_ADMIN,
+ buf, ARRAYLENGTH(buf));
+ ListView_InsertColumn(hw, 1, &lvc);
+
+ LoadString(hResModule, IDS_CFG_RE_HEAD_MASTER,
+ buf, ARRAYLENGTH(buf));
+ ListView_InsertColumn(hw, 2, &lvc);
+
+ ListView_SetImageList(hw,
+ k5_get_state_image_list(),
+ LVSIL_STATE);
+
+ /* set up columns for the domain/host mapping list */
+ hw = GetDlgItem(hwnd, IDC_CFG_DMAP);
+#ifdef DEBUG
+ assert(hw);
+#endif
+ GetWindowRect(hw, &r);
+ r.right -= 5;
+ ZeroMemory(&lvc, sizeof(lvc));
+ lvc.mask = LVCF_TEXT | LVCF_WIDTH;
+ lvc.pszText = buf;
+ lvc.cx = (r.right - r.left);
+ LoadString(hResModule, IDS_CFG_RE_HEAD_DOMAIN,
+ buf, ARRAYLENGTH(buf));
+
+ ListView_InsertColumn(hw, 0, &lvc);
+
+
+ ListView_SetImageList(hw,
+ k5_get_state_image_list(),
+ LVSIL_STATE);
+
+ /* Now set up the context menus */
+ d->hm_realms_ctx = k5_menu_from_def(k5_menu_realms, ARRAYLENGTH(k5_menu_realms));
+ d->hm_kdc_ctx = k5_menu_from_def(k5_menu_kdc, ARRAYLENGTH(k5_menu_kdc));
+ d->hm_dmap_ctx = k5_menu_from_def(k5_menu_dmap, ARRAYLENGTH(k5_menu_dmap));
+ }
+ break;
+
+ case WM_CONTEXTMENU:
+ {
+ UINT id;
+ HMENU hm = NULL;
+ int x,y;
+
+ id = GetDlgCtrlID((HWND) wParam);
+
+ if (id == IDC_CFG_REALMS) {
+ HWND hw_realms;
+ int n;
+ MENUITEMINFO mii;
+
+ hm = d->hm_realms_ctx;
+
+ hw_realms = GetDlgItem(hwnd, IDC_CFG_REALMS);
+#ifdef DEBUG
+ assert(hw_realms);
+#endif
+ n = ListView_GetSelectedCount(hw_realms);
+ ZeroMemory(&mii, sizeof(mii));
+ mii.cbSize = sizeof(mii);
+
+ if (n == 0) {
+ mii.fMask = MIIM_STATE;
+ mii.fState = MFS_DISABLED;
+
+ SetMenuItemInfo(hm, CMD_DEL_REALM, FALSE, &mii);
+ } else {
+
+ mii.fMask = MIIM_STATE;
+ mii.fState = MFS_ENABLED;
+
+ SetMenuItemInfo(hm, CMD_DEL_REALM, FALSE, &mii);
+ }
+
+ } else if (id == IDC_CFG_KDC) {
+ HWND hw_kdc;
+ int n;
+ MENUITEMINFO mii;
+
+ hm = d->hm_kdc_ctx;
+
+ hw_kdc = GetDlgItem(hwnd, IDC_CFG_KDC);
+#ifdef DEBUG
+ assert(hw_kdc);
+#endif
+ n = ListView_GetSelectedCount(hw_kdc);
+ ZeroMemory(&mii, sizeof(mii));
+ mii.cbSize = sizeof(mii);
+
+ if (n == 1) {
+ mii.fMask = MIIM_STATE;
+ mii.fState = MFS_ENABLED;
+
+ SetMenuItemInfo(hm, CMD_DEL_SERVER, FALSE, &mii);
+ SetMenuItemInfo(hm, CMD_MAKE_ADMIN, FALSE, &mii);
+ SetMenuItemInfo(hm, CMD_MAKE_MASTER, FALSE, &mii);
+ } else if (n == 0) {
+
+ mii.fMask = MIIM_STATE;
+ mii.fState = MFS_DISABLED;
+
+ SetMenuItemInfo(hm, CMD_DEL_SERVER, FALSE, &mii);
+ SetMenuItemInfo(hm, CMD_MAKE_ADMIN, FALSE, &mii);
+ SetMenuItemInfo(hm, CMD_MAKE_MASTER,FALSE, &mii);
+ } else {
+
+ mii.fMask = MIIM_STATE;
+ mii.fState = MFS_ENABLED;
+
+ SetMenuItemInfo(hm, CMD_DEL_SERVER, FALSE, &mii);
+
+ mii.fState = MFS_DISABLED;
+
+ SetMenuItemInfo(hm, CMD_MAKE_ADMIN, FALSE, &mii);
+ SetMenuItemInfo(hm, CMD_MAKE_MASTER,FALSE, &mii);
+ }
+
+ } else if (id == IDC_CFG_DMAP) {
+ HWND hw_dmap;
+ MENUITEMINFO mii;
+ int n;
+
+ hm = d->hm_dmap_ctx;
+
+ hw_dmap = GetDlgItem(hwnd, IDC_CFG_DMAP);
+#ifdef DEBUG
+ assert(hw_dmap);
+#endif
+
+ n = ListView_GetSelectedCount(hw_dmap);
+ ZeroMemory(&mii, sizeof(mii));
+ mii.cbSize = sizeof(mii);
+
+ if (n == 0) {
+ mii.fMask = MIIM_STATE;
+ mii.fState = MFS_DISABLED;
+
+ SetMenuItemInfo(hm, CMD_DEL_DMAP, FALSE, &mii);
+ } else {
+ mii.fMask = MIIM_STATE;
+ mii.fState = MFS_ENABLED;
+
+ SetMenuItemInfo(hm, CMD_DEL_DMAP, FALSE, &mii);
+ }
+ }
+
+ if (hm) {
+ if (LOWORD(lParam) == 0xffff) {
+ HWND hw;
+ RECT r;
+
+ hw = GetDlgItem(hwnd, id);
+#ifdef DEBUG
+ assert(hw);
+#endif
+ GetWindowRect(hw, &r);
+ x = r.left;
+ y = r.top;
+ } else {
+ x = LOWORD(lParam);
+ y = HIWORD(lParam);
+ }
+
+ TrackPopupMenu(hm,
+ TPM_LEFTALIGN | TPM_TOPALIGN,
+ x, y,
+ 0, hwnd, NULL);
+ }
+
+ return TRUE;
+ }
+ break;
+
+ case WM_NOTIFY:
+ {
+ LPNMHDR pnmh;
+ HWND hw_rlm = NULL;
+ HWND hw_kdc = NULL;
+ HWND hw_dmp = NULL;
+ int i;
+
+ pnmh = (LPNMHDR) lParam;
+
+ /* catchalls for all three list views */
+ switch (pnmh->code) {
+ case NM_DBLCLK:
+ {
+ HWND hw_ctl;
+ LVITEM lvi;
+ LVHITTESTINFO hti;
+ LPNMITEMACTIVATE pnmi;
+
+ if (pnmh->idFrom != IDC_CFG_REALMS &&
+ pnmh->idFrom != IDC_CFG_KDC &&
+ pnmh->idFrom != IDC_CFG_DMAP)
+ break;
+
+ /* if the user double clicks on the 'new
+ [something]' item, we start editing it. */
+ hw_ctl = pnmh->hwndFrom;
+ pnmi = (LPNMITEMACTIVATE) lParam;
+
+ ZeroMemory(&hti, sizeof(hti));
+ hti.pt = pnmi->ptAction;
+
+ ListView_SubItemHitTest(hw_ctl, &hti);
+ if (hti.flags & LVHT_ONITEM) {
+ ZeroMemory(&lvi, sizeof(lvi));
+ lvi.mask = LVIF_PARAM;
+ lvi.iItem = hti.iItem;
+
+ ListView_GetItem(hw_ctl, &lvi);
+
+ if (lvi.lParam == -1)
+ ListView_EditLabel(hw_ctl, hti.iItem);
+ }
+
+ return TRUE;
+ }
+ break;
+ }
+
+ if (pnmh->idFrom == IDC_CFG_REALMS) {
+
+ hw_rlm = pnmh->hwndFrom;
+
+ switch(pnmh->code) {
+ case LVN_ITEMCHANGED:
+ i = ListView_GetSelectedCount(hw_rlm);
+ hw_kdc = GetDlgItem(hwnd, IDC_CFG_KDC);
+ hw_dmp = GetDlgItem(hwnd, IDC_CFG_DMAP);
+
+ d->c_realm = (khm_size) -1;
+
+ if (i == 1) {
+ LVITEM lvi;
+ wchar_t fmt[256];
+ wchar_t buf[K5_MAXCCH_REALM + 256];
+
+ i = ListView_GetNextItem(hw_rlm, -1,
+ LVNI_SELECTED);
+ if (i == -1)
+ goto _no_selection;
+
+ ZeroMemory(&lvi, sizeof(lvi));
+
+ lvi.iItem = i;
+ lvi.iSubItem = 0;
+ lvi.mask = LVIF_PARAM;
+
+ ListView_GetItem(hw_rlm, &lvi);
+
+ if (lvi.lParam == -1)
+ goto _no_selection;
+
+ d->c_realm = lvi.lParam;
+
+ k5_update_kdcs_display(hw_kdc, d, lvi.lParam);
+ k5_update_dmap_display(hw_dmp, d, lvi.lParam);
+
+ LoadString(hResModule, IDS_CFG_RE_KDCS_R,
+ fmt, ARRAYLENGTH(fmt));
+ StringCbPrintf(buf, sizeof(buf), fmt,
+ d->realms[d->c_realm].realm);
+
+ SetDlgItemText(hwnd, IDC_CFG_SERVERSGRP, buf);
+
+ LoadString(hResModule, IDS_CFG_RE_DMAPS_R,
+ fmt, ARRAYLENGTH(fmt));
+ StringCbPrintf(buf, sizeof(buf), fmt,
+ d->realms[d->c_realm].realm);
+
+ SetDlgItemText(hwnd, IDC_CFG_DOMAINGRP, buf);
+ return TRUE;
+ }
+
+ _no_selection:
+ {
+ wchar_t buf[256];
+
+ k5_update_kdcs_display(hw_kdc, NULL, 0);
+ k5_update_dmap_display(hw_dmp, NULL, 0);
+
+ LoadString(hResModule, IDS_CFG_RE_KDCS,
+ buf, ARRAYLENGTH(buf));
+ SetDlgItemText(hwnd, IDC_CFG_SERVERSGRP, buf);
+
+ LoadString(hResModule, IDS_CFG_RE_DMAPS,
+ buf, ARRAYLENGTH(buf));
+ SetDlgItemText(hwnd, IDC_CFG_DOMAINGRP, buf);
+ }
+ break;
+
+ case LVN_BEGINLABELEDIT:
+ {
+ NMLVDISPINFO * pdisp;
+ LVITEM lvi;
+
+ pdisp = (NMLVDISPINFO *) lParam;
+
+ ZeroMemory(&lvi, sizeof(lvi));
+ lvi.iItem = pdisp->item.iItem;
+ lvi.mask = LVIF_PARAM;
+
+ ListView_GetItem(hw_rlm, &lvi);
+
+ if (pdisp->item.iItem == -1 ||
+ lvi.lParam != -1) {
+ SetWindowLongPtr(hwnd, DWLP_MSGRESULT, TRUE);
+ } else {
+ /* allow editing */
+ HWND hw_edit;
+
+ hw_edit = ListView_GetEditControl(hw_rlm);
+ if (hw_edit != NULL) {
+ SendMessage(hw_edit,
+ EM_SETLIMITTEXT,
+ K5_MAXCCH_REALM - 1,
+ 0);
+ }
+ SetWindowLongPtr(hwnd, DWLP_MSGRESULT, FALSE);
+ }
+
+ return TRUE;
+ }
+ break;
+
+ case LVN_ENDLABELEDIT:
+ {
+ NMLVDISPINFO * pdisp;
+ khm_size n;
+
+ pdisp = (NMLVDISPINFO *) lParam;
+
+ if (pdisp->item.pszText && pdisp->item.pszText[0]) {
+ khm_size i;
+
+ /* first find out whether this is actually
+ a new realm */
+
+ for (i=0; i < d->n_realms; i++) {
+ if ((d->realms[i].flags & K5_RDFLAG_NEW) &&
+ (d->realms[i].flags & K5_RDFLAG_DELETED))
+ continue;
+
+ if (!wcsicmp(d->realms[i].realm, pdisp->item.pszText))
+ break;
+ }
+
+ if (i < d->n_realms) {
+ khui_alert * alert = NULL;
+ wchar_t buf[KHUI_MAXCCH_MESSAGE];
+ wchar_t fmt[KHUI_MAXCCH_MESSAGE];
+
+ khui_alert_create_empty(&alert);
+
+ LoadString(hResModule, IDS_CFG_RE_ARNUT,
+ fmt, ARRAYLENGTH(fmt));
+ StringCbPrintf(buf, sizeof(buf), fmt,
+ pdisp->item.pszText);
+ khui_alert_set_title(alert, buf);
+
+ LoadString(hResModule, IDS_CFG_RE_ARNUM,
+ fmt, ARRAYLENGTH(fmt));
+ StringCbPrintf(buf, sizeof(buf), fmt,
+ pdisp->item.pszText);
+ khui_alert_set_message(alert, buf);
+
+ khui_alert_add_command(alert, KHUI_PACTION_CLOSE);
+ khui_alert_set_severity(alert, KHERR_INFO);
+
+ khui_alert_show_modal(alert);
+ khui_alert_release(alert);
+
+ return TRUE;
+ }
+
+ n = d->n_realms;
+ k5_assert_n_realms(d, n+1);
+ StringCbCopy(d->realms[n].realm,
+ sizeof(d->realms[n].realm),
+ pdisp->item.pszText);
+ d->realms[n].flags = K5_RDFLAG_NEW;
+ d->n_realms++;
+
+ d->flags |= K5_CDFLAG_MOD_REALMS;
+
+ k5_update_realms_display(hw_rlm, d);
+ }
+
+ return TRUE;
+ }
+ break;
+
+ case LVN_KEYDOWN:
+ {
+ NMLVKEYDOWN * pnmk;
+
+ pnmk = (NMLVKEYDOWN *) lParam;
+
+ if (pnmk->wVKey == VK_DELETE) {
+ k5_delete_realms(hwnd, d);
+ return TRUE;
+ }
+ }
+ break;
+ }
+ } else if (pnmh->idFrom == IDC_CFG_KDC) {
+ hw_kdc = pnmh->hwndFrom;
+
+ switch (pnmh->code) {
+ case LVN_BEGINLABELEDIT:
+ {
+ NMLVDISPINFO * pdisp;
+ LVITEM lvi;
+
+ pdisp = (NMLVDISPINFO *) lParam;
+
+ ZeroMemory(&lvi, sizeof(lvi));
+ lvi.iItem = pdisp->item.iItem;
+ lvi.mask = LVIF_PARAM;
+
+ ListView_GetItem(hw_kdc, &lvi);
+
+ /* Only allow editing if the user is trying to
+ edit the <New server> entry. */
+ if (pdisp->item.iItem == -1 ||
+ lvi.lParam != -1) {
+ SetWindowLongPtr(hwnd, DWLP_MSGRESULT, TRUE);
+ } else {
+ HWND hw_edit;
+
+ hw_edit = ListView_GetEditControl(hw_kdc);
+ if (hw_edit != NULL) {
+ SendMessage(hw_edit,
+ EM_SETLIMITTEXT,
+ K5_MAXCCH_HOST - 1,
+ 0);
+ }
+ SetWindowLongPtr(hwnd, DWLP_MSGRESULT, FALSE);
+ }
+ return TRUE;
+ }
+ break;
+
+ case LVN_ENDLABELEDIT:
+ {
+ NMLVDISPINFO * pdisp;
+ khm_size r;
+ khm_size k;
+
+ r = d->c_realm;
+
+ pdisp = (NMLVDISPINFO *) lParam;
+
+ if (pdisp->item.pszText && pdisp->item.pszText[0]) {
+
+ /* first of all, check if we already have
+ a KDC by this name... */
+ for (k=0; k < d->realms[r].n_kdcs; k++) {
+ if ((d->realms[r].kdcs[k].flags & K5_RKFLAG_NEW) &&
+ (d->realms[r].kdcs[k].flags & K5_RKFLAG_DELETED))
+ continue;
+
+ if (!wcsicmp(d->realms[r].kdcs[k].name,
+ pdisp->item.pszText))
+ break;
+ }
+
+ if (k < d->realms[r].n_kdcs) {
+ khui_alert * alert = NULL;
+ wchar_t buf[K5_MAXCCH_HOST + 256];
+ wchar_t fmt[256];
+
+ khui_alert_create_empty(&alert);
+
+ LoadString(hResModule, IDS_CFG_RE_ASNUT,
+ fmt, ARRAYLENGTH(fmt));
+ StringCbPrintf(buf, sizeof(buf), fmt,
+ pdisp->item.pszText,
+ d->realms[r].realm);
+ khui_alert_set_title(alert, buf);
+
+ LoadString(hResModule, IDS_CFG_RE_ASNUM,
+ fmt, ARRAYLENGTH(fmt));
+ StringCbPrintf(buf, sizeof(buf), fmt,
+ pdisp->item.pszText,
+ d->realms[r].realm);
+ khui_alert_set_message(alert, buf);
+
+ khui_alert_set_severity(alert, KHERR_INFO);
+ khui_alert_show_modal(alert);
+
+ khui_alert_release(alert);
+
+ SetWindowLongPtr(hwnd, DWLP_MSGRESULT, FALSE);
+ return TRUE;
+ }
+
+ if (k >= K5_MAX_KDC) {
+ SetWindowLongPtr(hwnd, DWLP_MSGRESULT, FALSE);
+ /* TODO: show a message box saying
+ there are too many KDC's
+ already. */
+ return TRUE;
+ }
+
+ StringCbCopy(d->realms[r].kdcs[k].name,
+ sizeof(d->realms[0].kdcs[0].name),
+ pdisp->item.pszText);
+ d->realms[r].kdcs[k].flags = K5_RKFLAG_NEW;
+ d->realms[r].n_kdcs++;
+
+ k5_update_kdcs_display(hw_kdc, d, d->c_realm);
+
+ if (!(d->realms[r].flags & K5_RDFLAG_MODIFED)) {
+ d->flags |= K5_CDFLAG_MOD_REALMS;
+ d->realms[r].flags |= K5_RDFLAG_MODIFED;
+ k5_update_realms_display(GetDlgItem(hwnd, IDC_CFG_REALMS), d);
+ }
+ }
+ return TRUE;
+ }
+ break;
+
+ case LVN_KEYDOWN:
+ {
+ NMLVKEYDOWN * pnmk;
+
+ pnmk = (NMLVKEYDOWN *) lParam;
+
+ if (pnmk->wVKey == VK_DELETE) {
+ k5_delete_servers(hwnd, d);
+ }
+ return TRUE;
+ }
+ break;
+
+ case NM_CLICK:
+ {
+ LPNMITEMACTIVATE lpnmi;
+ LVHITTESTINFO hti;
+ LVITEM lvi;
+ khm_size r;
+ khm_size k;
+
+ r = d->c_realm;
+
+ lpnmi = (LPNMITEMACTIVATE) lParam;
+
+ ZeroMemory(&hti, sizeof(hti));
+ hti.pt = lpnmi->ptAction;
+ ListView_SubItemHitTest(hw_kdc, &hti);
+
+ if (hti.iSubItem != 0) {
+
+ ZeroMemory(&lvi, sizeof(lvi));
+
+ lvi.mask = LVIF_PARAM;
+ lvi.iItem = hti.iItem;
+ ListView_GetItem(hw_kdc, &lvi);
+
+ if (lvi.lParam < 0 || lvi.lParam >= (int) d->realms[r].n_kdcs)
+ return TRUE;
+
+ k = lvi.lParam;
+
+ if (hti.iSubItem == K5_KDCSI_ADMIN) {
+ d->realms[r].kdcs[k].admin = !d->realms[r].kdcs[k].admin;
+ d->realms[r].kdcs[k].flags |= K5_RKFLAG_MOD_ADMIN;
+ } else if (hti.iSubItem == K5_KDCSI_MASTER) {
+ if (d->realms[r].kdcs[k].master) {
+ d->realms[r].kdcs[k].master = FALSE;
+ d->realms[r].kdcs[k].flags |= K5_RKFLAG_MOD_MASTER;
+ } else {
+ khm_size i;
+
+ for (i=0; i < d->realms[r].n_kdcs; i++) {
+ if ((d->realms[r].kdcs[i].flags & K5_RKFLAG_DELETED) &&
+ (d->realms[r].kdcs[i].flags & K5_RKFLAG_NEW))
+ continue;
+ if (d->realms[r].kdcs[i].master) {
+ d->realms[r].kdcs[i].master = FALSE;
+ d->realms[r].kdcs[i].flags |= K5_RKFLAG_MOD_MASTER;
+ }
+ }
+
+ d->realms[r].kdcs[k].master = TRUE;
+ d->realms[r].kdcs[k].flags |= K5_RKFLAG_MOD_MASTER;
+ }
+ } else {
+#ifdef DEBUG
+ assert(FALSE);
+#endif
+ }
+
+ if (!(d->realms[r].flags & K5_RDFLAG_MODIFED)) {
+ d->realms[r].flags |= K5_RDFLAG_MODIFED;
+ d->flags |= K5_CDFLAG_MOD_REALMS;
+ k5_update_realms_display(GetDlgItem(hwnd, IDC_CFG_REALMS), d);
+ }
+
+ k5_update_kdcs_display(hw_kdc, d, r);
+ }
+ }
+ break;
+ }
+ } else if (pnmh->idFrom == IDC_CFG_DMAP) {
+ hw_dmp = pnmh->hwndFrom;
+
+ switch (pnmh->code) {
+ case LVN_BEGINLABELEDIT:
+ {
+ NMLVDISPINFO * pdisp;
+ LVITEM lvi;
+
+ pdisp = (NMLVDISPINFO *) lParam;
+
+ ZeroMemory(&lvi, sizeof(lvi));
+ lvi.iItem = pdisp->item.iItem;
+ lvi.mask = LVIF_PARAM;
+
+ ListView_GetItem(hw_dmp, &lvi);
+
+ /* Only allow editing if the user is trying to
+ edit the <New domain mapping> entry. */
+ if (pdisp->item.iItem == -1 ||
+ lvi.lParam != -1) {
+ SetWindowLongPtr(hwnd, DWLP_MSGRESULT, TRUE);
+ } else {
+ HWND hw_edit;
+
+ hw_edit = ListView_GetEditControl(hw_dmp);
+ if (hw_edit != NULL) {
+ SendMessage(hw_edit,
+ EM_SETLIMITTEXT,
+ K5_MAXCCH_HOST - 1,
+ 0);
+ }
+ SetWindowLongPtr(hwnd, DWLP_MSGRESULT, FALSE);
+ }
+ return TRUE;
+ }
+ break;
+
+ case LVN_ENDLABELEDIT:
+ {
+ NMLVDISPINFO * pdisp;
+ khm_size r;
+ khm_size m;
+
+ r = d->c_realm;
+
+ pdisp = (NMLVDISPINFO *) lParam;
+
+ if (pdisp->item.pszText && pdisp->item.pszText[0]) {
+
+ /* first check if this is unique */
+ for (m=0; m < d->realms[r].n_domain_maps; m++) {
+ if ((d->realms[r].domain_maps[m].flags & K5_DMFLAG_NEW) &&
+ (d->realms[r].domain_maps[m].flags & K5_DMFLAG_DELETED))
+ continue;
+
+ if (!wcsicmp(d->realms[r].domain_maps[m].name,
+ pdisp->item.pszText))
+ break;
+ }
+
+ if (m < d->realms[r].n_domain_maps) {
+ khui_alert * alert;
+ wchar_t buf[K5_MAXCCH_HOST + 256];
+ wchar_t fmt[256];
+
+ khui_alert_create_empty(&alert);
+
+ LoadString(hResModule, IDS_CFG_RE_DMNUT,
+ fmt, ARRAYLENGTH(fmt));
+ StringCbPrintf(buf, sizeof(buf), fmt,
+ pdisp->item.pszText,
+ d->realms[r].realm);
+ khui_alert_set_title(alert, buf);
+
+ LoadString(hResModule, IDS_CFG_RE_DMNUM,
+ fmt, ARRAYLENGTH(fmt));
+ StringCbPrintf(buf, sizeof(buf), fmt,
+ pdisp->item.pszText,
+ d->realms[r].realm);
+ khui_alert_set_message(alert, buf);
+
+ khui_alert_set_severity(alert, KHERR_INFO);
+ khui_alert_show_modal(alert);
+
+ khui_alert_release(alert);
+
+ SetWindowLongPtr(hwnd, DWLP_MSGRESULT, FALSE);
+ return TRUE;
+ }
+
+ if (m >= K5_MAX_DOMAIN_MAPPINGS) {
+ SetWindowLongPtr(hwnd, DWLP_MSGRESULT, FALSE);
+ /* TODO: show a message box saying
+ there are too many domain mappings
+ already. */
+ return TRUE;
+ }
+
+ StringCbCopy(d->realms[r].domain_maps[m].name,
+ sizeof(d->realms[0].domain_maps[0].name),
+ pdisp->item.pszText);
+ d->realms[r].domain_maps[m].flags = K5_DMFLAG_NEW;
+ d->realms[r].n_domain_maps++;
+
+ k5_update_dmap_display(hw_dmp, d, d->c_realm);
+
+ if (!(d->realms[r].flags & K5_RDFLAG_MODIFED)) {
+ d->flags |= K5_CDFLAG_MOD_REALMS;
+ d->realms[r].flags |= K5_RDFLAG_MODIFED;
+ k5_update_realms_display(GetDlgItem(hwnd, IDC_CFG_REALMS), d);
+ }
+ }
+ return TRUE;
+ }
+ break;
+
+ case LVN_KEYDOWN:
+ {
+ NMLVKEYDOWN * pnmk;
+
+ pnmk = (NMLVKEYDOWN *) lParam;
+
+ if (pnmk->wVKey == VK_DELETE) {
+ k5_delete_dmap(hwnd, d);
+ return TRUE;
+ }
+ }
+ break;
+ }
+ } /* end of handling DMAP notifications */
+ }
+ break;
+
+ case WM_COMMAND:
+ switch(LOWORD(wParam)) {
+ case CMD_NEW_REALM:
+ {
+ ListView_EditLabel(GetDlgItem(hwnd, IDC_CFG_REALMS), 0);
+
+ return TRUE;
+ }
+ break;
+
+ case CMD_DEL_REALM:
+ {
+ k5_delete_realms(hwnd, d);
+
+ return TRUE;
+ }
+ break;
+
+ case CMD_NEW_SERVER:
+ {
+ ListView_EditLabel(GetDlgItem(hwnd, IDC_CFG_KDC), 0);
+
+ return TRUE;
+ }
+ break;
+
+ case CMD_DEL_SERVER:
+ {
+ k5_delete_servers(hwnd, d);
+
+ return TRUE;
+ }
+ break;
+
+ case CMD_MAKE_ADMIN:
+ {
+ HWND hw_kdc;
+ int idx;
+ khm_size r;
+ khm_size k;
+ BOOL modified = FALSE;
+
+ r = d->c_realm;
+
+ hw_kdc = GetDlgItem(hwnd, IDC_CFG_KDC);
+
+ if (ListView_GetSelectedCount(hw_kdc) != 1)
+ return TRUE;
+
+ idx = -1;
+ while ((idx = ListView_GetNextItem(hw_kdc, idx,
+ LVNI_SELECTED)) != -1) {
+ LVITEM lvi;
+
+ ZeroMemory(&lvi, sizeof(lvi));
+
+ lvi.mask = LVIF_PARAM;
+ lvi.iItem = idx;
+ ListView_GetItem(hw_kdc, &lvi);
+
+ k = lvi.lParam;
+
+ if (lvi.lParam >= 0 && lvi.lParam < (int) d->realms[r].n_kdcs) {
+ d->realms[r].kdcs[k].admin = !d->realms[r].kdcs[k].admin;
+ d->realms[r].kdcs[k].flags |= K5_RKFLAG_MOD_ADMIN;
+ modified = TRUE;
+
+ break;
+ }
+ }
+
+ if (modified) {
+ if (!(d->realms[r].flags & K5_RDFLAG_MODIFED)) {
+ d->flags |= K5_CDFLAG_MOD_REALMS;
+ d->realms[r].flags |= K5_RDFLAG_MODIFED;
+ k5_update_realms_display(GetDlgItem(hwnd, IDC_CFG_REALMS), d);
+ }
+ }
+
+ k5_update_kdcs_display(hw_kdc, d, r);
+
+ return TRUE;
+ }
+ break;
+
+ case CMD_MAKE_MASTER:
+ {
+ HWND hw_kdc;
+ int idx;
+ khm_size r;
+ khm_size k;
+ BOOL modified = FALSE;
+
+ r = d->c_realm;
+
+ hw_kdc = GetDlgItem(hwnd, IDC_CFG_KDC);
+
+ if (ListView_GetSelectedCount(hw_kdc) != 1)
+ return TRUE;
+
+ idx = -1;
+ while ((idx = ListView_GetNextItem(hw_kdc, idx,
+ LVNI_SELECTED)) != -1) {
+ LVITEM lvi;
+
+ ZeroMemory(&lvi, sizeof(lvi));
+
+ lvi.mask = LVIF_PARAM;
+ lvi.iItem = idx;
+ ListView_GetItem(hw_kdc, &lvi);
+
+ k = lvi.lParam;
+
+ if (lvi.lParam >= 0 && lvi.lParam < (int) d->realms[r].n_kdcs) {
+ if (d->realms[r].kdcs[k].master) {
+ d->realms[r].kdcs[k].master = FALSE;
+ } else {
+ khm_size i;
+
+ for (i=0; i < d->realms[r].n_kdcs; i++) {
+ if ((d->realms[r].kdcs[i].flags & K5_RKFLAG_NEW) &&
+ (d->realms[r].kdcs[i].flags & K5_RKFLAG_DELETED))
+ continue;
+
+ if (d->realms[r].kdcs[i].master) {
+ d->realms[r].kdcs[i].master = FALSE;
+ d->realms[r].kdcs[i].flags |= K5_RKFLAG_MOD_MASTER;
+ }
+ }
+
+ d->realms[r].kdcs[k].master = TRUE;
+ }
+ d->realms[r].kdcs[k].flags |= K5_RKFLAG_MOD_MASTER;
+ modified = TRUE;
+
+ break;
+ }
+ }
+
+ if (modified) {
+ if (!(d->realms[r].flags & K5_RDFLAG_MODIFED)) {
+ d->flags |= K5_CDFLAG_MOD_REALMS;
+ d->realms[r].flags |= K5_RDFLAG_MODIFED;
+ k5_update_realms_display(hwnd, d);
+ }
+ }
+
+ k5_update_kdcs_display(hw_kdc, d, r);
+
+ return TRUE;
+ }
+ break;
+
+ case CMD_NEW_DMAP:
+ {
+ ListView_EditLabel(GetDlgItem(hwnd, IDC_CFG_DMAP), 0);
+
+ return TRUE;
+ }
+ break;
+
+ case CMD_DEL_DMAP:
+ {
+ k5_delete_dmap(hwnd, d);
+
+ return TRUE;
+ }
+ break;
+ }
+ break;
+
+ case WM_DESTROY:
+ if (d->hm_realms_ctx)
+ DestroyMenu(d->hm_realms_ctx);
+ if (d->hm_kdc_ctx)
+ DestroyMenu(d->hm_kdc_ctx);
+ if (d->hm_dmap_ctx)
+ DestroyMenu(d->hm_dmap_ctx);
+
+ d->hm_realms_ctx = NULL;
+ d->hm_kdc_ctx = NULL;
+ d->hm_dmap_ctx = NULL;
+ break;
+
+ case KHUI_WM_CFG_NOTIFY:
+ /* the realms dialog receives this notification after the top
+ level krb5 configuration panel has received it. Therefore,
+ we assume that any changes have already been applied. When
+ applying changes, we switch the mod bits off to indicate
+ that the changes have been written. We just have to
+ repaint the screen at this point. */
+ if (HIWORD(wParam) == WMCFG_APPLY) {
+ k5_purge_config_data(d, TRUE, TRUE, TRUE);
+ k5_update_realms_display(GetDlgItem(hwnd, IDC_CFG_REALMS), d);
+ if (d->c_realm != -1) {
+ k5_update_kdcs_display(GetDlgItem(hwnd, IDC_CFG_KDC), d, d->c_realm);
+ k5_update_dmap_display(GetDlgItem(hwnd, IDC_CFG_DMAP), d, d->c_realm);
+ } else {
+ k5_update_kdcs_display(GetDlgItem(hwnd, IDC_CFG_KDC), NULL, 0);
+ k5_update_dmap_display(GetDlgItem(hwnd, IDC_CFG_DMAP), NULL, 0);
+ }
+ }
+ break;
+ }
+ return FALSE;
+}
+
+void
+k5_register_config_panels(void) {
+ khui_config_node node;
+ khui_config_node_reg reg;
+ wchar_t wshort[KHUI_MAXCCH_SHORT_DESC];
+ wchar_t wlong[KHUI_MAXCCH_LONG_DESC];
+
+ ZeroMemory(&reg, sizeof(reg));
+
+ LoadString(hResModule, IDS_K5CFG_SHORT_DESC,
+ wshort, ARRAYLENGTH(wshort));
+ LoadString(hResModule, IDS_K5CFG_LONG_DESC,
+ wlong, ARRAYLENGTH(wlong));
+
+ reg.name = L"Kerberos5";
+ reg.short_desc = wshort;
+ reg.long_desc = wlong;
+ reg.h_module = hResModule;
+ reg.dlg_template = MAKEINTRESOURCE(IDD_CONFIG);
+ reg.dlg_proc = k5_config_dlgproc;
+ reg.flags = 0;
+
+ khui_cfg_register(NULL, &reg);
+
+ if (KHM_FAILED(khui_cfg_open(NULL, L"Kerberos5", &node))) {
+ node = NULL;
+#ifdef DEBUG
+ assert(FALSE);
+#endif
+ }
+
+ ZeroMemory(&reg, sizeof(reg));
+
+ LoadString(hResModule, IDS_K5RLM_SHORT_DESC,
+ wshort, ARRAYLENGTH(wshort));
+ LoadString(hResModule, IDS_K5RLM_LONG_DESC,
+ wlong, ARRAYLENGTH(wlong));
+
+ reg.name = L"KerberosRealms";
+ reg.short_desc = wshort;
+ reg.long_desc = wlong;
+ reg.h_module = hResModule;
+ reg.dlg_template = MAKEINTRESOURCE(IDD_CFG_REALMS);
+ reg.dlg_proc = k5_realms_dlgproc;
+ reg.flags = 0;
+
+ khui_cfg_register(node, &reg);
+
+ ZeroMemory(&reg, sizeof(reg));
+
+ LoadString(hResModule, IDS_K5CCC_SHORT_DESC,
+ wshort, ARRAYLENGTH(wshort));
+ LoadString(hResModule, IDS_K5CCC_LONG_DESC,
+ wlong, ARRAYLENGTH(wlong));
+
+ reg.name = L"KerberosCCaches";
+ reg.short_desc = wshort;
+ reg.long_desc = wlong;
+ reg.h_module = hResModule;
+ reg.dlg_template = MAKEINTRESOURCE(IDD_CFG_CACHES);
+ reg.dlg_proc = k5_ccconfig_dlgproc;
+ reg.flags = 0;
+
+ khui_cfg_register(node, &reg);
+
+ khui_cfg_release(node);
+
+ if (KHM_FAILED(khui_cfg_open(NULL, L"KhmIdentities", &node))) {
+ node = NULL;
+#ifdef DEBUG
+ assert(FALSE);
+#endif
+ }
+
+ ZeroMemory(&reg, sizeof(reg));
+
+ LoadString(hResModule, IDS_K5CFG_IDS_SHORT_DESC,
+ wshort, ARRAYLENGTH(wshort));
+ LoadString(hResModule, IDS_K5CFG_IDS_LONG_DESC,
+ wlong, ARRAYLENGTH(wlong));
+
+ reg.name = L"KerberosIdentities";
+ reg.short_desc = wshort;
+ reg.long_desc = wlong;
+ reg.h_module = hResModule;
+ reg.dlg_template = MAKEINTRESOURCE(IDD_CFG_IDS_TAB);
+ reg.dlg_proc = k5_ids_tab_dlgproc;
+ reg.flags = KHUI_CNFLAG_SUBPANEL;
+
+ khui_cfg_register(node, &reg);
+
+ ZeroMemory(&reg, sizeof(reg));
+
+ LoadString(hResModule, IDS_K5CFG_ID_SHORT_DESC,
+ wshort, ARRAYLENGTH(wshort));
+ LoadString(hResModule, IDS_K5CFG_ID_LONG_DESC,
+ wlong, ARRAYLENGTH(wlong));
+
+ reg.name = L"KerberosIdentitiesPlural";
+ reg.short_desc = wshort;
+ reg.long_desc = wlong;
+ reg.h_module = hResModule;
+ reg.dlg_template = MAKEINTRESOURCE(IDD_CFG_ID_TAB);
+ reg.dlg_proc = k5_id_tab_dlgproc;
+ reg.flags = KHUI_CNFLAG_SUBPANEL | KHUI_CNFLAG_PLURAL;
+
+ khui_cfg_register(node, &reg);
+
+ khui_cfg_release(node);
+}
+
+void
+k5_unregister_config_panels(void) {
+ khui_config_node node_main;
+ khui_config_node node_realms;
+ khui_config_node node_ids;
+ khui_config_node node_tab;
+ khui_config_node node_ccaches;
+
+ if (KHM_FAILED(khui_cfg_open(NULL, L"Kerberos5", &node_main))) {
+ node_main = NULL;
+#ifdef DEBUG
+ assert(FALSE);
+#endif
+ }
+
+ if (KHM_SUCCEEDED(khui_cfg_open(node_main, L"KerberosRealms",
+ &node_realms))) {
+ khui_cfg_remove(node_realms);
+ khui_cfg_release(node_realms);
+ } else {
+#ifdef DEBUG
+ assert(FALSE);
+#endif
+ }
+
+ if (KHM_SUCCEEDED(khui_cfg_open(node_main, L"KerberosCCaches",
+ &node_ccaches))) {
+ khui_cfg_remove(node_ccaches);
+ khui_cfg_release(node_ccaches);
+ }
+#ifdef DEBUG
+ else
+ assert(FALSE);
+#endif
+
+ if (node_main) {
+ khui_cfg_remove(node_main);
+ khui_cfg_release(node_main);
+ }
+
+ if (KHM_FAILED(khui_cfg_open(NULL, L"KhmIdentities", &node_ids))) {
+ node_ids = NULL;
+#ifdef DEBUG
+ assert(FALSE);
+#endif
+ }
+
+ if (KHM_SUCCEEDED(khui_cfg_open(node_ids, L"KerberosIdentities", &node_tab))) {
+ khui_cfg_remove(node_tab);
+ khui_cfg_release(node_tab);
+ }
+ if (KHM_SUCCEEDED(khui_cfg_open(node_ids, L"KerberosIdentitiesPlural", &node_tab))) {
+ khui_cfg_remove(node_tab);
+ khui_cfg_release(node_tab);
+ }
+
+ if (node_ids)
+ khui_cfg_release(node_ids);
+}
diff --git a/src/windows/identity/plugins/krb5/krb5configid.c b/src/windows/identity/plugins/krb5/krb5configid.c
index a4e549d3d..ccc38941a 100644
--- a/src/windows/identity/plugins/krb5/krb5configid.c
+++ b/src/windows/identity/plugins/krb5/krb5configid.c
@@ -45,6 +45,13 @@ typedef struct tag_k5_id_dlg_data {
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;
@@ -94,6 +101,36 @@ k5_id_read_params(k5_id_dlg_data * d) {
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)) {
@@ -120,13 +157,30 @@ k5_id_read_params(k5_id_dlg_data * d) {
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)
+
+ 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;
}
@@ -147,6 +201,8 @@ k5_id_write_params(HWND hw, k5_id_dlg_data * d) {
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;
@@ -174,6 +230,32 @@ k5_id_write_params(HWND hw, k5_id_dlg_data * d) {
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)) &&
@@ -225,6 +307,19 @@ k5_id_tab_dlgproc(HWND hwnd,
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:
diff --git a/src/windows/identity/plugins/krb5/krb5funcs.c b/src/windows/identity/plugins/krb5/krb5funcs.c
index 5c076951a..af2d997c8 100644
--- a/src/windows/identity/plugins/krb5/krb5funcs.c
+++ b/src/windows/identity/plugins/krb5/krb5funcs.c
@@ -203,6 +203,8 @@ int com_addr(void)
#define ENCTYPE_LOCAL_RC4_MD4 0xFFFFFF80
#endif
+#define MAX_ADDRS 256
+
static long get_tickets_from_cache(krb5_context ctx,
krb5_ccache cache)
{
@@ -223,7 +225,6 @@ static long get_tickets_from_cache(krb5_context ctx,
FILETIME ft, eft;
khm_int32 ti;
-
#ifdef KRB5_TC_NOTICKET
flags = KRB5_TC_NOTICKET;
#else
@@ -442,30 +443,33 @@ static long get_tickets_from_cache(krb5_context ctx,
kcdb_cred_set_attr(cred, KCDB_ATTR_LOCATION, wcc_name,
KCDB_CBSIZE_AUTO);
- /*TODO: going here */
-#if 0
if ( KRBv5Credentials.addresses && KRBv5Credentials.addresses[0] ) {
- int n = 0;
- while ( KRBv5Credentials.addresses[n] )
- n++;
- list->addrList = PCALLOC(1, n * sizeof(char *));
- if (!list->addrList) {
- MessageBox(NULL, "Memory Error", "Error", MB_OK);
- return ENOMEM;
- }
- list->addrCount = n;
- for ( n=0; n<list->addrCount; n++ ) {
- wsprintf(Buffer, "Address: %s", one_addr(KRBv5Credentials.addresses[n]));
- list->addrList[n] = (char*) PCALLOC(1, strlen(Buffer)+1);
- if (!list->addrList[n])
- {
- MessageBox(NULL, "Memory Error", "Error", MB_OK);
- return ENOMEM;
- }
- strcpy(list->addrList[n], Buffer);
- }
+ 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);
}
-#endif
if(cred_flags & KCDB_CRED_FLAG_INITIAL) {
FILETIME ft_issue_new;
@@ -597,10 +601,16 @@ khm_krb5_list_tickets(krb5_context *krbv5Context)
ctx = (*krbv5Context);
for(i=0; pNCi[i]; i++) {
+ char ccname[KRB5_MAXCCH_CCNAME];
+
if (pNCi[i]->vers != CC_CRED_V5)
continue;
- code = (*pkrb5_cc_resolve)(ctx, pNCi[i]->name, &cache);
+ if (FAILED(StringCchPrintfA(ccname, sizeof(ccname), "API:%s",
+ pNCi[i]->name)))
+ continue;
+
+ code = (*pkrb5_cc_resolve)(ctx, ccname, &cache);
if (code)
continue;
@@ -668,7 +678,49 @@ _exit:
}
int
-khm_krb5_renew(khm_handle identity)
+khm_krb5_renew_cred(khm_handle cred)
+{
+ khm_handle identity = NULL;
+ krb5_error_code code = 0;
+ krb5_context ctx = 0;
+ krb5_ccache cc = 0;
+
+ 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;
+
+ /* TODO: going here */
+
+ _cleanup:
+
+ if (identity)
+ kcdb_identity_release(identity);
+
+ if (cc && ctx)
+ pkrb5_cc_close(ctx, cc);
+
+ if (ctx)
+ pkrb5_free_context(ctx);
+
+ return code;
+}
+
+int
+khm_krb5_renew_ident(khm_handle identity)
{
krb5_error_code code = 0;
krb5_context ctx = 0;
@@ -771,24 +823,67 @@ khm_krb5_kinit(krb5_context alt_ctx,
if (!pkrb5_init_context)
return 0;
+ _reportf(L"In khm_krb5_kinit");
+
pkrb5_get_init_creds_opt_init(&options);
memset(&my_creds, 0, sizeof(my_creds));
- if (alt_ctx)
- {
+ if (alt_ctx) {
ctx = alt_ctx;
- }
- else
- {
+ } else {
code = pkrb5_init_context(&ctx);
- if (code) goto cleanup;
+ if (code)
+ goto cleanup;
}
-// code = pkrb5_cc_default(ctx, &cc);
- if (ccache)
+ if (ccache) {
+ _reportf(L"Using supplied ccache name %S", ccache);
code = pkrb5_cc_resolve(ctx, ccache, &cc);
- else
- code = pkrb5_cc_resolve(ctx, principal_name, &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);
@@ -803,55 +898,57 @@ khm_krb5_kinit(krb5_context alt_ctx,
if (lifetime)
pkrb5_get_init_creds_opt_set_tkt_life(&options, lifetime);
+
pkrb5_get_init_creds_opt_set_forwardable(&options,
forwardable ? 1 : 0);
pkrb5_get_init_creds_opt_set_proxiable(&options,
proxiable ? 1 : 0);
pkrb5_get_init_creds_opt_set_renew_life(&options,
renew_life);
+
if (addressless)
pkrb5_get_init_creds_opt_set_address_list(&options,NULL);
else {
- if (publicIP)
- {
- // we are going to add the public IP address specified by the user
- // to the list provided by the operating system
- krb5_address ** local_addrs=NULL;
- DWORD netIPAddr;
-
- pkrb5_os_localaddr(ctx, &local_addrs);
- while ( local_addrs[i++] );
- addr_count = i + 1;
-
- addrs = (krb5_address **) 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);
- }
+ 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);
- }
+ 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);
+ 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);
@@ -865,27 +962,31 @@ khm_krb5_kinit(krb5_context alt_ctx,
netIPAddr = htonl(publicIP);
memcpy(addrs[i]->contents,&netIPAddr,4);
-
- pkrb5_get_init_creds_opt_set_address_list(&options,addrs);
-
}
+
+ 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);
+ 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:
@@ -1157,7 +1258,8 @@ khm_krb5_destroy_by_credset(khm_handle p_cs)
kcdb_credset_get_size(d_cs, &s);
if (s == 0) {
- /* nothing to do */
+ _reportf(L"No tickets to delete");
+
kcdb_credset_delete(d_cs);
return 0;
}
@@ -1215,6 +1317,8 @@ khm_krb5_destroy_by_credset(khm_handle p_cs)
char a_ccname[KRB5_MAXCCH_CCNAME];
krb5_ccache cc = NULL;
+ _reportf(L"Destroying ccache [%s]", ccname);
+
UnicodeStrToAnsi(a_ccname,
sizeof(a_ccname),
ccname);
@@ -1228,7 +1332,7 @@ khm_krb5_destroy_by_credset(khm_handle p_cs)
code = pkrb5_cc_destroy(ctx, cc);
if (code) {
- /*TODO: report error */
+ _reportf(L"krb5_cc_destroy returns code %d", code);
}
_delete_this_set:
@@ -1280,6 +1384,8 @@ khm_krb5_destroy_by_credset(khm_handle p_cs)
&cb)))
goto _done_with_this_cred;
+ _reportf(L"Looking at ccache [%s]", ccname);
+
UnicodeStrToAnsi(a_ccname,
sizeof(a_ccname),
ccname);
@@ -1315,6 +1421,8 @@ khm_krb5_destroy_by_credset(khm_handle p_cs)
&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));
@@ -1740,7 +1848,8 @@ readstring(FILE * file, char * buf, int len)
\return The string with the list of realms or NULL if the
operation fails.
*/
-wchar_t * khm_krb5_get_realm_list(void)
+wchar_t *
+khm_krb5_get_realm_list(void)
{
wchar_t * rlist = NULL;
@@ -1865,7 +1974,8 @@ wchar_t * khm_krb5_get_realm_list(void)
Returns NULL if the operation fails.
*/
-wchar_t * khm_krb5_get_default_realm(void)
+wchar_t *
+khm_krb5_get_default_realm(void)
{
wchar_t * realm;
size_t cch;
@@ -1914,7 +2024,8 @@ khm_krb5_set_default_realm(wchar_t * realm) {
return rv;
}
-wchar_t * khm_get_realm_from_princ(wchar_t * princ) {
+wchar_t *
+khm_get_realm_from_princ(wchar_t * princ) {
wchar_t * t;
if(!princ)
diff --git a/src/windows/identity/plugins/krb5/krb5funcs.h b/src/windows/identity/plugins/krb5/krb5funcs.h
index 6c2c3eb6b..d69950836 100644
--- a/src/windows/identity/plugins/krb5/krb5funcs.h
+++ b/src/windows/identity/plugins/krb5/krb5funcs.h
@@ -84,8 +84,11 @@ 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(khm_handle identity);
+khm_krb5_renew_ident(khm_handle identity);
wchar_t *
khm_krb5_get_default_realm(void);
diff --git a/src/windows/identity/plugins/krb5/krb5identpro.c b/src/windows/identity/plugins/krb5/krb5identpro.c
index 2ad904b43..f12e6a9b9 100644
--- a/src/windows/identity/plugins/krb5/krb5identpro.c
+++ b/src/windows/identity/plugins/krb5/krb5identpro.c
@@ -74,6 +74,7 @@ set_identity_from_ui(khui_new_creds * nc,
khm_size cch_left;
khm_handle ident;
LRESULT idx = CB_ERR;
+ khm_int32 rv = KHM_ERROR_SUCCESS;
cch = GetWindowTextLength(d->hw_username);
@@ -91,23 +92,34 @@ set_identity_from_ui(khui_new_creds * nc,
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)
+ if (cch == 0 || cch >= cch_left) {
+ rv = KHM_ERROR_INVALID_NAME;
goto _set_null_ident;
+ }
GetWindowText(d->hw_realm, realm, (int) cch_left);
_set_ident:
- if (KHM_FAILED(kcdb_identity_create(un,
- KCDB_IDENT_FLAG_CREATE,
- &ident)))
+ if (KHM_FAILED(rv = kcdb_identity_create(un,
+ KCDB_IDENT_FLAG_CREATE,
+ &ident))) {
goto _set_null_ident;
+ }
khui_cw_set_primary_id(nc, ident);
@@ -115,7 +127,37 @@ set_identity_from_ui(khui_new_creds * nc,
return;
_set_null_ident:
- khui_cw_set_primary_id(nc, NULL);
+ {
+ 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;
}
@@ -957,9 +999,9 @@ k5_ident_update_apply_proc(khm_handle cred,
khm_handle ident = NULL;
khm_int32 t;
khm_int32 flags;
- __int64 t_expire;
- __int64 t_cexpire;
- __int64 t_rexpire;
+ FILETIME t_expire;
+ FILETIME t_cexpire;
+ FILETIME t_rexpire;
khm_size cb;
khm_int32 rv = KHM_ERROR_SUCCESS;
@@ -980,24 +1022,26 @@ k5_ident_update_apply_proc(khm_handle cred,
KCDB_ATTR_EXPIRE,
NULL,
&t_cexpire,
- &cb))) {
- t_expire = 0;
- cb = sizeof(t_expire);
- if (KHM_FAILED(kcdb_identity_get_attr(tident,
- KCDB_ATTR_EXPIRE,
- NULL,
- &t_expire,
- &cb)) ||
- (t_cexpire > t_expire))
- kcdb_identity_set_attr(tident, KCDB_ATTR_EXPIRE,
- &t_cexpire, sizeof(t_cexpire));
- } else {
- kcdb_identity_set_attr(tident, KCDB_ATTR_EXPIRE, NULL, 0);
+ &cb))) {
+ cb = sizeof(t_expire);
+ if (KHM_FAILED(kcdb_identity_get_attr(tident,
+ KCDB_ATTR_EXPIRE,
+ NULL,
+ &t_expire,
+ &cb)) ||
+ CompareFileTime(&t_cexpire, &t_expire) > 0) {
+ goto update_identity;
+ }
}
- } else {
- goto _cleanup;
}
+ goto _cleanup;
+
+ update_identity:
+
+ kcdb_identity_set_attr(tident, KCDB_ATTR_EXPIRE,
+ &t_cexpire, sizeof(t_cexpire));
+
cb = sizeof(ccname);
if (KHM_SUCCEEDED(kcdb_cred_get_attr(cred, KCDB_ATTR_LOCATION,
NULL,
diff --git a/src/windows/identity/plugins/krb5/krb5main.c b/src/windows/identity/plugins/krb5/krb5main.c
index d324857fe..ee85355a0 100644
--- a/src/windows/identity/plugins/krb5/krb5main.c
+++ b/src/windows/identity/plugins/krb5/krb5main.c
@@ -94,10 +94,12 @@ KHMEXP khm_int32 KHMAPI init_module(kmm_module h_module) {
ZeroMemory(&pi, sizeof(pi));
pi.name = KRB5_PLUGIN_NAME;
pi.type = KHM_PITYPE_CRED;
- pi.icon = NULL; /*TODO: Assign icon */
+ 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);
@@ -105,7 +107,8 @@ KHMEXP khm_int32 KHMAPI init_module(kmm_module h_module) {
ZeroMemory(&pi, sizeof(pi));
pi.name = KRB5_IDENTPRO_NAME;
pi.type = KHM_PITYPE_IDENT;
- pi.icon = NULL; /* ignored */
+ 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;
@@ -157,7 +160,7 @@ KHMEXP khm_int32 KHMAPI init_module(kmm_module h_module) {
type.cb_min = 0;
type.cb_max = 0;
type.isValid = tdata->isValid;
- type.comp = tdata->comp;
+ type.comp = addr_list_comp;
type.dup = tdata->dup;
type.toString = addr_list_toString;
@@ -206,7 +209,7 @@ KHMEXP khm_int32 KHMAPI init_module(kmm_module h_module) {
attrib.name = ATTRNAME_KEY_ENCTYPE;
attrib.id = KCDB_ATTR_INVALID;
attrib.type = type_id_enctype;
- attrib.flags = 0;
+ 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;
@@ -232,7 +235,7 @@ KHMEXP khm_int32 KHMAPI init_module(kmm_module h_module) {
attrib.name = ATTRNAME_TKT_ENCTYPE;
attrib.id = KCDB_ATTR_INVALID;
attrib.type = type_id_enctype;
- attrib.flags = 0;
+ 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;
@@ -258,7 +261,7 @@ KHMEXP khm_int32 KHMAPI init_module(kmm_module h_module) {
attrib.name = ATTRNAME_ADDR_LIST;
attrib.id = KCDB_ATTR_INVALID;
attrib.type = type_id_addr_list;
- attrib.flags = 0;
+ 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;
@@ -284,7 +287,7 @@ KHMEXP khm_int32 KHMAPI init_module(kmm_module h_module) {
attrib.name = ATTRNAME_KRB5_FLAGS;
attrib.id = KCDB_ATTR_INVALID;
attrib.type = type_id_krb5_flags;
- attrib.flags = 0;
+ attrib.flags = KCDB_ATTR_FLAG_TRANSIENT;
LoadString(hResModule, IDS_KRB5_FLAGS_SHORT_DESC, sbuf, ARRAYLENGTH(sbuf));
attrib.short_desc = sbuf;
attrib.long_desc = NULL;
@@ -309,7 +312,9 @@ KHMEXP khm_int32 KHMAPI init_module(kmm_module h_module) {
attrib.name = ATTRNAME_KRB5_CCNAME;
attrib.id = KCDB_ATTR_INVALID;
attrib.type = KCDB_TYPE_STRING;
- attrib.flags = KCDB_ATTR_FLAG_PROPERTY;
+ 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;
diff --git a/src/windows/identity/plugins/krb5/krb5newcreds.c b/src/windows/identity/plugins/krb5/krb5newcreds.c
index e6bf6479d..c89653779 100644
--- a/src/windows/identity/plugins/krb5/krb5newcreds.c
+++ b/src/windows/identity/plugins/krb5/krb5newcreds.c
@@ -30,6 +30,8 @@
#include<strsafe.h>
#include<krb5.h>
+#include<commctrl.h>
+
#include<assert.h>
extern LPVOID k5_main_fiber;
@@ -41,8 +43,10 @@ typedef struct k5_dlg_data_t {
khui_tracker tc_lifetime;
khui_tracker tc_renew;
- BOOL dirty;
-
+ 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;
@@ -99,9 +103,9 @@ k5_handle_wm_destroy(HWND hwnd,
d = (k5_dlg_data *) (LONG_PTR)
GetWindowLongPtr(hwnd, DWLP_USER);
-#ifdef DEBUG
- assert(d);
-#endif
+
+ if (!d)
+ return TRUE;
khui_cw_find_type(d->nc, credtype_id_krb5, &nct);
@@ -154,29 +158,31 @@ k5_handle_wmnc_notify(HWND hwnd,
return TRUE;
/* need to update the controls with d->* */
- if(d->renewable) {
- SendDlgItemMessage(hwnd, IDC_NCK5_RENEWABLE,
- BM_SETCHECK, BST_CHECKED,
- 0);
- EnableWindow(GetDlgItem(hwnd, IDC_NCK5_RENEW_EDIT),
- TRUE);
- } else {
- SendDlgItemMessage(hwnd, IDC_NCK5_RENEWABLE,
- BM_SETCHECK, BST_UNCHECKED, 0);
- EnableWindow(GetDlgItem(hwnd, IDC_NCK5_RENEW_EDIT),
- FALSE);
- }
+ 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);
- if(d->forwardable) {
- SendDlgItemMessage(hwnd, IDC_NCK5_FORWARDABLE,
- BM_SETCHECK, BST_CHECKED, 0);
- } else {
- SendDlgItemMessage(hwnd, IDC_NCK5_FORWARDABLE,
- BM_SETCHECK, BST_UNCHECKED, 0);
- }
+ 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);
}
break;
@@ -280,15 +286,45 @@ k5_handle_wmnc_notify(HWND hwnd,
d = (k5_dlg_data *)(LONG_PTR)
GetWindowLongPtr(hwnd, DWLP_USER);
- if(d->dirty) {
+ if(!d->sync) {
kmq_post_sub_msg(k5_sub, KMSG_CRED,
KMSG_CRED_DIALOG_NEW_OPTIONS,
0, (void *) d->nc);
- /* the above notification effectively takes
- all our changes into account. The data we
- have is no longer dirty */
- d->dirty = FALSE;
+ /* the above notification effectively takes all our
+ changes into account. The data we have is no
+ longer out of sync */
+ d->sync = FALSE;
+ }
+ }
+ 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;
@@ -298,6 +334,32 @@ k5_handle_wmnc_notify(HWND hwnd,
}
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)
@@ -323,9 +385,10 @@ k5_handle_wm_command(HWND hwnd,
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_RENEWABLE,
+ c = (int) SendDlgItemMessage(hwnd, IDC_NCK5_FORWARDABLE,
BM_GETCHECK, 0, 0);
if(c==BST_CHECKED) {
d->forwardable = TRUE;
@@ -333,6 +396,26 @@ k5_handle_wm_command(HWND hwnd,
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 &&
@@ -414,6 +497,9 @@ k5_nc_dlg_proc(HWND hwnd,
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);
}
@@ -464,19 +550,19 @@ k5_kinit_fiber_proc(PVOID lpParameter)
}
}
- g_fjob.code = khm_krb5_kinit(
- 0,
- g_fjob.principal,
- g_fjob.password,
- g_fjob.ccache,
- g_fjob.lifetime,
- g_fjob.forwardable,
- g_fjob.proxiable,
- (g_fjob.renewable ? g_fjob.renew_life : 0),
- g_fjob.addressless,
- g_fjob.publicIP,
- k5_kinit_prompter,
- &g_fjob);
+ g_fjob.code =
+ khm_krb5_kinit(0,
+ g_fjob.principal,
+ g_fjob.password,
+ g_fjob.ccache,
+ g_fjob.lifetime,
+ g_fjob.forwardable,
+ g_fjob.proxiable,
+ (g_fjob.renewable ? g_fjob.renew_life : 0),
+ g_fjob.addressless,
+ g_fjob.publicIP,
+ k5_kinit_prompter,
+ &g_fjob);
}
_switch_to_main:
@@ -1027,6 +1113,7 @@ k5_read_dlg_params(khm_handle conf,
khc_read_int32(conf, L"Forwardable", &d->forwardable);
khc_read_int32(conf, L"Proxiable", &d->proxiable);
khc_read_int32(conf, L"Addressless", &d->addressless);
+ khc_read_int32(conf, L"PublicIP", &d->publicIP);
khc_read_int32(conf, L"DefaultLifetime", &i);
d->tc_lifetime.current = i;
@@ -1079,6 +1166,7 @@ k5_write_dlg_params(khm_handle conf,
khc_write_int32(conf, L"Forwardable", d->forwardable);
khc_write_int32(conf, L"Proxiable", d->proxiable);
khc_write_int32(conf, L"Addressless", d->addressless);
+ khc_write_int32(conf, L"PublicIP", d->publicIP);
khc_write_int32(conf, L"DefaultLifetime",
(khm_int32) d->tc_lifetime.current);
@@ -1117,6 +1205,9 @@ k5_prep_kinit_job(khui_new_creds * nc)
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);
@@ -1141,7 +1232,7 @@ k5_prep_kinit_job(khui_new_creds * nc)
g_fjob.renewable = d->renewable;
g_fjob.renew_life = (krb5_deltat) d->tc_renew.current;
g_fjob.addressless = d->addressless;
- g_fjob.publicIP = 0;
+ g_fjob.publicIP = d->publicIP;
g_fjob.code = 0;
g_fjob.identity = ident;
g_fjob.prompt_set = 0;
@@ -1238,7 +1329,8 @@ k5_find_tgt_filter(khm_handle cred,
&cident)) &&
cident == ident &&
KHM_SUCCEEDED(kcdb_cred_get_flags(cred, &f)) &&
- (f & KCDB_CRED_FLAG_INITIAL))
+ (f & KCDB_CRED_FLAG_INITIAL) &&
+ !(f & KCDB_CRED_FLAG_EXPIRED))
rv = 1;
else
rv = 0;
@@ -1406,7 +1498,9 @@ k5_msg_cred_dialog(khm_int32 msg_type,
hasn't changed the options */
khui_cw_lock_nc(nc);
- if(!d->dirty && nc->n_identities > 0 &&
+ /* ?: 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) {
khm_handle h_id = NULL;
@@ -1648,7 +1742,9 @@ k5_msg_cred_dialog(khm_int32 msg_type,
assert(g_fjob.state == FIBER_STATE_NONE);
#endif
g_fjob.code = 0;
- } else if (nc->result == KHUI_NC_RESULT_GET_CREDS) {
+
+ _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);
@@ -1666,7 +1762,7 @@ k5_msg_cred_dialog(khm_int32 msg_type,
if (nc->result == KHUI_NC_RESULT_CANCEL) {
/* nothing to report */
g_fjob.code = 0;
- } else if (nc->result == KHUI_NC_RESULT_GET_CREDS) {
+ } 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 */
@@ -1694,8 +1790,10 @@ k5_msg_cred_dialog(khm_int32 msg_type,
k5_find_tgt_filter,
nc->identities[0],
NULL,
- NULL))))
+ NULL)))) {
+ _reportf(L"No password entered, but a valid TGT exists. Continuing");
g_fjob.code = 0;
+ }
if(g_fjob.code != 0) {
wchar_t tbuf[1024];
@@ -1722,7 +1820,7 @@ k5_msg_cred_dialog(khm_int32 msg_type,
assert(g_fjob.state == FIBER_STATE_NONE);
#endif
- } else if (nc->result == KHUI_NC_RESULT_GET_CREDS &&
+ } else if (nc->result == KHUI_NC_RESULT_PROCESS &&
g_fjob.state == FIBER_STATE_NONE) {
khm_handle sp = NULL;
khm_handle ep = NULL;
@@ -1734,6 +1832,8 @@ k5_msg_cred_dialog(khm_int32 msg_type,
khm_size cb_ms;
khm_int32 rv;
+ _reportf(L"Tickets successfully acquired");
+
r = KHUI_NC_RESPONSE_SUCCESS |
KHUI_NC_RESPONSE_EXIT;
@@ -1770,6 +1870,7 @@ k5_msg_cred_dialog(khm_int32 msg_type,
khm_krb5_list_tickets(&ctx);
if (nc->set_default) {
+ _reportf(L"Setting default identity");
kcdb_identity_set_default(nc->identities[0]);
}
@@ -1781,6 +1882,7 @@ k5_msg_cred_dialog(khm_int32 msg_type,
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]);
}
}
@@ -1957,10 +2059,29 @@ k5_msg_cred_dialog(khm_int32 msg_type,
if (nc->ctx.scope == KHUI_SCOPE_IDENT ||
(nc->ctx.scope == KHUI_SCOPE_CREDTYPE &&
- nc->ctx.cred_type == credtype_id_krb5)) {
+ 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.identity != 0) {
+ 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);
@@ -1970,12 +2091,17 @@ k5_msg_cred_dialog(khm_int32 msg_type,
&ftidexp,
&cb);
- code = khm_krb5_renew(nc->ctx.identity);
+ 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);
@@ -2035,7 +2161,7 @@ k5_msg_cred_dialog(khm_int32 msg_type,
_end_task();
} else if (nc->subtype == KMSG_CRED_PASSWORD &&
- nc->result == KHUI_NC_RESULT_GET_CREDS) {
+ nc->result == KHUI_NC_RESULT_PROCESS) {
_begin_task(0);
_report_mr0(KHERR_NONE, MSG_CTX_PASSWD);
diff --git a/src/windows/identity/plugins/krb5/krb5plugin.c b/src/windows/identity/plugins/krb5/krb5plugin.c
index e58e69f34..7c5287769 100644
--- a/src/windows/identity/plugins/krb5/krb5plugin.c
+++ b/src/windows/identity/plugins/krb5/krb5plugin.c
@@ -134,23 +134,21 @@ k5_msg_system(khm_int32 msg_type, khm_int32 msg_subtype,
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(credtype_id_krb5 >= 0) {
+ /* basically just unregister the credential type */
+ kcdb_credtype_unregister(credtype_id_krb5);
- if(k5_main_fiber != NULL) {
+ /* 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
-#if CLEANUP_FIBERS_ON_EXIT
+#ifdef CLEANUP_FIBERS_ON_EXIT
DeleteFiber(k5_kinit_fiber);
CloseHandle(k5_kinit_fiber);
#endif
@@ -158,7 +156,6 @@ k5_msg_system(khm_int32 msg_type, khm_int32 msg_subtype,
}
k5_main_fiber = NULL;
-
}
if(k5_sub != NULL) {
@@ -200,9 +197,16 @@ k5_msg_cred(khm_int32 msg_type, khm_int32 msg_subtype,
khui_action_context * ctx;
ctx = (khui_action_context *) vparam;
-
- if (ctx->credset)
+
+ 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;
diff --git a/src/windows/identity/plugins/krb5/krbconfig.csv b/src/windows/identity/plugins/krb5/krbconfig.csv
index 9b849c88f..49da4f2df 100644
--- a/src/windows/identity/plugins/krb5/krbconfig.csv
+++ b/src/windows/identity/plugins/krb5/krbconfig.csv
@@ -13,9 +13,10 @@ Krb5Cred,KC_SPACE,0,Kerberos V Credentials Provider
DefaultLifetime,KC_INT32,36000,Default ticket lifetime
MaxLifetime,KC_INT32,86400,Maximum lifetime
MinLifetime,KC_INT32,60,Minimum lifetime
- Forwardable,KC_INT32,1,Obtain forwardable tickets (boolean)
+ Forwardable,KC_INT32,0,Obtain forwardable tickets (boolean)
Proxiable,KC_INT32,0,Obtain proxiable tickets (boolean)
Addressless,KC_INT32,1,Obtain addressless tickets (boolean)
+ PublicIP,KC_INT32,0,Additional public IP address to use (int32)
Renewable,KC_INT32,1,Obtain renewable tickets (boolean)
DefaultRenewLifetime,KC_INT32,604800,Default renewable lifetime
MaxRenewLifetime,KC_INT32,2592000,Maximum renewable lifetime
diff --git a/src/windows/identity/plugins/krb5/krbcred.h b/src/windows/identity/plugins/krb5/krbcred.h
index 7ab035c8c..3e64b0077 100644
--- a/src/windows/identity/plugins/krb5/krbcred.h
+++ b/src/windows/identity/plugins/krb5/krbcred.h
@@ -180,6 +180,8 @@ extern fiber_job g_fjob; /* global fiber job object */
#define FIBER_STATE_NONE 0
#define FIBER_STATE_KINIT 1
+#define K5_SET_CRED_MSG WMNC_USER
+
void
k5_pp_begin(khui_property_sheet * s);
diff --git a/src/windows/identity/plugins/krb5/lang/en_us/langres.rc b/src/windows/identity/plugins/krb5/lang/en_us/langres.rc
index d54fc101e..c54bdb4b1 100644
--- a/src/windows/identity/plugins/krb5/lang/en_us/langres.rc
+++ b/src/windows/identity/plugins/krb5/lang/en_us/langres.rc
@@ -58,6 +58,8 @@ STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD | WS_CLIPSIBLINGS |
EXSTYLE WS_EX_CONTROLPARENT
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
+ CONTROL "Kerberos 5 Ticket Options",IDC_STATIC,"Static",
+ SS_LEFTNOWORDWRAP | SS_SUNKEN | WS_GROUP,7,7,286,11
LTEXT "Realm",IDC_STATIC,7,25,52,13
COMBOBOX IDC_NCK5_REALM,60,25,233,17,CBS_DROPDOWN |
CBS_AUTOHSCROLL | CBS_SORT | WS_VSCROLL | WS_TABSTOP
@@ -71,8 +73,12 @@ BEGIN
CONTROL "Can be &forwarded to other machines",
IDC_NCK5_FORWARDABLE,"Button",BS_AUTOCHECKBOX |
BS_NOTIFY | WS_TABSTOP,7,107,132,12
- CONTROL "Kerberos 5 Ticket Options",IDC_STATIC,"Static",
- SS_LEFTNOWORDWRAP | SS_SUNKEN | WS_GROUP,7,7,286,11
+ CONTROL "Addressless",IDC_NCK5_ADDRESS,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,7,128,54,10
+ LTEXT "Additional IP address",IDC_STATIC,118,129,68,8,NOT
+ WS_VISIBLE
+ CONTROL "",IDC_NCK5_PUBLICIP,"SysIPAddress32",NOT WS_VISIBLE |
+ WS_TABSTOP,193,125,100,15
END
IDD_PP_KRB5C DIALOGEX 0, 0, 235, 156
@@ -129,18 +135,19 @@ BEGIN
LTEXT "Default Realm",IDC_CFG_LBL_REALM,13,9,46,8
COMBOBOX IDC_CFG_DEFREALM,76,7,166,30,CBS_DROPDOWN | CBS_SORT |
WS_VSCROLL | WS_TABSTOP
- PUSHBUTTON "Configure Realms ...",IDC_CFG_CFGREALMS,76,25,84,14,
- WS_DISABLED
+ PUSHBUTTON "Configure Realms ...",IDC_CFG_CFGREALMS,76,25,84,14,NOT
+ WS_VISIBLE | WS_DISABLED
GROUPBOX "Keberos Configuration File",IDC_CFG_CFGFILEGRP,7,45,241,
61
LTEXT "Location",IDC_CFG_LBL_CFGFILE,13,61,28,8
EDITTEXT IDC_CFG_CFGFILE,76,58,119,14,ES_AUTOHSCROLL
PUSHBUTTON "Browse...",IDC_CFG_BROWSE,198,58,44,14
CONTROL "Create file if missing",IDC_CFG_CREATECONFIG,"Button",
- BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,76,76,80,10
+ BS_AUTOCHECKBOX | NOT WS_VISIBLE | WS_DISABLED |
+ WS_TABSTOP,76,90,80,10
CONTROL "Include realms in New Credentials realm list",
IDC_CFG_INCREALMS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,
- 76,91,153,10
+ 76,78,153,10
GROUPBOX "Windows® Options",IDC_CFG_WINGRP,7,110,241,65
LTEXT "Hostname",IDC_CFG_LBL_HOSTNAME,13,123,33,8
EDITTEXT IDC_CFG_HOSTNAME,76,120,166,14,ES_AUTOHSCROLL |
@@ -200,11 +207,19 @@ FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
LTEXT "Ticket lifetime",IDC_CFG_LBL_DEFLIFE,7,10,44,8
EDITTEXT IDC_CFG_DEFLIFE,91,7,137,14,ES_AUTOHSCROLL
- LTEXT "Ticket renewable lifetime",IDC_CFG_LBL_DEFRLIFE,7,29,80,
- 8
- EDITTEXT IDC_CFG_DEFRLIFE,91,26,137,14,ES_AUTOHSCROLL
- LTEXT "Credentials cache",IDC_STATIC,7,63,58,8
- EDITTEXT IDC_CFG_CCACHE,91,60,137,14,ES_AUTOHSCROLL
+ CONTROL "Renewable for",IDC_CFG_RENEW,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,7,41,63,10
+ EDITTEXT IDC_CFG_DEFRLIFE,91,39,137,14,ES_AUTOHSCROLL
+ CONTROL "Can be forwarded to other machines",IDC_CFG_FORWARD,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,59,133,10
+ CONTROL "Addressless",IDC_CFG_ADDRESSLESS,"Button",
+ BS_AUTOCHECKBOX | WS_TABSTOP,7,77,54,10
+ LTEXT "Additional IP address",IDC_STATIC,91,78,68,8,NOT
+ WS_VISIBLE
+ CONTROL "",IDC_CFG_PUBLICIP,"SysIPAddress32",NOT WS_VISIBLE |
+ WS_TABSTOP,128,89,100,15
+ LTEXT "Credentials cache",IDC_STATIC,7,132,58,8
+ EDITTEXT IDC_CFG_CCACHE,91,130,137,14,ES_AUTOHSCROLL
END
IDD_NC_KRB5_PASSWORD DIALOGEX 0, 0, 300, 166
@@ -226,18 +241,19 @@ STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_SYSMENU
EXSTYLE WS_EX_CONTROLPARENT
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
- GROUPBOX "File Caches",IDC_CFG_FCGRP,7,38,241,137
+ GROUPBOX "File Caches",IDC_CFG_FCGRP,7,26,241,149
CONTROL "",IDC_CFG_FCLIST,"SysListView32",LVS_REPORT |
LVS_SORTASCENDING | LVS_ALIGNLEFT | WS_BORDER |
- WS_TABSTOP,13,48,229,86
+ WS_TABSTOP,13,37,229,97
EDITTEXT IDC_CFG_FCNAME,13,139,173,14,ES_AUTOHSCROLL
PUSHBUTTON "&Browse ...",IDC_CFG_BROWSE,192,139,50,14
PUSHBUTTON "Add",IDC_CFG_ADD,13,156,50,14
PUSHBUTTON "Remove Selected",IDC_CFG_REMOVE,88,156,80,14
- CHECKBOX "Include all API: credentials caches",IDC_CFG_INCAPI,13,
- 7,125,10
+ CONTROL "Include all API: credentials caches",IDC_CFG_INCAPI,
+ "Button",BS_AUTOCHECKBOX | NOT WS_VISIBLE | WS_TABSTOP,
+ 123,7,125,10
CONTROL "Include Windows LSA cache (MSLSA:)",IDC_CFG_INCMSLSA,
- "Button",BS_AUTOCHECKBOX | WS_TABSTOP,13,22,136,10
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,13,7,136,10
END
@@ -396,7 +412,7 @@ STRINGTABLE
BEGIN
IDS_KRB4_SHORT_DESC "Kerberos 4"
IDS_KRB4_LONG_DESC "Kerberos 4 tickets"
- IDS_KRB5_FLAGS_SHORT_DESC "Flags"
+ IDS_KRB5_FLAGS_SHORT_DESC "Krb5 Flags"
IDS_RENEW_TILL_SHORT_DESC "Renew Till"
IDS_RENEW_TILL_LONG_DESC "Renewable Till"
IDS_RENEW_FOR_SHORT_DESC "Renew for"
@@ -484,6 +500,27 @@ BEGIN
IDS_CFG_RE_NEWSERVER "<New server...>"
IDS_CFG_RE_NEWDMAP "<New domain mapping...>"
IDS_KRB5_NC_NAME "Kerberos 5"
+ IDS_NCERR_IDENT_TOO_LONG "The identity name is too long."
+ IDS_NCERR_IDENT_INVALID "The identity name is invalid."
+ IDS_NCERR_IDENT_UNKNOWN "An unknown error occurred while validating the identity name."
+ IDS_CFG_RE_ARNUT "Can't add new realm %s"
+ IDS_CFG_RE_ARNUM "The new realm name %s can't be added because there is already a realm with the same name listed. Please type another name."
+ IDS_CFG_RE_ASNUT "Can't add new server %s for realm %s"
+ IDS_CFG_RE_ASNUM "There already is a server named %s for realm %s. The new server can not be added."
+ IDS_CFG_RE_DMNUT "Can't add new domain map %s for realm %s"
+END
+
+STRINGTABLE
+BEGIN
+ IDS_CFG_RE_DMNUM "There already is a domain named %s mapping to realm %s. The new domain map could not be added."
+ IDS_CFG_RE_MNR "&Add new realm"
+ IDS_CFG_RE_MDR "&Remove realm"
+ IDS_CFG_RE_MNK "&Add new server"
+ IDS_CFG_RE_MDK "&Remove server"
+ IDS_CFG_RE_MAK "Toggle a&dmin server"
+ IDS_CFG_RE_MMK "Toggle &master KDC"
+ IDS_CFG_RE_MND "&Add new domain mapping"
+ IDS_CFG_RE_MDD "&Remove domain mapping"
END
#endif // English (U.S.) resources
diff --git a/src/windows/identity/plugins/krb5/lang/krb5_msgs.mc b/src/windows/identity/plugins/krb5/lang/krb5_msgs.mc
index 2b637ac9f..01e01761f 100644
--- a/src/windows/identity/plugins/krb5/lang/krb5_msgs.mc
+++ b/src/windows/identity/plugins/krb5/lang/krb5_msgs.mc
@@ -151,6 +151,11 @@ Language=English
This is commonly caused by an incorrect password. Please verify that the password is correct and note that passwords are case sensitive.
.
+MessageId=
+SymbolicName=MSG_ERR_CTX_DESTROY_CREDS
+Language=English
+Destroying Krb5 tickets
+.
MessageId=
SymbolicName=MSG_
diff --git a/src/windows/identity/plugins/krb5/langres.h b/src/windows/identity/plugins/krb5/langres.h
index 6f76cc56b..edda7dd02 100644
--- a/src/windows/identity/plugins/krb5/langres.h
+++ b/src/windows/identity/plugins/krb5/langres.h
@@ -1,6 +1,6 @@
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
-// Used by D:\work\pismere\athena\auth\krb5\src\windows\identity\plugins\krb5\lang\en_us\langres.rc
+// 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
@@ -115,6 +115,23 @@
#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 IDC_NCK5_RENEWABLE 1002
#define IDC_NCK5_FORWARDABLE 1004
#define IDC_NCK5_REALM 1005
@@ -172,16 +189,24 @@
#define IDC_CFG_INCAPI 1066
#define IDC_CFG_INCMSLSA 1067
#define IDC_PPK5_FLAGS 1072
-#define IDC_CHECK1 1073
#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 ID_FOO_BAR 40001
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
-#define _APS_NEXT_RESOURCE_VALUE 117
-#define _APS_NEXT_COMMAND_VALUE 40001
-#define _APS_NEXT_CONTROL_VALUE 1074
+#define _APS_NEXT_RESOURCE_VALUE 118
+#define _APS_NEXT_COMMAND_VALUE 40002
+#define _APS_NEXT_CONTROL_VALUE 1079
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif
diff --git a/src/windows/identity/plugins/krb5/version.rc b/src/windows/identity/plugins/krb5/version.rc
index 10b16dd29..ec58aa90b 100644
--- a/src/windows/identity/plugins/krb5/version.rc
+++ b/src/windows/identity/plugins/krb5/version.rc
@@ -26,6 +26,28 @@
#include<netidmgr_intver.h>
+#ifndef LANGVER
+
+#define STR_FILEDESC "Kerberos 5 Plugin for NetIDMgr"
+#define STR_INTNAME "krb5cred"
+#define STR_ORIGNAME "krb5cred.dll"
+
+#else
+
+#ifdef LANG_en_us
+
+#define STR_FILEDESC "English(US) language resources for the Keberos 5 plugin"
+#define STR_INTNAME "krb5cred_en_us"
+#define STR_ORIGNAME "krb5cred_en_us.dll"
+
+#else
+
+#error Unknown langugae
+
+#endif
+
+#endif
+
1 VERSIONINFO
FILEVERSION KH_VERSION_LIST
PRODUCTVERSION KH_VERSION_LIST
@@ -40,20 +62,22 @@
BLOCK "040904b0"
{
VALUE "CompanyName", KH_VERSTR_COMPANY_1033
- VALUE "FileDescription", "Kerberos 5 plugin for NetIDMgr"
+ VALUE "FileDescription", STR_FILEDESC
VALUE "FileVersion", KH_VERSTR_VERSION_1033
- VALUE "InternalName", "krb5cred"
+ VALUE "InternalName", STR_INTNAME
VALUE "LegalCopyright", KH_VERSTR_COPYRIGHT_1033
- VALUE "OriginalFilename", "krb5cred.dll"
+ VALUE "OriginalFilename", STR_ORIGNAME
VALUE "ProductName", "NetIDMgr"
VALUE "ProductVersion", KH_VERSTR_PRODUCT_1033
#ifdef KH_VERSTR_COMMENT_1033
VALUE "Comment", KH_VERSTR_COMMENT_1033
#endif
+#ifndef LANGVER
VALUE NIMV_MODULE, "MITKrb5"
VALUE NIMV_PLUGINS, "Krb5Cred,Krb5Ident"
VALUE NIMV_APIVER, KH_VERSION_STRINGAPI
VALUE NIMV_SUPPORT, "http://web.mit.edu/kerberos"
+#endif
}
}