From: Tom Yu Date: Wed, 8 Nov 2006 23:45:00 +0000 (+0000) Subject: pull up r18767 from trunk X-Git-Tag: krb5-1.6-alpha1~13 X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=a577113cba357c5d82fa73a8e7f27b7357b90792;p=krb5.git pull up r18767 from trunk r18767@cathode-dark-space: jaltman | 2006-11-08 04:58:49 -0500 ticket:new tags: pullup subject: commits for KFW 3.1 Beta 3 KfW 3.1 beta 3 (NetIDMgr 1.1.4.0) source for 1.1.4.0 - Eliminate unused commented out code. nidmgr32.dll (1.1.4.0) - The configuration provider was incorrectly handling the case where a configuration value also specifies a configuration path, resulting in the configuration value not being found. Fixed. - Fix a race condition when refreshing identities where removing an identity during a refresh cycle may a crash. - Fix a bug which would cause an assertion to fail if an item was removed from one of the system defined menus. - When creating an indirect UI context, khui_context_create() will correctly fill up a credential set using the selected credentials. krb5cred.dll (1.1.4.0) - Fix a race condition during new credentials acquisition which may cause the Krb5 plug-in to abandon a call to krb5_get_init_creds_password() and make another call unnecessarily. - If krb5_get_init_creds_password() KRB5KDC_ERR_KEY_EXP, the new credentials dialog will automatically prompt for a password change instead of notifying the user that the password needs to be changed. - When handling WMNC_DIALOG_PREPROCESS messages, the plug-in thread would only be notified of any changes to option if the user confirmed the new credentials operation instead of cancelling it. - Additional debug output for the DEBUG build. - Reset the sync flag when reloading new credentials options for an identity. Earlier, the flag was not being reset, which can result in the new credentials dialog not obtaining credentials using the new options. - Handle the case where the new credentials dialog maybe closed during the plug-in thread is processing a request. - Fix a condition which would cause the Krb5 plug-in to clear the custom prompts even if Krb5 was not the identity provider. - Once a password is changed, use the new password to obtain new credentials for the identity. netidmgr.exe (1.1.4.0) - Fix a redraw issue which left areas of the credentials window unupdated if another window was dragged across it. - Handle WM_PRINTCLIENT messages so that the NetIDMgr window will support window animation and other features that require a valid WM_PRINTCLIENT handler. - During window repaints, NetIDMgr will no longer invoke the default window procedure. - Add support for properly activating and bringing the NetIDMgr window to the foreground when necessary. If the window cannot be brought to the foreground, it will flash the window to notify the user that she needs to manually activate the NetIDMgr window. - When a new credentials dialog is launched as a result of an external application requesting credentials, if the NetIDMgr application is not minimized, it will be brought to the foreground before the new credentials dialog is brought to the foreground. Earlier, the new credentials dialog may remain hidden behind other windows in some circumstances. - When displaying custom prompts for the new credentials dialog, align the input controls on the right. ticket: 4667 git-svn-id: svn://anonsvn.mit.edu/krb5/branches/krb5-1-6@18779 dc483132-0cff-0310-8789-dd5450dbe970 --- diff --git a/src/windows/identity/Makefile b/src/windows/identity/Makefile index 1ed267d2e..e8fb50190 100644 --- a/src/windows/identity/Makefile +++ b/src/windows/identity/Makefile @@ -181,7 +181,13 @@ afsplugin: plugincommon $(ECHO) -- Done with $@ !endif -finale: krb5plugin doc +!ifdef NODOCBUILD +doctarget= +!else +doctarget=doc +!endif + +finale: krb5plugin $(doctarget) $(ECHO) -- Done. pdoc: diff --git a/src/windows/identity/config/Makefile.w2k b/src/windows/identity/config/Makefile.w2k index dbc2690cd..9e62821ba 100644 --- a/src/windows/identity/config/Makefile.w2k +++ b/src/windows/identity/config/Makefile.w2k @@ -47,7 +47,7 @@ KHIMAIRA_WIN32_CONFIG=1 # Version info NETIDMGR_VERSION_MAJOR=1 NETIDMGR_VERSION_MINOR=1 -NETIDMGR_VERSION_PATCH=2 +NETIDMGR_VERSION_PATCH=4 NETIDMGR_VERSION_AUX=0 NETIDMGR_RELEASEDESC= diff --git a/src/windows/identity/config/Makefile.w32 b/src/windows/identity/config/Makefile.w32 index 7d259d19c..c63ed0d11 100644 --- a/src/windows/identity/config/Makefile.w32 +++ b/src/windows/identity/config/Makefile.w32 @@ -47,7 +47,7 @@ KHIMAIRA_WIN32_CONFIG=1 # Version info NETIDMGR_VERSION_MAJOR=1 NETIDMGR_VERSION_MINOR=1 -NETIDMGR_VERSION_PATCH=2 +NETIDMGR_VERSION_PATCH=4 NETIDMGR_VERSION_AUX=0 NETIDMGR_RELEASEDESC= diff --git a/src/windows/identity/doc/main_page.h b/src/windows/identity/doc/main_page.h index 238ce3e6c..415a8e3f3 100644 --- a/src/windows/identity/doc/main_page.h +++ b/src/windows/identity/doc/main_page.h @@ -76,11 +76,6 @@ NetIDMgr was developed at the Massachusetts Institute of Technology. - (Contributor list goes here) - - At the moment, no contributers have come forward to accept - responsibility. - Information Services and Technology at Massachusetts Institute of Technology diff --git a/src/windows/identity/kconfig/api.c b/src/windows/identity/kconfig/api.c index 190b59e07..b3b4eb691 100644 --- a/src/windows/identity/kconfig/api.c +++ b/src/windows/identity/kconfig/api.c @@ -866,11 +866,6 @@ khc_open_space(khm_handle parent, const wchar_t * cspace, khm_int32 flags, end = wcschr(str, L'\\'); /* safe because cspace was validated above */ -#if 0 - if(!end) - end = wcschr(str, L'/'); /* safe because cspace was - validated above */ -#endif } if(!end) { @@ -886,11 +881,7 @@ khc_open_space(khm_handle parent, const wchar_t * cspace, khm_int32 flags, rv = khcint_open_space(p, str, end - str, flags, &c); - if(KHM_SUCCEEDED(rv) && (*end == L'\\' -#if 0 - || *end == L'/' -#endif - )) { + if(KHM_SUCCEEDED(rv) && (*end == L'\\')) { khcint_space_release(p); p = c; c = NULL; @@ -951,11 +942,7 @@ khc_read_string(khm_handle pconf, int i; - if(wcschr(pvalue, L'\\') -#if 0 - || wcschr(pvalue, L'/') -#endif - ) { + if((value = wcsrchr(pvalue, L'\\')) != NULL) { if(KHM_FAILED(khc_open_space( pconf, @@ -965,15 +952,14 @@ khc_read_string(khm_handle pconf, goto _shadow; free_space = 1; -#if 0 - const wchar_t * back, * forward; - - back = wcsrchr(pvalue, L'\\'); - forward = wcsrchr(pvalue, L'/'); - value = (back > forward)?back:forward; /* works for nulls too */ -#else - value = wcsrchr(pvalue, L'\\'); + + if (value) { + value++; + } else { +#ifdef DEBUG + assert(FALSE); #endif + } } else { value = pvalue; conf = pconf; @@ -1115,11 +1101,7 @@ khc_read_int32(khm_handle pconf, const wchar_t * pvalue, khm_int32 * buf) { int i; - if(wcschr(pvalue, L'\\') -#if 0 - || wcschr(pvalue, L'/') -#endif - ) { + if((value = wcsrchr(pvalue, L'\\')) != NULL) { if(KHM_FAILED(khc_open_space( pconf, pvalue, @@ -1127,15 +1109,14 @@ khc_read_int32(khm_handle pconf, const wchar_t * pvalue, khm_int32 * buf) { &conf))) goto _shadow; free_space = 1; -#if 0 - const wchar_t * back, * forward; - - back = wcsrchr(pvalue, L'\\'); - forward = wcsrchr(pvalue, L'/'); - value = (back > forward)?back:forward; -#else - value = wcsrchr(pvalue, L'\\'); + + if (value) { + value++; + } else { +#ifdef DEBUG + assert(FALSE); #endif + } } else { value = pvalue; conf = pconf; @@ -1235,11 +1216,7 @@ khc_read_int64(khm_handle pconf, const wchar_t * pvalue, khm_int64 * buf) { int i; - if(wcschr(pvalue, L'\\') -#if 0 - || wcschr(pvalue, L'/') -#endif - ) { + if((value = wcsrchr(pvalue, L'\\')) != NULL) { if(KHM_FAILED(khc_open_space( pconf, pvalue, @@ -1247,15 +1224,14 @@ khc_read_int64(khm_handle pconf, const wchar_t * pvalue, khm_int64 * buf) { &conf))) goto _shadow; free_space = 1; -#if 0 - const wchar_t * back, *forward; - - back = wcsrchr(pvalue, L'\\'); - forward = wcsrchr(pvalue, L'/'); - value = (back > forward)?back:forward; -#else - value = wcsrchr(pvalue, L'\\'); + + if (value) { + value++; + } else { +#ifdef DEBUG + assert(FALSE); #endif + } } else { value = pvalue; conf = pconf; @@ -1354,11 +1330,7 @@ khc_read_binary(khm_handle pconf, const wchar_t * pvalue, int free_space = 0; khm_handle conf = NULL; - if(wcschr(pvalue, L'\\') -#if 0 - || wcschr(pvalue, L'/') -#endif - ) { + if((value = wcsrchr(pvalue, L'\\')) != NULL) { if(KHM_FAILED(khc_open_space( pconf, pvalue, @@ -1366,15 +1338,14 @@ khc_read_binary(khm_handle pconf, const wchar_t * pvalue, &conf))) goto _shadow; free_space = 1; -#if 0 - const wchar_t * back, *forward; - - back = wcsrchr(pvalue, L'\\'); - forward = wcsrchr(pvalue, L'/'); - value = (back > forward)?back:forward; -#else - value = wcsrchr(pvalue, L'\\'); + + if (value) { + value++; + } else { +#ifdef DEBUG + assert(FALSE); #endif + } } else { value = pvalue; conf = pconf; @@ -1515,25 +1486,20 @@ khc_write_string(khm_handle pconf, } } - if(wcschr(pvalue, L'\\') -#if 0 - || wcschr(pvalue, L'/') -#endif - ) { + if((value = wcsrchr(pvalue, L'\\')) != NULL) { if(KHM_FAILED(khc_open_space(pconf, pvalue, KCONF_FLAG_TRAILINGVALUE | (pconf?khc_handle_flags(pconf):0), &conf))) return KHM_ERROR_INVALID_PARAM; free_space = 1; -#if 0 - const wchar_t * back, *forward; - - back = wcsrchr(pvalue, L'\\'); - forward = wcsrchr(pvalue, L'/'); - value = (back > forward)?back:forward; -#else - value = wcsrchr(pvalue, L'\\'); + + if (value) { + value ++; + } else { +#ifdef DEBUG + assert(FALSE); #endif + } } else { value = pvalue; conf = pconf; @@ -1594,11 +1560,7 @@ khc_write_int32(khm_handle pconf, } } - if(wcschr(pvalue, L'\\') -#if 0 - || wcschr(pvalue, L'/') -#endif - ) { + if((value = wcsrchr(pvalue, L'\\')) != NULL) { if(KHM_FAILED(khc_open_space( pconf, pvalue, @@ -1606,15 +1568,14 @@ khc_write_int32(khm_handle pconf, &conf))) return KHM_ERROR_INVALID_PARAM; free_space = 1; -#if 0 - const wchar_t * back, *forward; - - back = wcsrchr(pvalue, L'\\'); - forward = wcsrchr(pvalue, L'/'); - value = (back > forward)?back:forward; -#else - value = wcsrchr(pvalue, L'\\'); + + if (value) { + value ++; + } else { +#ifdef DEBUG + assert(FALSE); #endif + } } else { value = pvalue; conf = pconf; @@ -1670,11 +1631,7 @@ khc_write_int64(khm_handle pconf, const wchar_t * pvalue, khm_int64 buf) { } } - if(wcschr(pvalue, L'\\') -#if 0 - || wcschr(pvalue, L'/') -#endif - ) { + if((value = wcsrchr(pvalue, L'\\')) != NULL) { if(KHM_FAILED(khc_open_space( pconf, pvalue, @@ -1682,15 +1639,14 @@ khc_write_int64(khm_handle pconf, const wchar_t * pvalue, khm_int64 buf) { &conf))) return KHM_ERROR_INVALID_PARAM; free_space = 1; -#if 0 - const wchar_t * back, *forward; - - back = wcsrchr(pvalue, L'\\'); - forward = wcsrchr(pvalue, L'/'); - value = (back > forward)?back:forward; -#else - value = wcsrchr(pvalue, L'\\'); + + if (value) { + value ++; + } else { +#ifdef DEBUG + assert(FALSE); #endif + } } else { value = pvalue; conf = pconf; @@ -1739,11 +1695,7 @@ khc_write_binary(khm_handle pconf, if(pconf && !khc_is_machine_handle(pconf) && !khc_is_user_handle(pconf)) return KHM_ERROR_INVALID_OPERATION; - if(wcschr(pvalue, L'\\') -#if 0 - || wcschr(pvalue, L'/') -#endif - ) { + if((value = wcsrchr(pvalue, L'\\')) != NULL) { if(KHM_FAILED(khc_open_space( pconf, pvalue, @@ -1751,15 +1703,14 @@ khc_write_binary(khm_handle pconf, &conf))) return KHM_ERROR_INVALID_PARAM; free_space = 1; -#if 0 - const wchar_t * back, *forward; - - back = wcsrchr(pvalue, L'\\'); - forward = wcsrchr(pvalue, L'/'); - value = (back > forward)?back:forward; -#else - value = wcsrchr(pvalue, L'\\'); + + if (value) { + value ++; + } else { +#ifdef DEBUG + assert(FALSE); #endif + } } else { value = pvalue; conf = pconf; diff --git a/src/windows/identity/kcreddb/identity.c b/src/windows/identity/kcreddb/identity.c index 4236c2795..3e9f394ec 100644 --- a/src/windows/identity/kcreddb/identity.c +++ b/src/windows/identity/kcreddb/identity.c @@ -321,12 +321,6 @@ kcdb_identity_delete(khm_handle vid) { are freed. Once they are released, kcdb_identity_delete() will be called again. */ -#if 0 - EnterCriticalSection(&cs_ident); - if(id->refcount == 0) { - /*TODO: free up the identity */ - } -#endif _exit: LeaveCriticalSection(&cs_ident); @@ -804,11 +798,11 @@ kcdb_identity_refresh_all(void) { ident != NULL; ident = next) { - next = LNEXT(ident); - if (!kcdb_is_active_identity(ident) || - ident->refresh_cycle == kcdb_ident_refresh_cycle) + ident->refresh_cycle == kcdb_ident_refresh_cycle) { + next = LNEXT(ident); continue; + } kcdb_identity_hold((khm_handle) ident); @@ -818,6 +812,7 @@ kcdb_identity_refresh_all(void) { EnterCriticalSection(&cs_ident); + next = LNEXT(ident); kcdb_identity_release((khm_handle) ident); hit_count++; diff --git a/src/windows/identity/plugins/krb5/krb5newcreds.c b/src/windows/identity/plugins/krb5/krb5newcreds.c index e7641df8a..1bff68e3c 100644 --- a/src/windows/identity/plugins/krb5/krb5newcreds.c +++ b/src/windows/identity/plugins/krb5/krb5newcreds.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005 Massachusetts Institute of Technology + * Copyright (c) 2006 Secure Endpoints Inc. * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation @@ -126,6 +126,51 @@ k5_handle_wm_destroy(HWND hwnd, return TRUE; } +LRESULT +k5_force_password_change(k5_dlg_data * d) { + /* we are turning this dialog into a change password dialog... */ + wchar_t wbuf[KHUI_MAXCCH_BANNER]; + + khui_cw_clear_prompts(d->nc); + + LoadString(hResModule, IDS_NC_PWD_BANNER, + wbuf, ARRAYLENGTH(wbuf)); + khui_cw_begin_custom_prompts(d->nc, 3, NULL, wbuf); + + LoadString(hResModule, IDS_NC_PWD_PWD, + wbuf, ARRAYLENGTH(wbuf)); + khui_cw_add_prompt(d->nc, KHUI_NCPROMPT_TYPE_PASSWORD, + wbuf, NULL, KHUI_NCPROMPT_FLAG_HIDDEN); + + LoadString(hResModule, IDS_NC_PWD_NPWD, + wbuf, ARRAYLENGTH(wbuf)); + khui_cw_add_prompt(d->nc, KHUI_NCPROMPT_TYPE_NEW_PASSWORD, + wbuf, NULL, KHUI_NCPROMPT_FLAG_HIDDEN); + + LoadString(hResModule, IDS_NC_PWD_NPWD_AGAIN, + wbuf, ARRAYLENGTH(wbuf)); + khui_cw_add_prompt(d->nc, KHUI_NCPROMPT_TYPE_NEW_PASSWORD_AGAIN, + wbuf, NULL, KHUI_NCPROMPT_FLAG_HIDDEN); + + d->pwd_change = TRUE; + + if (is_k5_identpro && + d->nc->n_identities > 0 && + d->nc->identities[0]) { + + kcdb_identity_set_flags(d->nc->identities[0], + KCDB_IDENT_FLAG_VALID, + KCDB_IDENT_FLAG_VALID); + + } + + PostMessage(d->nc->hwnd, KHUI_WM_NC_NOTIFY, + MAKEWPARAM(0, WMNC_UPDATE_CREDTEXT), + (LPARAM) d->nc); + + return TRUE; +} + INT_PTR k5_handle_wmnc_notify(HWND hwnd, WPARAM wParam, @@ -151,6 +196,7 @@ k5_handle_wmnc_notify(HWND hwnd, case WMNC_DIALOG_SETUP: { k5_dlg_data * d; + BOOL old_sync; d = (k5_dlg_data *)(LONG_PTR) GetWindowLongPtr(hwnd, DWLP_USER); @@ -158,6 +204,11 @@ k5_handle_wmnc_notify(HWND hwnd, if (d->nc->subtype == KMSG_CRED_PASSWORD) return TRUE; + /* we save the value of the 'sync' field here because some + of the notifications that are generated while setting + the controls overwrite the field. */ + old_sync = d->sync; + /* need to update the controls with d->* */ SendDlgItemMessage(hwnd, IDC_NCK5_RENEWABLE, BM_SETCHECK, @@ -184,6 +235,8 @@ k5_handle_wmnc_notify(HWND hwnd, 0, d->publicIP); EnableWindow(GetDlgItem(hwnd, IDC_NCK5_PUBLICIP), !d->addressless); + + d->sync = old_sync; } break; @@ -206,47 +259,7 @@ k5_handle_wmnc_notify(HWND hwnd, l->id, l->id_len); if (!wcscmp(linktext, L"Krb5Cred:!Passwd")) { - /* we are turning this dialog into a change password dialog... */ - wchar_t wbuf[KHUI_MAXCCH_BANNER]; - - khui_cw_clear_prompts(nc); - - LoadString(hResModule, IDS_NC_PWD_BANNER, - wbuf, ARRAYLENGTH(wbuf)); - khui_cw_begin_custom_prompts(nc, 3, NULL, wbuf); - - LoadString(hResModule, IDS_NC_PWD_PWD, - wbuf, ARRAYLENGTH(wbuf)); - khui_cw_add_prompt(nc, KHUI_NCPROMPT_TYPE_PASSWORD, - wbuf, NULL, KHUI_NCPROMPT_FLAG_HIDDEN); - - LoadString(hResModule, IDS_NC_PWD_NPWD, - wbuf, ARRAYLENGTH(wbuf)); - khui_cw_add_prompt(nc, KHUI_NCPROMPT_TYPE_NEW_PASSWORD, - wbuf, NULL, KHUI_NCPROMPT_FLAG_HIDDEN); - - LoadString(hResModule, IDS_NC_PWD_NPWD_AGAIN, - wbuf, ARRAYLENGTH(wbuf)); - khui_cw_add_prompt(nc, KHUI_NCPROMPT_TYPE_NEW_PASSWORD_AGAIN, - wbuf, NULL, KHUI_NCPROMPT_FLAG_HIDDEN); - - d->pwd_change = TRUE; - - if (is_k5_identpro && - d->nc->n_identities > 0 && - d->nc->identities[0]) { - - kcdb_identity_set_flags(d->nc->identities[0], - KCDB_IDENT_FLAG_VALID, - KCDB_IDENT_FLAG_VALID); - - } - - PostMessage(d->nc->hwnd, KHUI_WM_NC_NOTIFY, - MAKEWPARAM(0, WMNC_UPDATE_CREDTEXT), - (LPARAM) d->nc); - - return TRUE; + return k5_force_password_change(d); } } break; @@ -353,15 +366,10 @@ k5_handle_wmnc_notify(HWND hwnd, d = (k5_dlg_data *)(LONG_PTR) GetWindowLongPtr(hwnd, DWLP_USER); - if(!d->sync) { + if(!d->sync && d->nc->result == KHUI_NC_RESULT_PROCESS) { kmq_post_sub_msg(k5_sub, KMSG_CRED, KMSG_CRED_DIALOG_NEW_OPTIONS, 0, (void *) d->nc); - - /* the above notification effectively takes all our - changes into account. The data we have is no - longer out of sync */ - d->sync = TRUE; } } break; @@ -617,6 +625,16 @@ k5_kinit_fiber_proc(PVOID lpParameter) } } +#ifdef DEBUG + /* log the state of g_fjob.* */ + _reportf(L"g_fjob state prior to calling khm_krb5_kinit() :"); + _reportf(L" g_fjob.principal = [%S]", g_fjob.principal); + _reportf(L" g_fjob.code = %d", g_fjob.code); + _reportf(L" g_fjob.state = %d", g_fjob.state); + _reportf(L" g_fjob.prompt_set= %d", g_fjob.prompt_set); + _reportf(L" g_fjob.valid_principal = %d", (int) g_fjob.valid_principal); +#endif + g_fjob.code = khm_krb5_kinit(0, g_fjob.principal, @@ -916,9 +934,17 @@ k5_kinit_prompter(krb5_context context, khm_size ncp; krb5_error_code code = 0; BOOL new_prompts = TRUE; - khm_handle csp_prcache = NULL; +#ifdef DEBUG + _reportf(L"k5_kinit_prompter() received %d prompts with name=[%S] banner=[%S]", + num_prompts, + name, banner); + for (i=0; i < num_prompts; i++) { + _reportf(L"Prompt[%d]: string[%S]", i, prompts[i].prompt); + } +#endif + /* we got prompts? Then we assume that the principal is valid */ g_fjob.valid_principal = TRUE; @@ -1401,6 +1427,7 @@ k5_read_dlg_params(khm_handle conf, /* once we read the new data, in, it is no longer considered dirty */ d->dirty = FALSE; + d->sync = FALSE; } void @@ -1814,6 +1841,11 @@ k5_msg_cred_dialog(khm_int32 msg_type, d = (k5_dlg_data *)(LONG_PTR) GetWindowLongPtr(nct->hwnd_panel, DWLP_USER); + /* this can be NULL if the dialog was closed while the + plug-in thread was processing. */ + if (d == NULL) + break; + if (!is_k5_identpro) { /* enumerate all realms and place in realms combo box */ @@ -1881,6 +1913,9 @@ k5_msg_cred_dialog(khm_int32 msg_type, d = (k5_dlg_data *)(LONG_PTR) GetWindowLongPtr(nct->hwnd_panel, DWLP_USER); + if (d == NULL) + break; + /* we only load the identity specific defaults if the user hasn't changed the options */ khui_cw_lock_nc(nc); @@ -1930,6 +1965,8 @@ k5_msg_cred_dialog(khm_int32 msg_type, d = (k5_dlg_data *)(LONG_PTR) GetWindowLongPtr(nct->hwnd_panel, DWLP_USER); + if (d == NULL) + break; if (nc->subtype == KMSG_CRED_PASSWORD) { khm_size n_prompts = 0; @@ -1993,6 +2030,11 @@ k5_msg_cred_dialog(khm_int32 msg_type, kcdb_identity_hold(ident); k5_prep_kinit_job(nc); + + /* after the switch to the fiber, the dialog will be + back in sync with the kinit thread. */ + d->sync = TRUE; + khui_cw_unlock_nc(nc); SwitchToFiber(k5_kinit_fiber); @@ -2001,13 +2043,25 @@ k5_msg_cred_dialog(khm_int32 msg_type, wchar_t msg[KHUI_MAXCCH_BANNER]; khm_size cb; + /* Special case. If the users' password has + expired, we force a password change dialog on + top of the new credentials dialog using a set + of custom prompts, but only if we are the + identity provider. */ + if (g_fjob.code == KRB5KDC_ERR_KEY_EXP && + is_k5_identpro) { + + k5_force_password_change(d); + goto done_with_bad_princ; + + } + /* we can't possibly have succeeded without a password */ - if(g_fjob.code) { - if (is_k5_identpro) - kcdb_identity_set_flags(ident, - KCDB_IDENT_FLAG_INVALID, - KCDB_IDENT_FLAG_INVALID); + if(g_fjob.code && is_k5_identpro) { + kcdb_identity_set_flags(ident, + KCDB_IDENT_FLAG_INVALID, + KCDB_IDENT_FLAG_INVALID); khui_cw_clear_prompts(nc); } @@ -2027,9 +2081,11 @@ k5_msg_cred_dialog(khm_int32 msg_type, break; case KRB5KDC_ERR_KEY_EXP: - /* password needs changing. */ - LoadString(hResModule, IDS_K5ERR_KEY_EXPIRED, - msg, ARRAYLENGTH(msg)); + { + /* password needs changing. */ + LoadString(hResModule, IDS_K5ERR_KEY_EXPIRED, + msg, ARRAYLENGTH(msg)); + } break; default: @@ -2060,6 +2116,8 @@ k5_msg_cred_dialog(khm_int32 msg_type, StringCbCopy(d->cred_message, cb, msg); } + done_with_bad_princ: + k5_free_kinit_job(); } else if(g_fjob.state == FIBER_STATE_KINIT) { @@ -2112,6 +2170,8 @@ k5_msg_cred_dialog(khm_int32 msg_type, if (nc->subtype == KMSG_CRED_NEW_CREDS) { d = (k5_dlg_data *) nct->aux; + if (d == NULL) + break; if (d->pwd_change) { /* we are forcing a password change */ @@ -2538,12 +2598,12 @@ k5_msg_cred_dialog(khm_int32 msg_type, if (code) rv = KHM_ERROR_UNKNOWN; - else if (nc->subtype == KMSG_CRED_NEW_CREDS) { + else { khm_handle csp_idcfg = NULL; krb5_context ctx = NULL; - /* we forced a password change. now we need - to get the initial credentials. */ + /* we set a new password. now we need to get + initial credentials. */ d = (k5_dlg_data *) nct->aux; @@ -2552,9 +2612,28 @@ k5_msg_cred_dialog(khm_int32 msg_type, goto _pwd_exit; } + if (nc->subtype == KMSG_CRED_PASSWORD) { + /* since this was just a password change, + we need to load new credentials options + from the configuration store. */ + + if (KHM_SUCCEEDED + (k5_open_config_handle(nc->identities[0], + KHM_FLAG_CREATE | + KCONF_FLAG_WRITEIFMOD, + &csp_idcfg))) { + k5_read_dlg_params(csp_idcfg, d); + khc_close_space(csp_idcfg); + csp_idcfg = NULL; + } + } + /* the password change phase is now done */ d->pwd_change = FALSE; +#ifdef DEBUG + _reportf(L"Calling khm_krb5_kinit()"); +#endif code = khm_krb5_kinit(NULL, /* context (create one) */ idname, /* principal_name */ npwd, /* new password */ @@ -2575,13 +2654,17 @@ k5_msg_cred_dialog(khm_int32 msg_type, /* save the settings that we used for obtaining the ticket. */ - if (KHM_SUCCEEDED + if (nc->subtype == KMSG_CRED_NEW_CREDS && + KHM_SUCCEEDED (k5_open_config_handle(nc->identities[0], KHM_FLAG_CREATE | KCONF_FLAG_WRITEIFMOD, &csp_idcfg))) { k5_write_dlg_params(csp_idcfg, d); khc_close_space(csp_idcfg); + + /* and then update the LRU too */ + k5_update_LRU(nc->identities[0]); } /* and do a quick refresh of the krb5 tickets @@ -2603,11 +2686,31 @@ k5_msg_cred_dialog(khm_int32 msg_type, } } - /* and then update the LRU too */ - k5_update_LRU(nc->identities[0]); - if (ctx != NULL) pkrb5_free_context(ctx); + + if (nc->subtype == KMSG_CRED_PASSWORD) { + /* if we obtained new credentials as a + result of successfully changing the + password, we also schedule an identity + renewal for this identity. This allows + the other credential types to obtain + credentials for this identity. */ + khui_action_context ctx; + + _reportf(L"Scheduling renewal of [%s] after password change", + widname); + + khui_context_create(&ctx, + KHUI_SCOPE_IDENT, + nc->identities[0], + KCDB_CREDTYPE_INVALID, + NULL); + khui_action_trigger(KHUI_ACTION_RENEW_CRED, + &ctx); + + khui_context_release(&ctx); + } } /* result is only set when code != 0 */ @@ -2629,9 +2732,6 @@ k5_msg_cred_dialog(khm_int32 msg_type, PFREE(result); PFREE(wresult); - /* leave wresult. It will get freed when the - reported event is freed. */ - /* we don't need to report anything more */ code = 0; } diff --git a/src/windows/identity/ui/credfuncs.h b/src/windows/identity/ui/credfuncs.h index 677d27945..aede41a7b 100644 --- a/src/windows/identity/ui/credfuncs.h +++ b/src/windows/identity/ui/credfuncs.h @@ -34,6 +34,9 @@ void khm_cred_destroy_creds(khm_boolean sync, khm_boolean quiet); +void +khm_cred_destroy_identity(khm_handle identity); + void khm_cred_renew_identity(khm_handle identity); diff --git a/src/windows/identity/ui/credwnd.c b/src/windows/identity/ui/credwnd.c index a870fe527..36e0572fe 100644 --- a/src/windows/identity/ui/credwnd.c +++ b/src/windows/identity/ui/credwnd.c @@ -1700,72 +1700,69 @@ cw_erase_rect(HDC hdc, BOOL rie; HBRUSH hbr; - if(RectVisible(hdc, r_erase)) { - - switch(type) { - case CW_ER_BLANK: - hbr = tbl->hb_normal; - break; - - case CW_ER_GREY: - hbr = tbl->hb_grey; - break; + switch(type) { + case CW_ER_BLANK: + hbr = tbl->hb_normal; + break; - case CW_ER_SEL: - hbr = tbl->hb_sel; - break; + case CW_ER_GREY: + hbr = tbl->hb_grey; + break; - default: - return; - } + case CW_ER_SEL: + hbr = tbl->hb_sel; + break; - if(tbl->kbm_logo_shade.cx != -1 && type == CW_ER_BLANK) { - rlogo.left = r_wnd->right - tbl->kbm_logo_shade.cx; - rlogo.right = r_wnd->right; - rlogo.top = r_wnd->bottom - tbl->kbm_logo_shade.cy; - rlogo.bottom = r_wnd->bottom; - rie = IntersectRect(&ri, r_erase, &rlogo); - } else { - ZeroMemory(&rlogo, sizeof(rlogo)); - ZeroMemory(&ri, sizeof(ri)); - rie = FALSE; - } + default: + return; + } - if(!rie) { - FillRect(hdc, r_erase, hbr); - } else { - HDC hdcb = CreateCompatibleDC(hdc); - HBITMAP hbmold = SelectObject(hdcb, tbl->kbm_logo_shade.hbmp); + if(tbl->kbm_logo_shade.cx != -1 && type == CW_ER_BLANK) { + rlogo.left = r_wnd->right - tbl->kbm_logo_shade.cx; + rlogo.right = r_wnd->right; + rlogo.top = r_wnd->bottom - tbl->kbm_logo_shade.cy; + rlogo.bottom = r_wnd->bottom; + rie = IntersectRect(&ri, r_erase, &rlogo); + } else { + ZeroMemory(&rlogo, sizeof(rlogo)); + ZeroMemory(&ri, sizeof(ri)); + rie = FALSE; + } - BitBlt(hdc, ri.left, ri.top, ri.right - ri.left, ri.bottom - ri.top, - hdcb, ri.left - rlogo.left, ri.top - rlogo.top, SRCCOPY); + if(!rie) { + FillRect(hdc, r_erase, hbr); + } else { + HDC hdcb = CreateCompatibleDC(hdc); + HBITMAP hbmold = SelectObject(hdcb, tbl->kbm_logo_shade.hbmp); + + BitBlt(hdc, ri.left, ri.top, ri.right - ri.left, ri.bottom - ri.top, + hdcb, ri.left - rlogo.left, ri.top - rlogo.top, SRCCOPY); - SelectObject(hdcb, hbmold); - DeleteDC(hdcb); - - if(r_erase->top < ri.top && r_erase->left < ri.left) { - t.left = r_erase->left; - t.top = r_erase->top; - t.right = ri.left; - t.bottom = ri.top; - FillRect(hdc, &t, hbr); - } + SelectObject(hdcb, hbmold); + DeleteDC(hdcb); + + if(r_erase->top < ri.top && r_erase->left < ri.left) { + t.left = r_erase->left; + t.top = r_erase->top; + t.right = ri.left; + t.bottom = ri.top; + FillRect(hdc, &t, hbr); + } - if(r_erase->left < ri.left) { - t.left = r_erase->left; - t.top = ri.top; - t.right = ri.left; - t.bottom = ri.bottom; - FillRect(hdc, &t, hbr); - } + if(r_erase->left < ri.left) { + t.left = r_erase->left; + t.top = ri.top; + t.right = ri.left; + t.bottom = ri.bottom; + FillRect(hdc, &t, hbr); + } - if(r_erase->top < ri.top) { - t.left = ri.left; - t.top = r_erase->top; - t.right = ri.right; - t.bottom = ri.top; - FillRect(hdc, &t, hbr); - } + if(r_erase->top < ri.top) { + t.left = ri.left; + t.top = r_erase->top; + t.right = ri.right; + t.bottom = ri.top; + FillRect(hdc, &t, hbr); } } } @@ -2322,6 +2319,7 @@ cw_wm_destroy(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) return DefWindowProc(hwnd, uMsg, wParam, lParam); } +/* handles WM_PAINT and WM_PRINTCLIENT */ LRESULT cw_wm_paint(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { @@ -2336,13 +2334,28 @@ cw_wm_paint(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) int flag_col = -1; int d_x = -1; int selected = 0; + BOOL has_dc = FALSE; tbl = (khui_credwnd_tbl *)(LONG_PTR) GetWindowLongPtr(hwnd, 0); - if(!GetUpdateRect(hwnd, &r, FALSE)) + if (wParam != 0) { + /* we assume that if wParam != 0, then that contains a device + context for us to draw in. Otherwise, we have to call + BeginPaint() to get one. */ + hdc = (HDC) wParam; + has_dc = TRUE; + } + + if(!has_dc && !GetUpdateRect(hwnd, &r, FALSE)) { +#ifdef DEBUG + assert(FALSE); +#endif goto _exit; + } + + if (!has_dc) + hdc = BeginPaint(hwnd, &ps); - hdc = BeginPaint(hwnd, &ps); if(tbl->hf_normal) hf_old = SelectFont(hdc, tbl->hf_normal); SetTextAlign(hdc, TA_LEFT | TA_TOP | TA_NOUPDATECP); @@ -2451,9 +2464,6 @@ cw_wm_paint(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) rh.left = x; rh.right = x + tbl->cols[j].width; - if(!RectVisible(hdc, &rh)) - continue; - if(!cw_is_custom_attr(tbl->cols[j].attr_id)) { if(!(tbl->rows[i].flags & KHUI_CW_ROW_HEADER)) { cw_erase_rect(hdc, tbl, &r, &rh, (selected)?CW_ER_SEL:CW_ER_BLANK); @@ -2471,7 +2481,6 @@ cw_wm_paint(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) SetTextAlign(hdc, 0); DrawText(hdc, buf, (int)((cbbuf / sizeof(wchar_t)) - 1), &rh, DT_LEFT | DT_VCENTER | DT_NOCLIP | DT_SINGLELINE | DT_END_ELLIPSIS); - //TextOut(hdc, x, y + tbl->vpad, buf, (cbbuf / sizeof(wchar_t)) - 1); } } } else { @@ -2574,9 +2583,11 @@ cw_wm_paint(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) if(tbl->hf_normal) SelectFont(hdc, hf_old); - EndPaint(hwnd,&ps); -_exit: - return DefWindowProc(hwnd, uMsg, wParam, lParam); + if (!has_dc) + EndPaint(hwnd,&ps); + + _exit: + return TRUE; } LRESULT @@ -4519,11 +4530,14 @@ khm_credwnd_proc(HWND hwnd, /* we don't bother wasting cycles erasing the background because the foreground elements completely cover the client area */ - return TRUE; + return FALSE; case WM_PAINT: return cw_wm_paint(hwnd, uMsg, wParam, lParam); + case WM_PRINTCLIENT: + return cw_wm_paint(hwnd, uMsg, wParam, lParam); + case WM_SIZE: return cw_wm_size(hwnd, uMsg, wParam, lParam); diff --git a/src/windows/identity/ui/mainwnd.c b/src/windows/identity/ui/mainwnd.c index bc9b1cec7..c03d47f1d 100644 --- a/src/windows/identity/ui/mainwnd.c +++ b/src/windows/identity/ui/mainwnd.c @@ -803,6 +803,25 @@ khm_show_main_window(void) { khm_nCmdShow = SW_RESTORE; } +void +khm_activate_main_window(void) { + + if (!SetForegroundWindow(khm_hwnd_main)) { + FLASHWINFO finfo; + + SetActiveWindow(khm_hwnd_main); + + ZeroMemory(&finfo, sizeof(finfo)); + finfo.cbSize = sizeof(finfo); + finfo.hwnd = khm_hwnd_main; + finfo.dwFlags = FLASHW_ALL; + finfo.uCount = 3; + finfo.dwTimeout = 0; + + FlashWindowEx(&finfo); + } +} + void khm_close_main_window(void) { khm_handle csp_cw; diff --git a/src/windows/identity/ui/mainwnd.h b/src/windows/identity/ui/mainwnd.h index 526248b1d..5d0bdc564 100644 --- a/src/windows/identity/ui/mainwnd.h +++ b/src/windows/identity/ui/mainwnd.h @@ -38,6 +38,7 @@ void khm_register_main_wnd_class(void); void khm_unregister_main_wnd_class(void); void khm_create_main_window_controls(HWND); void khm_create_main_window(void); +void khm_activate_main_window(void); void khm_show_main_window(void); void khm_close_main_window(void); void khm_hide_main_window(void); diff --git a/src/windows/identity/ui/newcredwnd.c b/src/windows/identity/ui/newcredwnd.c index a52d09b41..a0472e236 100644 --- a/src/windows/identity/ui/newcredwnd.c +++ b/src/windows/identity/ui/newcredwnd.c @@ -828,6 +828,13 @@ nc_handle_wm_create(HWND hwnd, &t)) && t != 0) { + /* if the main window is not visible, then the SetWindowPos() + call is sufficient to bring the new creds window to the + top. However, if the main window is visible but not + active, the main window needs to be activated before a + child window can be activated. */ + khm_activate_main_window(); + SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0, (SWP_NOMOVE | SWP_NOSIZE)); @@ -1508,6 +1515,7 @@ static LRESULT nc_handle_wm_nc_notify(HWND hwnd, HWND hw, hw_prev; HFONT hf, hfold; HDC hdc; + BOOL use_large_lables = FALSE; /* we assume that WMNC_CLEAR_PROMPTS has already been received */ @@ -1598,6 +1606,25 @@ static LRESULT nc_handle_wm_nc_notify(HWND hwnd, hdc = GetWindowDC(d->dlg_main); hfold = SelectObject(hdc,hf); + /* first do a trial run and see if we should use the + larger text labels or not. This is so that all the + labels and input controls align properly. */ + for (i=0; i < d->nc->n_prompts; i++) { + if (d->nc->prompts[i]->prompt != NULL) { + SIZE s; + + GetTextExtentPoint32(hdc, + d->nc->prompts[i]->prompt, + (int) wcslen(d->nc->prompts[i]->prompt), + &s); + + if(s.cx >= d->r_n_label.right - d->r_n_label.left) { + use_large_lables = TRUE; + break; + } + } + } + for(i=0; inc->n_prompts; i++) { RECT pr, er; SIZE s; @@ -1608,11 +1635,12 @@ static LRESULT nc_handle_wm_nc_notify(HWND hwnd, d->nc->prompts[i]->prompt, (int) wcslen(d->nc->prompts[i]->prompt), &s); - if(s.cx < d->r_n_label.right - d->r_n_label.left) { + if(s.cx < d->r_n_label.right - d->r_n_label.left && + !use_large_lables) { CopyRect(&pr, &d->r_n_label); CopyRect(&er, &d->r_n_input); dy = d->r_row.bottom; - } else if(s.cx < + } else if(s.cx < d->r_e_label.right - d->r_e_label.left) { CopyRect(&pr, &d->r_e_label); CopyRect(&er, &d->r_e_input); diff --git a/src/windows/identity/uilib/action.c b/src/windows/identity/uilib/action.c index dcce3de93..78fd3a821 100644 --- a/src/windows/identity/uilib/action.c +++ b/src/windows/identity/uilib/action.c @@ -602,6 +602,9 @@ khui_menu_insert_paction(khui_menu_def * d, khm_size idx, khui_action * paction, KHMEXP void KHMAPI khui_menu_remove_action(khui_menu_def * d, khm_size idx) { + if (!(d->state & KHUI_MENUSTATE_ALLOCD)) + menu_const_to_allocd(d); + assert(d->state & KHUI_MENUSTATE_ALLOCD); if (idx < 0 || idx >= d->n_items) @@ -1172,6 +1175,13 @@ khui_action_context khui_ctx = { NULL, 0}; +khm_int32 KHMAPI +set_cred_select_flag(khm_handle cred, void * rock) { + kcdb_cred_set_flags(cred, KCDB_CRED_FLAG_SELECTED, + KCDB_CRED_FLAG_SELECTED); + return KHM_ERROR_SUCCESS; +} + KHMEXP void KHMAPI khui_context_create(khui_action_context * ctx, khui_scope scope, @@ -1189,6 +1199,42 @@ khui_context_create(khui_action_context * ctx, tctx.cred_type = cred_type; tctx.cred = cred; + /* fill up the credset based on the scope */ + if (scope != KHUI_SCOPE_NONE) { + if (tctx.credset == NULL) + kcdb_credset_create(&tctx.credset); + else + kcdb_credset_flush(tctx.credset); + + if (scope == KHUI_SCOPE_IDENT) { + kcdb_credset_extract(tctx.credset, + NULL, + tctx.identity, + KCDB_CREDTYPE_INVALID); + } else if (scope == KHUI_SCOPE_CREDTYPE) { + kcdb_credset_extract(tctx.credset, + NULL, + tctx.identity, + tctx.cred_type); + } else if (scope == KHUI_SCOPE_CRED) { + khm_handle dupcred = NULL; + kcdb_cred_dup(cred, &dupcred); + + kcdb_credset_add_cred(tctx.credset, dupcred, -1); + } else { +#ifdef DEBUG + /* KHUI_SCOPE_GROUP is not used with + khui_context_create() */ + assert(FALSE); +#endif + } + + kcdb_credset_apply(tctx.credset, set_cred_select_flag, + NULL); + + kcdb_credset_seal(tctx.credset); + } + khuiint_copy_context(ctx, &tctx); } diff --git a/src/windows/identity/uilib/khversion.h b/src/windows/identity/uilib/khversion.h deleted file mode 100644 index d5dc36d24..000000000 --- a/src/windows/identity/uilib/khversion.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (c) 2005 Massachusetts Institute of Technology - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -/* $Id$ */ - -#ifndef __KHIMAIRA_KHUIDEFS_H -#define __KHIMAIRA_KHUIDEFS_H - - - -#endif