From: Tom Yu Date: Wed, 11 Oct 2006 19:26:08 +0000 (+0000) Subject: pull up r18670 from trunk X-Git-Tag: krb5-1.5.2-final~17 X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=6837ab2903626113afa5824c7554ae5e506d8603;p=krb5.git pull up r18670 from trunk r18670@cathode-dark-space: jaltman | 2006-10-09 14:08:10 -0400 ticket: new subject: final commits for KFW 3.1 Beta 2 tags: pullup krb5cred.dll (1.1.2.0) - Fix the control logic so that if the password is expired for an identity, the krb5 credentials provider will initiate a change password request. Once the password is successfully changed, the new password will be used to obtain new credentials. - Fix an incorrect condition which caused the new credentials dialog to refresh custom prompts unnecessarily. - Removing an identity from the list of NetIDMgr identities now causes the corresponding principal to be removed from the LRU principals list. - Properly handle KMSG_CRED_PROCESS message when the user is cancelling out. - Add more debug output - Do not renew Kerberos tickets which are not initial tickets. - Fix whitespace in source code. - When providing identity selection controls, disable the realm selector when the user specifies the realm in the username control. - k5_ident_valiate_name() will refuse principal names with empty or unspecified realms. - When updating identity properties, the identity provider will correctly set the properties for identities that were destroyed. This fixes a problem where the values may be incorrect if an identity has two or more credential caches and one of them is destroyed. nidmgr32.dll (1.1.2.0) - Send out a separate notification if the configuration information associated with an identity is removed. - If an identity is being removed from the NetIDMgr identity list in the configuration panel, do not send out APPLY notifications to the subpanels after the configuration information has been removed. Otherwise this causes the configuration information to be reinstated and prevent the identity from being removed. - Properly initialize the new credentials blob including the UI context structure. netidmgr.exe (1.1.2.0) - When suppressing error messages, make sure that the final KMSG_CRED_END notification is sent. Otherwise the new credentials acquisition operation will not be cleaned up. - Autoinit option now checks to see if there are identity credentials for the default identity and triggers the new credentials dialog if there aren't any. - Properly synchronize the configuration node list when applying changes (e.g.: when removing or adding an identity). - Fix a handle leak when removing an identity from the NetIDMgr identity list. - Refresh the properties for the active identities before calculating the renewal and expiration timers. Otherwise the timestamps being used might be incorrect. - Add Identity dialog (in the configuration panel) now uses the identity selection controls provided by the identity provider. - Improve type safety when handling timer refreshes. - When getting the expiration times and issue times for an identity, the timer refresh code may fail over to the expiration and issue times for the credential it is currently looking at. Now the code makes sure that both the issue and expiration times come from the identity or the credential but not mixed. - Not being able to get the time of issue of a credential now does not result in the credential being skipped from the timer refresh pass. However, not having a time of issue will result in the half-life algorithm not being applied for the renew timer. - Fix a bug which caused a credential to be abandoned from the timer refresh pass if the reamining lifetime of the credential is less than the renewal threshold. - Fix a bug where the vertical scroll bars for the hypertext window would not appear when the contents of the window changed. - Trigger a refresh of the configuration nodes when adding or removing an identity. source for (1.1.2.0) - Explicitly include so that the SDK can be used in build environments that define WIN32_LEAN_AND_MEAN. ticket: 4407 version_fixed: 1.5.2 git-svn-id: svn://anonsvn.mit.edu/krb5/branches/krb5-1-5@18681 dc483132-0cff-0310-8789-dd5450dbe970 --- diff --git a/src/windows/identity/apiversion.txt b/src/windows/identity/apiversion.txt index 2a49540cd..4399861e8 100644 --- a/src/windows/identity/apiversion.txt +++ b/src/windows/identity/apiversion.txt @@ -1,5 +1,4 @@ -# Copyright (c) 2004-2006 Massachusetts Institute of Technology -# Copyright (c) 2006 Secure Endpoints Inc. +# 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 @@ -213,3 +212,5 @@ Date=(TBD) !kcdb_buf_get_attrib(), kcdb_buf_get_attrib_string(), kcbd_buf_set_attrib() # attr_name is now a const pointer ++KCDB_OP_DELCONFIG +# notification that the configuration information for an identity is to be removed. diff --git a/src/windows/identity/config/Makefile b/src/windows/identity/config/Makefile index f1ac2ac67..41e29bf82 100644 --- a/src/windows/identity/config/Makefile +++ b/src/windows/identity/config/Makefile @@ -1,5 +1,6 @@ # -# Copyright (c) 2004 Massachusetts Institute of Technology +# Copyright (c) 2004,2005,2006 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 files diff --git a/src/windows/identity/config/Makefile.w2k b/src/windows/identity/config/Makefile.w2k index 0677d13c9..dbc2690cd 100644 --- a/src/windows/identity/config/Makefile.w2k +++ b/src/windows/identity/config/Makefile.w2k @@ -3,7 +3,7 @@ # This file will be included by all the makefiles # in the build tree. # -# Copyright (c) 2004,2005 Massachusetts Institute of Technology +# Copyright (c) 2004,2005,2006 Massachusetts Institute of Technology # Copyright (c) 2006 Secure Endpoints Inc. # # Permission is hereby granted, free of charge, to any person @@ -47,8 +47,8 @@ KHIMAIRA_WIN32_CONFIG=1 # Version info NETIDMGR_VERSION_MAJOR=1 NETIDMGR_VERSION_MINOR=1 -NETIDMGR_VERSION_PATCH=1 -NETIDMGR_VERSION_AUX=2 +NETIDMGR_VERSION_PATCH=2 +NETIDMGR_VERSION_AUX=0 NETIDMGR_RELEASEDESC= # The API version. This number must be incremented each time the API diff --git a/src/windows/identity/config/Makefile.w32 b/src/windows/identity/config/Makefile.w32 index 0f47bcb13..7d259d19c 100644 --- a/src/windows/identity/config/Makefile.w32 +++ b/src/windows/identity/config/Makefile.w32 @@ -47,8 +47,8 @@ KHIMAIRA_WIN32_CONFIG=1 # Version info NETIDMGR_VERSION_MAJOR=1 NETIDMGR_VERSION_MINOR=1 -NETIDMGR_VERSION_PATCH=0 -NETIDMGR_VERSION_AUX=2 +NETIDMGR_VERSION_PATCH=2 +NETIDMGR_VERSION_AUX=0 NETIDMGR_RELEASEDESC= # The API version. This number must be incremented each time the API diff --git a/src/windows/identity/kcreddb/identity.c b/src/windows/identity/kcreddb/identity.c index 15c36130f..4236c2795 100644 --- a/src/windows/identity/kcreddb/identity.c +++ b/src/windows/identity/kcreddb/identity.c @@ -617,9 +617,13 @@ kcdb_identity_get_config(khm_handle vid, &hident); if(KHM_FAILED(rv)) { + khm_int32 oldflags; EnterCriticalSection(&cs_ident); + oldflags = id->flags; id->flags &= ~KCDB_IDENT_FLAG_CONFIG; LeaveCriticalSection(&cs_ident); + if (oldflags & KCDB_IDENT_FLAG_CONFIG) + kcdbint_ident_post_message(KCDB_OP_DELCONFIG, id); goto _exit; } diff --git a/src/windows/identity/kcreddb/kcreddb.h b/src/windows/identity/kcreddb/kcreddb.h index 1b5d9b67c..060f556ac 100644 --- a/src/windows/identity/kcreddb/kcreddb.h +++ b/src/windows/identity/kcreddb/kcreddb.h @@ -3310,6 +3310,7 @@ kcdb_buf_release(khm_handle record); #define KCDB_OP_SETSEARCH 8 #define KCDB_OP_UNSETSEARCH 9 #define KCDB_OP_NEW_DEFAULT 10 +#define KCDB_OP_DELCONFIG 11 /*@}*/ diff --git a/src/windows/identity/plugins/krb5/krb5funcs.c b/src/windows/identity/plugins/krb5/krb5funcs.c index 95f9a38c6..331e789dc 100644 --- a/src/windows/identity/plugins/krb5/krb5funcs.c +++ b/src/windows/identity/plugins/krb5/krb5funcs.c @@ -702,6 +702,19 @@ khm_krb5_renew_cred(khm_handle cred) khm_boolean brenewIdentity = FALSE; khm_boolean istgt = FALSE; + khm_int32 flags; + + cbname = sizeof(wname); + kcdb_cred_get_name(cred, wname, &cbname); + _reportf(L"Krb5 renew cred for %s", wname); + + kcdb_cred_get_flags(cred, &flags); + + if (!(flags & KCDB_CRED_FLAG_INITIAL)) { + _reportf(L"Krb5 skipping renewal because this is not an initial credential"); + return 0; + } + memset(&in_creds, 0, sizeof(in_creds)); memset(&cc_creds, 0, sizeof(cc_creds)); @@ -2161,80 +2174,79 @@ khm_krb5_changepwd(char * principal, if ( !pkrb5_init_context ) goto cleanup; - if (rc = pkrb5_init_context(&context)) { - goto cleanup; - } - - if (rc = pkrb5_parse_name(context, principal, &princ)) { - goto cleanup; - } - - pkrb5_get_init_creds_opt_init(&opts); - pkrb5_get_init_creds_opt_set_tkt_life(&opts, 5*60); - pkrb5_get_init_creds_opt_set_renew_life(&opts, 0); - pkrb5_get_init_creds_opt_set_forwardable(&opts, 0); - pkrb5_get_init_creds_opt_set_proxiable(&opts, 0); - pkrb5_get_init_creds_opt_set_address_list(&opts,NULL); - - if (rc = pkrb5_get_init_creds_password(context, &creds, princ, - password, 0, 0, 0, - "kadmin/changepw", &opts)) { - if (rc == KRB5KRB_AP_ERR_BAD_INTEGRITY) { + if (rc = pkrb5_init_context(&context)) { + goto cleanup; + } + + if (rc = pkrb5_parse_name(context, principal, &princ)) { + goto cleanup; + } + + pkrb5_get_init_creds_opt_init(&opts); + pkrb5_get_init_creds_opt_set_tkt_life(&opts, 5*60); + pkrb5_get_init_creds_opt_set_renew_life(&opts, 0); + pkrb5_get_init_creds_opt_set_forwardable(&opts, 0); + pkrb5_get_init_creds_opt_set_proxiable(&opts, 0); + pkrb5_get_init_creds_opt_set_address_list(&opts,NULL); + + if (rc = pkrb5_get_init_creds_password(context, &creds, princ, + password, 0, 0, 0, + "kadmin/changepw", &opts)) { + if (rc == KRB5KRB_AP_ERR_BAD_INTEGRITY) { #if 0 - com_err(argv[0], 0, - "Password incorrect while getting initial ticket"); + com_err(argv[0], 0, + "Password incorrect while getting initial ticket"); #endif - } - else { + } else { #if 0 - com_err(argv[0], ret, "getting initial ticket"); + com_err(argv[0], ret, "getting initial ticket"); #endif - } - goto cleanup; - } + } + goto cleanup; + } - if (rc = pkrb5_change_password(context, &creds, newpassword, - &result_code, &result_code_string, - &result_string)) { + if (rc = pkrb5_change_password(context, &creds, newpassword, + &result_code, &result_code_string, + &result_string)) { #if 0 - com_err(argv[0], ret, "changing password"); + com_err(argv[0], ret, "changing password"); #endif - goto cleanup; - } - - if (result_code) { - int len = result_code_string.length + - (result_string.length ? (sizeof(": ") - 1) : 0) + - result_string.length; - if (len && error_str) { - *error_str = PMALLOC(len + 1); - if (*error_str) - StringCchPrintfA(*error_str, len+1, - "%.*s%s%.*s", - result_code_string.length, - result_code_string.data, - result_string.length?": ":"", - result_string.length, - result_string.data); - } - rc = result_code; - goto cleanup; - } + goto cleanup; + } + + if (result_code) { + int len = result_code_string.length + + (result_string.length ? (sizeof(": ") - 1) : 0) + + result_string.length; + if (len && error_str) { + *error_str = PMALLOC(len + 1); + if (*error_str) + StringCchPrintfA(*error_str, len+1, + "%.*s%s%.*s", + result_code_string.length, + result_code_string.data, + result_string.length?": ":"", + result_string.length, + result_string.data); + } + rc = result_code; + goto cleanup; + } cleanup: - if (result_string.data) - pkrb5_free_data_contents(context, &result_string); + if (result_string.data) + pkrb5_free_data_contents(context, &result_string); - if (result_code_string.data) - pkrb5_free_data_contents(context, &result_code_string); + if (result_code_string.data) + pkrb5_free_data_contents(context, &result_code_string); - if (princ) - pkrb5_free_principal(context, princ); + if (princ) + pkrb5_free_principal(context, princ); - if (context) - pkrb5_free_context(context); + if (context) + pkrb5_free_context(context); - return rc; + return rc; } khm_int32 KHMAPI diff --git a/src/windows/identity/plugins/krb5/krb5identpro.c b/src/windows/identity/plugins/krb5/krb5identpro.c index 11a7410b1..05f93fcd3 100644 --- a/src/windows/identity/plugins/krb5/krb5identpro.c +++ b/src/windows/identity/plugins/krb5/krb5identpro.c @@ -226,8 +226,10 @@ update_crossfeed(khui_new_creds * nc, un_realm = khm_get_realm_from_princ(un); - if (un_realm == NULL) + if (un_realm == NULL) { + EnableWindow(d->hw_realm, TRUE); return FALSE; + } if (ctrl_id_src == K5_NCID_UN) { @@ -270,6 +272,15 @@ update_crossfeed(khui_new_creds * nc, SetWindowText(d->hw_realm, un_realm); + if (GetFocus() == d->hw_realm) { + HWND hw_next = GetNextDlgTabItem(nc->hwnd, d->hw_realm, + FALSE); + if (hw_next) + SetFocus(hw_next); + } + + EnableWindow(d->hw_realm, FALSE); + return TRUE; } /* else... */ @@ -739,6 +750,7 @@ k5_ident_valiate_name(khm_int32 msg_type, char princ_name[KCDB_IDENT_MAXCCH_NAME]; kcdb_ident_name_xfer * nx; krb5_error_code code; + wchar_t * atsign; nx = (kcdb_ident_name_xfer *) vparam; @@ -759,11 +771,18 @@ k5_ident_valiate_name(khm_int32 msg_type, return KHM_ERROR_SUCCESS; } - if (princ != NULL) + if (princ != NULL) pkrb5_free_principal(k5_identpro_ctx, princ); - nx->result = KHM_ERROR_SUCCESS; + /* krb5_parse_name() accepts principal names with no realm or an + empty realm. We don't. */ + atsign = wcschr(nx->name_src, L'@'); + if (atsign == NULL || atsign[1] == L'\0') { + nx->result = KHM_ERROR_INVALID_NAME; + } else { + nx->result = KHM_ERROR_SUCCESS; + } return KHM_ERROR_SUCCESS; } @@ -1032,15 +1051,23 @@ k5_ident_notify_create(khm_int32 msg_type, return KHM_ERROR_SUCCESS; } +struct k5_ident_update_data { + khm_handle identity; + + FILETIME ft_expire; /* expiration */ + FILETIME ft_issue; /* issue */ + FILETIME ft_rexpire; /* renew expiration */ + wchar_t ccname[KRB5_MAXCCH_CCNAME]; + khm_int32 k5_flags; +}; + static khm_int32 KHMAPI k5_ident_update_apply_proc(khm_handle cred, void * rock) { - wchar_t ccname[KRB5_MAXCCH_CCNAME]; - khm_handle tident = (khm_handle) rock; + struct k5_ident_update_data * d = (struct k5_ident_update_data *) rock; khm_handle ident = NULL; khm_int32 t; khm_int32 flags; - FILETIME t_expire; FILETIME t_cexpire; FILETIME t_rexpire; khm_size cb; @@ -1049,12 +1076,15 @@ k5_ident_update_apply_proc(khm_handle cred, if (KHM_FAILED(kcdb_cred_get_type(cred, &t)) || t != credtype_id_krb5 || KHM_FAILED(kcdb_cred_get_identity(cred, &ident))) + return KHM_ERROR_SUCCESS; - if (!kcdb_identity_is_equal(ident,tident)) + if (!kcdb_identity_is_equal(ident,d->identity)) + goto _cleanup; if (KHM_FAILED(kcdb_cred_get_flags(cred, &flags))) + flags = 0; if (flags & KCDB_CRED_FLAG_INITIAL) { @@ -1064,13 +1094,9 @@ k5_ident_update_apply_proc(khm_handle cred, NULL, &t_cexpire, &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) { + if ((d->ft_expire.dwLowDateTime == 0 && + d->ft_expire.dwHighDateTime == 0) || + CompareFileTime(&t_cexpire, &d->ft_expire) > 0) { goto update_identity; } } @@ -1080,52 +1106,35 @@ k5_ident_update_apply_proc(khm_handle cred, update_identity: - kcdb_identity_set_attr(tident, KCDB_ATTR_EXPIRE, - &t_cexpire, sizeof(t_cexpire)); + d->ft_expire = t_cexpire; - cb = sizeof(ccname); - if (KHM_SUCCEEDED(kcdb_cred_get_attr(cred, KCDB_ATTR_LOCATION, - NULL, - ccname, - &cb))) { - kcdb_identity_set_attr(tident, attr_id_krb5_ccname, - ccname, cb); - } else { - kcdb_identity_set_attr(tident, attr_id_krb5_ccname, - NULL, 0); + cb = sizeof(d->ccname); + if (KHM_FAILED(kcdb_cred_get_attr(cred, KCDB_ATTR_LOCATION, NULL, d->ccname, &cb))) { + d->ccname[0] = L'\0'; } - - cb = sizeof(t); - if (KHM_SUCCEEDED(kcdb_cred_get_attr(cred, - attr_id_krb5_flags, - NULL, - &t, - &cb))) { - kcdb_identity_set_attr(tident, attr_id_krb5_flags, - &t, sizeof(t)); + cb = sizeof(d->k5_flags); + if (KHM_FAILED(kcdb_cred_get_attr(cred, attr_id_krb5_flags, NULL, + &d->k5_flags, &cb))) { + d->k5_flags = 0; + } - cb = sizeof(t_rexpire); - if (!(t & TKT_FLG_RENEWABLE) || - KHM_FAILED(kcdb_cred_get_attr(cred, - KCDB_ATTR_RENEW_EXPIRE, - NULL, - &t_rexpire, - &cb))) { - kcdb_identity_set_attr(tident, KCDB_ATTR_RENEW_EXPIRE, - NULL, 0); - } else { - kcdb_identity_set_attr(tident, KCDB_ATTR_RENEW_EXPIRE, - &t_rexpire, sizeof(t_rexpire)); - } - } else { - kcdb_identity_set_attr(tident, attr_id_krb5_flags, - NULL, 0); - kcdb_identity_set_attr(tident, KCDB_ATTR_RENEW_EXPIRE, - NULL, 0); + cb = sizeof(d->ft_issue); + if (KHM_FAILED(kcdb_cred_get_attr(cred, KCDB_ATTR_ISSUE, NULL, &d->ft_issue, &cb))) { + ZeroMemory(&d->ft_issue, sizeof(d->ft_issue)); } - rv = KHM_ERROR_EXIT; + cb = sizeof(t_rexpire); + if ((d->k5_flags & TKT_FLG_RENEWABLE) && + KHM_SUCCEEDED(kcdb_cred_get_attr(cred, + KCDB_ATTR_RENEW_EXPIRE, + NULL, + &t_rexpire, + &cb))) { + d->ft_rexpire = t_rexpire; + } else { + ZeroMemory(&d->ft_rexpire, sizeof(d->ft_rexpire)); + } _cleanup: if (ident) @@ -1140,6 +1149,7 @@ k5_ident_update(khm_int32 msg_type, khm_ui_4 uparam, void * vparam) { + struct k5_ident_update_data d; khm_handle ident; khm_handle tident; krb5_ccache cc = NULL; @@ -1153,9 +1163,52 @@ k5_ident_update(khm_int32 msg_type, if (ident == NULL) return KHM_ERROR_SUCCESS; + ZeroMemory(&d, sizeof(d)); + d.identity = ident; + kcdb_credset_apply(NULL, k5_ident_update_apply_proc, - (void *) ident); + (void *) &d); + + if (d.ft_expire.dwLowDateTime != 0 || + d.ft_expire.dwHighDateTime != 0) { + + /* we found a TGT */ + + kcdb_identity_set_attr(ident, KCDB_ATTR_EXPIRE, + &d.ft_expire, sizeof(d.ft_expire)); + if (d.ft_issue.dwLowDateTime != 0 || + d.ft_issue.dwHighDateTime != 0) + kcdb_identity_set_attr(ident, KCDB_ATTR_ISSUE, + &d.ft_issue, sizeof(d.ft_issue)); + else + kcdb_identity_set_attr(ident, KCDB_ATTR_ISSUE, NULL, 0); + + if (d.ft_rexpire.dwLowDateTime != 0 || + d.ft_rexpire.dwHighDateTime != 0) + kcdb_identity_set_attr(ident, KCDB_ATTR_RENEW_EXPIRE, + &d.ft_rexpire, sizeof(d.ft_rexpire)); + else + kcdb_identity_set_attr(ident, KCDB_ATTR_RENEW_EXPIRE, NULL, 0); + + kcdb_identity_set_attr(ident, attr_id_krb5_flags, + &d.k5_flags, sizeof(d.k5_flags)); + + if (d.ccname[0]) + kcdb_identity_set_attr(ident, attr_id_krb5_ccname, + d.ccname, KCDB_CBSIZE_AUTO); + else + kcdb_identity_set_attr(ident, attr_id_krb5_ccname, NULL, 0); + + } else { + /* Clear out the attributes. We don't have any information + about this identity */ + kcdb_identity_set_attr(ident, KCDB_ATTR_EXPIRE, NULL, 0); + kcdb_identity_set_attr(ident, KCDB_ATTR_ISSUE, NULL, 0); + kcdb_identity_set_attr(ident, KCDB_ATTR_RENEW_EXPIRE, NULL, 0); + kcdb_identity_set_attr(ident, attr_id_krb5_flags, NULL, 0); + kcdb_identity_set_attr(ident, attr_id_krb5_ccname, NULL, 0); + } if (KHM_SUCCEEDED(kcdb_identity_get_default(&tident))) { kcdb_identity_release(tident); diff --git a/src/windows/identity/plugins/krb5/krb5newcreds.c b/src/windows/identity/plugins/krb5/krb5newcreds.c index db9462eb6..e7641df8a 100644 --- a/src/windows/identity/plugins/krb5/krb5newcreds.c +++ b/src/windows/identity/plugins/krb5/krb5newcreds.c @@ -232,6 +232,20 @@ k5_handle_wmnc_notify(HWND hwnd, 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; } } @@ -347,7 +361,7 @@ k5_handle_wmnc_notify(HWND hwnd, /* the above notification effectively takes all our changes into account. The data we have is no longer out of sync */ - d->sync = FALSE; + d->sync = TRUE; } } break; @@ -1573,6 +1587,47 @@ k5_find_tgt_filter(khm_handle cred, return rv; } +khm_int32 +k5_remove_from_LRU(khm_handle identity) +{ + wchar_t * wbuf = NULL; + wchar_t idname[KCDB_IDENT_MAXCCH_NAME]; + khm_size cb; + khm_size cb_ms; + khm_int32 rv = KHM_ERROR_SUCCESS; + + cb = sizeof(idname); + rv = kcdb_identity_get_name(identity, idname, &cb); + assert(rv == KHM_ERROR_SUCCESS); + + rv = khc_read_multi_string(csp_params, L"LRUPrincipals", NULL, &cb_ms); + if (rv != KHM_ERROR_TOO_LONG) + cb_ms = sizeof(wchar_t) * 2; + + wbuf = PMALLOC(cb_ms); + assert(wbuf); + + cb = cb_ms; + + if (rv == KHM_ERROR_TOO_LONG) { + rv = khc_read_multi_string(csp_params, L"LRUPrincipals", wbuf, &cb); + assert(KHM_SUCCEEDED(rv)); + + if (multi_string_find(wbuf, idname, KHM_CASE_SENSITIVE) != NULL) { + multi_string_delete(wbuf, idname, KHM_CASE_SENSITIVE); + } + } else { + multi_string_init(wbuf, cb_ms); + } + + rv = khc_write_multi_string(csp_params, L"LRUPrincipals", wbuf); + + if (wbuf) + PFREE(wbuf); + + return rv; +} + khm_int32 k5_update_LRU(khm_handle identity) { @@ -1915,6 +1970,13 @@ k5_msg_cred_dialog(khm_int32 msg_type, assert(nc->subtype == KMSG_CRED_NEW_CREDS); + /* If we are forcing a password change, then we don't do + anything here. Note that if the identity changed, then + this field would have been reset, so we would proceed + as usual. */ + if (d->pwd_change) + return KHM_ERROR_SUCCESS; + /* if the fiber is already in a kinit, cancel it */ if(g_fjob.state == FIBER_STATE_KINIT) { g_fjob.command = FIBER_CMD_CANCEL; @@ -1965,7 +2027,7 @@ k5_msg_cred_dialog(khm_int32 msg_type, break; case KRB5KDC_ERR_KEY_EXP: - /* password needs changing */ + /* password needs changing. */ LoadString(hResModule, IDS_K5ERR_KEY_EXPIRED, msg, ARRAYLENGTH(msg)); break; @@ -2320,7 +2382,7 @@ k5_msg_cred_dialog(khm_int32 msg_type, kherr_suggestion sug_id; /* if we failed to get new tickets, but the - identity isstill valid, then we assume that + identity is still valid, then we assume that the current tickets are still good enough for other credential types to obtain their credentials. */ @@ -2374,7 +2436,13 @@ k5_msg_cred_dialog(khm_int32 msg_type, khui_cw_lock_nc(nc); - if (nc->n_identities == 0 || + if (nc->result == KHUI_NC_RESULT_CANCEL) { + + khui_cw_set_response(nc, credtype_id_krb5, + KHUI_NC_RESPONSE_SUCCESS | + KHUI_NC_RESPONSE_EXIT); + + } else if (nc->n_identities == 0 || nc->identities[0] == NULL) { _report_mr0(KHERR_ERROR, MSG_PWD_NO_IDENTITY); _suggest_mr(MSG_PWD_S_NO_IDENTITY, KHERR_SUGGEST_RETRY); @@ -2382,6 +2450,7 @@ k5_msg_cred_dialog(khm_int32 msg_type, khui_cw_set_response(nc, credtype_id_krb5, KHUI_NC_RESPONSE_FAILED | KHUI_NC_RESPONSE_NOEXIT); + } else { wchar_t widname[KCDB_IDENT_MAXCCH_NAME]; char idname[KCDB_IDENT_MAXCCH_NAME]; @@ -2483,9 +2552,12 @@ k5_msg_cred_dialog(khm_int32 msg_type, goto _pwd_exit; } + /* the password change phase is now done */ + d->pwd_change = FALSE; + code = khm_krb5_kinit(NULL, /* context (create one) */ idname, /* principal_name */ - npwd, /* password */ + npwd, /* new password */ NULL, /* ccache name (figure out the identity cc)*/ (krb5_deltat) d->tc_lifetime.current, d->forwardable, diff --git a/src/windows/identity/plugins/krb5/krb5plugin.c b/src/windows/identity/plugins/krb5/krb5plugin.c index 7c5287769..e80e01c47 100644 --- a/src/windows/identity/plugins/krb5/krb5plugin.c +++ b/src/windows/identity/plugins/krb5/krb5plugin.c @@ -169,6 +169,23 @@ k5_msg_system(khm_int32 msg_type, khm_int32 msg_subtype, return rv; } +khm_int32 KHMAPI +k5_msg_kcdb(khm_int32 msg_type, khm_int32 msg_subtype, + khm_ui_4 uparam, void * vparam) +{ + khm_int32 rv = KHM_ERROR_SUCCESS; + + switch(msg_subtype) { + case KMSG_KCDB_IDENT: + if (uparam == KCDB_OP_DELCONFIG) { + k5_remove_from_LRU((khm_handle) vparam); + } + break; + } + + return rv; +} + /* Handler for CRED type messages @@ -241,6 +258,8 @@ k5_msg_callback(khm_int32 msg_type, khm_int32 msg_subtype, return k5_msg_system(msg_type, msg_subtype, uparam, vparam); case KMSG_CRED: return k5_msg_cred(msg_type, msg_subtype, uparam, vparam); + case KMSG_KCDB: + return k5_msg_kcdb(msg_type, msg_subtype, uparam, vparam); } return KHM_ERROR_SUCCESS; } diff --git a/src/windows/identity/plugins/krb5/krbcred.h b/src/windows/identity/plugins/krb5/krbcred.h index f31bde4e6..694323ce3 100644 --- a/src/windows/identity/plugins/krb5/krbcred.h +++ b/src/windows/identity/plugins/krb5/krbcred.h @@ -200,6 +200,9 @@ k5_msg_ident(khm_int32 msg_type, khm_ui_4 uparam, void * vparam); +khm_int32 +k5_remove_from_LRU(khm_handle identity); + int k5_get_realm_from_nc(khui_new_creds * nc, wchar_t * buf, 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 54f3ed787..dde30e387 100644 --- a/src/windows/identity/plugins/krb5/lang/en_us/langres.rc +++ b/src/windows/identity/plugins/krb5/lang/en_us/langres.rc @@ -59,7 +59,7 @@ 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 + COMBOBOX IDC_NCK5_REALM,60,25,233,51,CBS_DROPDOWN | CBS_AUTOHSCROLL | CBS_SORT | WS_VSCROLL | WS_TABSTOP PUSHBUTTON "Specify &additional realms ...",IDC_NCK5_ADD_REALMS,181,43,112,16,BS_NOTIFY | NOT WS_VISIBLE | WS_DISABLED LTEXT "&Lifetime",IDC_STATIC,7,67,61,12 EDITTEXT IDC_NCK5_LIFETIME_EDIT,85,67,107,12,ES_AUTOHSCROLL @@ -119,7 +119,7 @@ STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_SYSMENU FONT 8, "MS Shell Dlg", 400, 0, 0x1 BEGIN LTEXT "Default Realm",IDC_CFG_LBL_REALM,13,9,46,8 - COMBOBOX IDC_CFG_DEFREALM,76,7,166,30,CBS_DROPDOWN | CBS_SORT | WS_VSCROLL | WS_TABSTOP + COMBOBOX IDC_CFG_DEFREALM,76,7,166,51,CBS_DROPDOWN | CBS_SORT | WS_VSCROLL | WS_TABSTOP 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 @@ -134,7 +134,7 @@ BEGIN LTEXT "Domain",IDC_CFG_LBL_DOMAIN,13,141,24,8 EDITTEXT IDC_CFG_DOMAIN,76,138,166,14,ES_AUTOHSCROLL | ES_READONLY LTEXT "Import tickets",IDC_LBL_IMPORT,13,158,45,8 - COMBOBOX IDC_CFG_IMPORT,76,156,166,30,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + COMBOBOX IDC_CFG_IMPORT,76,156,166,51,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP END IDD_CFG_REALMS DIALOGEX 0, 0, 255, 182 @@ -195,7 +195,7 @@ FONT 8, "MS Shell Dlg", 400, 0, 0x1 BEGIN CONTROL "Kerberos 5 Change Password Options",IDC_STATIC,"Static",SS_LEFTNOWORDWRAP | SS_SUNKEN | WS_GROUP,7,7,286,11 LTEXT "Realm",IDC_STATIC,7,25,52,13 - COMBOBOX IDC_NCK5_REALM,60,25,233,17,CBS_DROPDOWN | CBS_AUTOHSCROLL | CBS_SORT | WS_VSCROLL | WS_TABSTOP + COMBOBOX IDC_NCK5_REALM,60,25,233,51,CBS_DROPDOWN | CBS_AUTOHSCROLL | CBS_SORT | WS_VSCROLL | WS_TABSTOP PUSHBUTTON "Specify &additional realms ...",IDC_NCK5_ADD_REALMS,181,43,112,16,BS_NOTIFY | WS_DISABLED END diff --git a/src/windows/identity/ui/cfg_identities_wnd.c b/src/windows/identity/ui/cfg_identities_wnd.c index 3297b05be..3f92ad839 100644 --- a/src/windows/identity/ui/cfg_identities_wnd.c +++ b/src/windows/identity/ui/cfg_identities_wnd.c @@ -130,10 +130,11 @@ apply_all(HWND hwnd, khui_config_node_reg reg; int idx; int count; + BOOL cont = TRUE; count = TabCtrl_GetItemCount(hw_tab); - for (idx = 0; idx < count; idx++) { + for (idx = 0; idx < count && cont; idx++) { ZeroMemory(&tci, sizeof(tci)); @@ -156,7 +157,7 @@ apply_all(HWND hwnd, #endif SendMessage(hw, KHUI_WM_CFG_NOTIFY, - MAKEWPARAM(0, WMCFG_APPLY), 0); + MAKEWPARAM(0, WMCFG_APPLY), (LPARAM) &cont); } } @@ -317,6 +318,7 @@ typedef struct tag_idents_data { ident_data * idents; khm_size n_idents; khm_size nc_idents; +#define IDENTS_DATA_ALLOC_INCR 8 /* global options */ global_props saved; @@ -430,6 +432,7 @@ write_params_ident(ident_data * d) { if (d->removed) { khm_handle h = NULL; + khm_int32 flags = 0; khc_remove_space(csp_ident); @@ -444,6 +447,10 @@ write_params_ident(ident_data * d) { #endif khc_close_space(h); } +#ifdef DEBUG + kcdb_identity_get_flags(d->ident, &flags); + assert(!(flags & KCDB_IDENT_FLAG_CONFIG)); +#endif } else { @@ -470,11 +477,15 @@ write_params_ident(ident_data * d) { if (d->hwnd) PostMessage(d->hwnd, KHUI_WM_CFG_NOTIFY, MAKEWPARAM(0, WMCFG_UPDATE_STATE), 0); + + khm_refresh_config(); } static void write_params_idents(void) { +#if 0 int i; +#endif khm_handle csp_cw; if (KHM_SUCCEEDED(khc_open_space(NULL, L"CredWindow", @@ -500,9 +511,11 @@ write_params_idents(void) { khc_close_space(csp_cw); } +#if 0 for (i=0; i < (int)cfg_idents.n_idents; i++) { write_params_ident(&cfg_idents.idents[i]); } +#endif if (cfg_idents.hwnd) PostMessage(cfg_idents.hwnd, KHUI_WM_CFG_NOTIFY, @@ -622,6 +635,9 @@ init_idents_data(void) { cfg_idents.idents[i].removed = FALSE; kcdb_identity_get_flags(ident, &cfg_idents.idents[i].flags); +#ifdef DEBUG + assert(cfg_idents.idents[i].flags & KCDB_IDENT_FLAG_CONFIG); +#endif read_params_ident(&cfg_idents.idents[i]); @@ -712,82 +728,258 @@ refresh_view_idents_state(HWND hwnd) { KHUI_CNFLAG_APPLIED | KHUI_CNFLAG_MODIFIED); } +struct ctrl_row_dimensions { + RECT enclosure; + RECT label; + RECT control; +}; + +typedef struct tag_add_ident_data { + khui_new_creds * nc; + + struct ctrl_row_dimensions dim_small; + struct ctrl_row_dimensions dim_medium; + struct ctrl_row_dimensions dim_large; + int row_gap; + + int current_y; + int current_x; + + HWND hwnd_last_ctrl; +} add_ident_data; + +void +get_ctrl_row_metrics(struct ctrl_row_dimensions * dim, HWND hw_lbl, HWND hw_ctl) { + + assert(hw_lbl); + assert(hw_ctl); + + GetWindowRect(hw_lbl, &dim->label); + GetWindowRect(hw_ctl, &dim->control); + + UnionRect(&dim->enclosure, &dim->label, &dim->control); + OffsetRect(&dim->label, + -dim->enclosure.left, + -dim->enclosure.top); + OffsetRect(&dim->control, + -dim->enclosure.left, + -dim->enclosure.top); + OffsetRect(&dim->enclosure, + -dim->enclosure.left, + -dim->enclosure.top); +} + /* dialog box procedure for the "Add new identity" dialog */ INT_PTR CALLBACK khm_cfg_add_ident_proc(HWND hwnd, UINT umsg, WPARAM wParam, - LPARAM lparam) { + LPARAM lParam) { + add_ident_data * d; + switch(umsg) { case WM_INITDIALOG: - /* set the max length of the edit control first */ - SendDlgItemMessage(hwnd, IDC_CFG_IDNAME, - EM_SETLIMITTEXT, - KCDB_IDENT_MAXCCH_NAME - 1, - 0); + /* we create a new credentials blob and pull in the identity + selectors from the identity provider. */ + d = PMALLOC(sizeof(*d)); + ZeroMemory(d, sizeof(*d)); + + khui_cw_create_cred_blob(&d->nc); +#ifdef DEBUG + assert(d->nc != NULL); +#endif + if (d->nc == NULL) { + PFREE(d); + break; + } + + if (KHM_FAILED(kcdb_identpro_get_ui_cb(&d->nc->ident_cb))) { + /* this should have worked. The only reason it would fail + is if there is no identity provider or if the identity + provider does not support providing idnetity + selectors. */ + khui_cw_destroy_cred_blob(d->nc); + PFREE(d); + break; + } + +#pragma warning(push) +#pragma warning(disable: 4244) + SetWindowLongPtr(hwnd, DWLP_USER, (LONG_PTR) d); +#pragma warning(pop) + + /* get metrics for dynamic controls */ + get_ctrl_row_metrics(&d->dim_small, + GetDlgItem(hwnd, IDC_SM_LBL), + GetDlgItem(hwnd, IDC_SM_CTL)); + get_ctrl_row_metrics(&d->dim_medium, + GetDlgItem(hwnd, IDC_MED_LBL), + GetDlgItem(hwnd, IDC_MED_CTL)); + get_ctrl_row_metrics(&d->dim_large, + GetDlgItem(hwnd, IDC_LG_LBL), + GetDlgItem(hwnd, IDC_LG_CTL)); + + { + RECT rlbl; + RECT rctl; + RECT rwnd; + + GetWindowRect(GetDlgItem(hwnd, IDC_SM_LBL), + &rlbl); + GetWindowRect(GetDlgItem(hwnd, IDC_SM_CTL), + &rctl); + GetWindowRect(hwnd, &rwnd); + + OffsetRect(&rlbl, -rwnd.left, -rwnd.top); + OffsetRect(&rctl, -rwnd.left, -rwnd.top); + + d->current_x = rlbl.left; + d->current_y = rctl.top - GetSystemMetrics(SM_CYCAPTION); + + GetWindowRect(GetDlgItem(hwnd, IDC_MED_CTL), + &rlbl); + OffsetRect(&rlbl, -rwnd.left, -rwnd.top); + + d->row_gap = rlbl.top - rctl.bottom; + } + + d->nc->hwnd = hwnd; + + /* now call the UI callback and make it create the + controls. */ + d->nc->ident_cb(d->nc, WMNC_IDENT_INIT, NULL, 0, 0, + (LPARAM) hwnd); + break; case WM_DESTROY: - /* nor do we have to do anything here */ + d = (add_ident_data *)(LONG_PTR) + GetWindowLongPtr(hwnd, DWLP_USER); + if (d == NULL) + break; + + d->nc->ident_cb(d->nc, WMNC_IDENT_EXIT, NULL, 0, 0, 0); + + khui_cw_destroy_cred_blob(d->nc); + PFREE(d); break; + case KHUI_WM_NC_NOTIFY: + d = (add_ident_data *)(LONG_PTR) + GetWindowLongPtr(hwnd, DWLP_USER); + + switch(HIWORD(wParam)) { + case WMNC_ADD_CONTROL_ROW: + { + khui_control_row * row; + RECT r_lbl, r_inp, r_enc; + struct ctrl_row_dimensions * dim; + HFONT hf; + + row = (khui_control_row *) lParam; + +#ifdef DEBUG + assert(row->label); + assert(row->input); + assert(d); +#endif + + if (row->size == KHUI_CTRLSIZE_SMALL) { + dim = &d->dim_small; + } else if (row->size == KHUI_CTRLSIZE_HALF) { + dim = &d->dim_medium; + } else { + dim = &d->dim_large; +#ifdef DEBUG + assert(row->size == KHUI_CTRLSIZE_FULL); +#endif + } + + CopyRect(&r_enc, &dim->enclosure); + CopyRect(&r_lbl, &dim->label); + CopyRect(&r_inp, &dim->control); + + OffsetRect(&r_enc, d->current_x, d->current_y); + OffsetRect(&r_lbl, r_enc.left, r_enc.top); + OffsetRect(&r_inp, r_enc.left, r_enc.top); + + d->current_y += r_enc.bottom - r_enc.top; + + hf = (HFONT) SendDlgItemMessage(hwnd, IDOK, WM_GETFONT, 0, 0); + + if (row->label) { + SetWindowPos(row->label, + ((d->hwnd_last_ctrl != NULL)? + d->hwnd_last_ctrl : + HWND_TOP), + r_lbl.left, r_lbl.top, + r_lbl.right - r_lbl.left, + r_lbl.bottom - r_lbl.top, + SWP_DEFERERASE | SWP_NOACTIVATE | + SWP_NOOWNERZORDER); + if (hf) + SendMessage(row->label, WM_SETFONT, + (WPARAM) hf, + TRUE); + d->hwnd_last_ctrl = row->label; + } + + if (row->input) { + SetWindowPos(row->input, + ((d->hwnd_last_ctrl != NULL)? + d->hwnd_last_ctrl : + HWND_TOP), + r_inp.left, r_inp.top, + r_inp.right - r_inp.left, + r_inp.bottom - r_inp.top, + SWP_DEFERERASE | SWP_NOACTIVATE | + SWP_NOOWNERZORDER); + if (hf) + SendMessage(row->input, WM_SETFONT, + (WPARAM) hf, + TRUE); + d->hwnd_last_ctrl = row->input; + } + } + break; + + case WMNC_IDENTITY_CHANGE: + break; + } + return TRUE; + case WM_COMMAND: if (LOWORD(wParam) == IDOK) { wchar_t idname[KCDB_IDENT_MAXCCH_NAME]; - khm_int32 rv = KHM_ERROR_SUCCESS; + wchar_t err_msg[1024]; khm_handle ident = NULL; khm_handle csp_ident = NULL; - khm_size i; - wchar_t err_msg[512] = L""; - - GetDlgItemText(hwnd, IDC_CFG_IDNAME, idname, - ARRAYLENGTH(idname)); - - idname[ARRAYLENGTH(idname) - 1] = L'\0'; - if (KHM_FAILED(rv = kcdb_identpro_validate_name(idname)) && - rv != KHM_ERROR_NO_PROVIDER && - rv != KHM_ERROR_NOT_IMPLEMENTED) { - /* the supplied name was invalid or something */ - - wchar_t fmt[256]; + khm_size cb; + khm_int32 rv = KHM_ERROR_SUCCESS; - LoadString(khm_hInstance, IDS_CFG_IDNAME_INV, - fmt, ARRAYLENGTH(fmt)); - StringCbPrintf(err_msg, sizeof(err_msg), fmt, idname); + d = (add_ident_data *)(LONG_PTR) + GetWindowLongPtr(hwnd, DWLP_USER); - goto show_failure; - } + if (!d || !d->nc) + break; - /* now check if this is actually a new identity */ - for (i=0; i < cfg_idents.n_idents; i++) { - if (!kcdb_identpro_compare_name(cfg_idents.idents[i].idname, - idname)) - break; - } + /* check if there was an identity selected */ + if (d->nc->n_identities == 0 || + d->nc->identities[0] == NULL) { - if (i < cfg_idents.n_idents) { - wchar_t fmt[256]; + StringCbCopy(idname, sizeof(idname), L""); - LoadString(khm_hInstance, IDS_CFG_IDNAME_EXT, - fmt, ARRAYLENGTH(fmt)); - StringCbPrintf(err_msg, sizeof(err_msg), fmt, idname); + LoadString(khm_hInstance, IDS_CFG_IDNAME_NON, + err_msg, ARRAYLENGTH(err_msg)); goto show_failure; } - /* ok. now we are all set to add the new identity */ - if (KHM_FAILED(rv = kcdb_identity_create(idname, - KCDB_IDENT_FLAG_CREATE, - &ident))) { - /* oops */ - wchar_t fmt[256]; - - LoadString(khm_hInstance, IDS_CFG_IDNAME_CCR, - fmt, ARRAYLENGTH(fmt)); - StringCbPrintf(err_msg, sizeof(err_msg), fmt, rv); + ident = d->nc->identities[0]; + kcdb_identity_hold(ident); - goto show_failure; - } + cb = sizeof(idname); + kcdb_identity_get_name(ident, idname, &cb); /* now we have to create the identity configuration. */ if (KHM_FAILED(rv = kcdb_identity_get_config(ident, @@ -804,6 +996,11 @@ khm_cfg_add_ident_proc(HWND hwnd, goto show_failure; } + /* create a value so that the configuration space will + actually be created in the registry. We don't want + this new identity to be sticky. */ + khc_write_int32(csp_ident, L"Sticky", 0); + khm_refresh_config(); kcdb_identity_release(ident); @@ -833,6 +1030,14 @@ khm_cfg_add_ident_proc(HWND hwnd, } else if (LOWORD(wParam) == IDCANCEL) { EndDialog(hwnd, 1); + } else { + d = (add_ident_data *)(LONG_PTR) + GetWindowLongPtr(hwnd, DWLP_USER); + + if (d && d->nc && d->nc->ident_cb) { + return d->nc->ident_cb(d->nc, WMNC_IDENT_WMSG, + hwnd, umsg, wParam, lParam); + } } break; } @@ -1023,6 +1228,7 @@ find_ident_by_node(khui_config_node node) { khm_size cb; wchar_t idname[KCDB_IDENT_MAXCCH_NAME]; int i; + khm_handle ident = NULL; cb = sizeof(idname); khui_cfg_get_name(node, idname, &cb); @@ -1034,8 +1240,56 @@ find_ident_by_node(khui_config_node node) { if (i < (int)cfg_idents.n_idents) return &cfg_idents.idents[i]; - else + + /* there is no identity data for this configuration node. We try + to create it. */ + if (KHM_FAILED(kcdb_identity_create(idname, 0, &ident))) return NULL; + + if (cfg_idents.n_idents >= cfg_idents.nc_idents) { + cfg_idents.nc_idents = UBOUNDSS(cfg_idents.n_idents + 1, + IDENTS_DATA_ALLOC_INCR, + IDENTS_DATA_ALLOC_INCR); +#ifdef DEBUG + assert(cfg_idents.nc_idents > cfg_idents.n_idents); +#endif + cfg_idents.idents = PREALLOC(cfg_idents.idents, + sizeof(*cfg_idents.idents) * + cfg_idents.nc_idents); +#ifdef DEBUG + assert(cfg_idents.idents); +#endif + ZeroMemory(&(cfg_idents.idents[cfg_idents.n_idents]), + sizeof(*cfg_idents.idents) * + (cfg_idents.nc_idents - cfg_idents.n_idents)); + } + + i = (int) cfg_idents.n_idents; + + StringCbLength(idname, KCDB_IDENT_MAXCB_NAME, &cb); + cb += sizeof(wchar_t); + + cfg_idents.idents[i].idname = PMALLOC(cb); +#ifdef DEBUG + assert(cfg_idents.idents[i].idname); +#endif + StringCbCopy(cfg_idents.idents[i].idname, cb, idname); + + cfg_idents.idents[i].ident = ident; + cfg_idents.idents[i].removed = FALSE; + + kcdb_identity_get_flags(ident, &cfg_idents.idents[i].flags); +#ifdef DEBUG + assert(cfg_idents.idents[i].flags & KCDB_IDENT_FLAG_CONFIG); +#endif + + read_params_ident(&cfg_idents.idents[i]); + + cfg_idents.n_idents++; + + /* leave ident held. */ + + return &cfg_idents.idents[i]; } static void @@ -1191,13 +1445,17 @@ khm_cfg_id_tab_proc(HWND hwnd, case KHUI_WM_CFG_NOTIFY: { ident_data * d; + BOOL * cont; khui_cfg_get_dialog_data(hwnd, &idata, NULL); switch (HIWORD(wParam)) { case WMCFG_APPLY: + cont = (BOOL *) lParam; d = find_ident_by_node(idata->ctx_node); write_params_ident(d); + if (d->removed && cont) + *cont = FALSE; khui_cfg_set_flags_inst(idata, KHUI_CNFLAG_APPLIED, KHUI_CNFLAG_APPLIED | KHUI_CNFLAG_MODIFIED); diff --git a/src/windows/identity/ui/configwnd.c b/src/windows/identity/ui/configwnd.c index 24f9a619c..660c1fae8 100644 --- a/src/windows/identity/ui/configwnd.c +++ b/src/windows/identity/ui/configwnd.c @@ -422,6 +422,209 @@ cfgui_apply_settings(khui_config_node node) { } } +static void +cfgui_remove_item(HWND hwtv, + HTREEITEM hItem) { + khui_config_node node; + HTREEITEM hChild; + TVITEMEX itemex; + + for (hChild = TreeView_GetChild(hwtv, hItem); + hChild; + hChild = TreeView_GetChild(hwtv, hItem)) { + + cfgui_remove_item(hwtv, hChild); + + } + + ZeroMemory(&itemex, sizeof(itemex)); + + itemex.mask = TVIF_PARAM; + itemex.hItem = hItem; + + TreeView_GetChild(hwtv, &itemex); + + node = (khui_config_node) itemex.lParam; + + if (node) { + HWND hw; + hw = khui_cfg_get_hwnd(node); + + if (hw) + DestroyWindow(hw); + + khui_cfg_release(node); + } + + TreeView_DeleteItem(hwtv, hItem); +} + +struct cfgui_child_info { + HTREEITEM hItem; + khui_config_node node; + BOOL checked; +}; + +#define CI_ALLOC_INCR 8 + +static void +cfgui_sync_node(cfgui_wnd_data * d, + HWND hwtv, + khui_config_node c, + HTREEITEM hItem) { + khui_config_node child; + HTREEITEM hChild; + struct cfgui_child_info * childinfo = NULL; + khm_size n_childinfo = 0; + khm_size nc_childinfo = 0; + khm_size i; + + /* first, get the list of children from the treeview control */ + for (hChild = TreeView_GetChild(hwtv, hItem); + hChild; + hChild = TreeView_GetNextSibling(hwtv, hChild)) { + + if (n_childinfo >= nc_childinfo) { + nc_childinfo = UBOUNDSS(n_childinfo + 1, + CI_ALLOC_INCR, CI_ALLOC_INCR); +#ifdef DEBUG + assert(nc_childinfo > n_childinfo); +#endif + childinfo = PREALLOC(childinfo, + sizeof(*childinfo) * nc_childinfo); +#ifdef DEBUG + assert(childinfo); +#endif + } + + ZeroMemory(&childinfo[n_childinfo], + sizeof(childinfo[n_childinfo])); + + childinfo[n_childinfo].hItem = hChild; + childinfo[n_childinfo].checked = FALSE; + n_childinfo++; + } + + /* now, go through the list of actual nodes and make sure they + match up */ + child = NULL; + for (khui_cfg_get_first_child(c, &child); + child; + khui_cfg_get_next_release(&child)) { + + hChild = (HTREEITEM) khui_cfg_get_param(child); + + for (i=0; i < n_childinfo; i++) { + if (childinfo[i].hItem == hChild) + break; + } + + if (i < n_childinfo) { + childinfo[i].checked = TRUE; + } else { + /* add it to the list, so we can create the node in the + tree view control later. */ + if (n_childinfo >= nc_childinfo) { + nc_childinfo = UBOUNDSS(n_childinfo + 1, + CI_ALLOC_INCR, CI_ALLOC_INCR); +#ifdef DEBUG + assert(nc_childinfo > n_childinfo); +#endif + childinfo = PREALLOC(childinfo, + sizeof(*childinfo) * nc_childinfo); +#ifdef DEBUG + assert(childinfo); +#endif + } + + ZeroMemory(&childinfo[n_childinfo], + sizeof(childinfo[n_childinfo])); + + childinfo[n_childinfo].node = child; + khui_cfg_hold(child); + n_childinfo++; + } + } + + /* by this point, the childinfo list contains items of the + following forms: + + 1. childinfo[i].hItem != NULL && childinfo[i].checked == TRUE + + Corresponds to a tree view item that has a matching + configuration node. Nothing to do here. + + 2. childinfo[i].hItem != NULL && childinfo[i].checked == FALSE + + Corresponds to a tree view item that has no matching + configuration node. These should be removed. + + 3. childinfo[i].hItem == NULL && childinfo[i].node != NULL + + Corresponds to a configuration node that has no matching + tree view item. These nodes should be added. + */ + + /* first do the removals */ + for (i=0; i < n_childinfo; i++) { + if (childinfo[i].hItem == NULL) + break; /* nothing more to see from this point + on */ + if (!childinfo[i].checked) { + /* remove! */ + cfgui_remove_item(hwtv, childinfo[i].hItem); + } + } + + /* continue from where the previous loop left off */ + for (; i < n_childinfo; i++) { +#ifdef DEBUG + assert(childinfo[i].hItem == NULL); + assert(childinfo[i].node != NULL); +#endif + + cfgui_add_node(d, hwtv, childinfo[i].node, c, FALSE); + + khui_cfg_release(childinfo[i].node); + childinfo[i].node = NULL; + } + + if (childinfo) + PFREE(childinfo); + + /* finally recurse through to the next level */ + for (hChild = TreeView_GetChild(hwtv, hItem); + hChild; + hChild = TreeView_GetNextSibling(hwtv, hChild)) { + + TVITEMEX itemex; + + ZeroMemory(&itemex, sizeof(itemex)); + + itemex.mask = TVIF_PARAM; + itemex.hItem = hChild; + + TreeView_GetItem(hwtv, &itemex); + + if (itemex.lParam) { + child = (khui_config_node) itemex.lParam; + + cfgui_sync_node(d, hwtv, child, hChild); + } + } +} + +static void +cfgui_sync_node_list(cfgui_wnd_data * d, HWND hwnd) { + HWND hwtv; + HTREEITEM hItem; + + hwtv = GetDlgItem(hwnd, IDC_CFG_NODELIST); + hItem = TreeView_GetRoot(hwtv); + + cfgui_sync_node(d, hwtv, NULL, hItem); +} + static void cfgui_update_state(HWND hwnd, khm_int32 flags, @@ -670,7 +873,8 @@ cfgui_dlgproc(HWND hwnd, break; case WMCFG_SYNC_NODE_LIST: - /*TODO: synchronize the node lists here */ + d = cfgui_get_wnd_data(hwnd); + cfgui_sync_node_list(d, hwnd); break; } @@ -825,6 +1029,9 @@ void khm_refresh_config(void) { khui_cfg_remove(cfg_iter); } + + if (tident) + kcdb_identity_release(tident); } /* Now iterate through the root level configuration nodes and make diff --git a/src/windows/identity/ui/credfuncs.c b/src/windows/identity/ui/credfuncs.c index d695afead..530ef0852 100644 --- a/src/windows/identity/ui/credfuncs.c +++ b/src/windows/identity/ui/credfuncs.c @@ -267,8 +267,9 @@ kmsg_cred_completion(kmq_message *m) kcdb_credset_get_size(tcs, &count); kcdb_credset_delete(tcs); - if (count == 0) - break; + if (count == 0) { + goto done_with_op; + } } ctx = kherr_peek_context(); @@ -348,6 +349,8 @@ kmsg_cred_completion(kmq_message *m) kherr_clear_error(); } + done_with_op: + if (nc->subtype == KMSG_CRED_RENEW_CREDS) { kmq_post_message(KMSG_CRED, KMSG_CRED_END, 0, m->vparam); @@ -994,11 +997,23 @@ khm_cred_process_startup_actions(void) { } if (khm_startup.autoinit) { - khm_size count; + khm_size count = 0; + khm_handle credset = NULL; + khm_int32 ctype_ident = KCDB_CREDTYPE_INVALID; + khm_int32 delta = 0; khm_startup.autoinit = FALSE; - kcdb_credset_get_size(NULL, &count); + kcdb_credset_create(&credset); + kcdb_identity_get_type(&ctype_ident); + + kcdb_credset_collect(credset, NULL, + defident, ctype_ident, + &delta); + + kcdb_credset_get_size(credset, &count); + + kcdb_credset_delete(credset); if (count == 0) { if (defident) diff --git a/src/windows/identity/ui/htwnd.c b/src/windows/identity/ui/htwnd.c index f65525690..afb68aa02 100644 --- a/src/windows/identity/ui/htwnd.c +++ b/src/windows/identity/ui/htwnd.c @@ -806,7 +806,8 @@ static LRESULT htw_paint(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) EndPaint(hwnd, &ps); - if (d->ext_width < ext_width) { + if (d->ext_width < ext_width || + d->ext_height < ext_height) { SCROLLINFO si; LONG l; diff --git a/src/windows/identity/ui/lang/en_us/khapp.rc b/src/windows/identity/ui/lang/en_us/khapp.rc index eb84b8f1e..48f577684 100644 --- a/src/windows/identity/ui/lang/en_us/khapp.rc +++ b/src/windows/identity/ui/lang/en_us/khapp.rc @@ -370,9 +370,9 @@ FONT 8, "MS Shell Dlg", 400, 0, 0x1 BEGIN GROUPBOX "Font for credentials display",IDC_STATIC,7,7,241,137 LTEXT "&Font name",IDC_STATIC,17,22,35,8 - COMBOBOX IDC_CFG_FONTS,62,20,178,30,CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP + COMBOBOX IDC_CFG_FONTS,62,20,178,51,CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP LTEXT "&Size",IDC_STATIC,62,43,14,8 - COMBOBOX IDC_CFG_SIZE,87,41,48,14,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + COMBOBOX IDC_CFG_SIZE,87,41,48,51,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP CONTROL "&Bold",IDC_CFG_BOLD,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,162,42,29,10 CONTROL "&Italics",IDC_CFG_ITALICS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,205,42,35,10 EDITTEXT IDC_CFG_SAMPLE_NORMAL,62,66,178,21,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER | NOT WS_TABSTOP,WS_EX_STATICEDGE @@ -380,15 +380,19 @@ BEGIN PUSHBUTTON "&Revert to default",IDC_CFG_REVERT,168,122,72,14 END -IDD_CFG_ADDIDENT DIALOGEX 0, 0, 325, 70 +IDD_CFG_ADDIDENT DIALOGEX 0, 0, 279, 95 STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "Add new identity" FONT 8, "MS Shell Dlg", 400, 0, 0x1 BEGIN - LTEXT "&Identity name",IDC_STATIC,7,10,46,8 - EDITTEXT IDC_CFG_IDNAME,67,7,195,14,ES_AUTOHSCROLL - DEFPUSHBUTTON "OK",IDOK,268,7,50,14 - PUSHBUTTON "Cancel",IDCANCEL,268,24,50,14 + LTEXT "&Identity name",IDC_SM_LBL,7,10,46,8,NOT WS_VISIBLE + EDITTEXT IDC_SM_CTL,67,7,205,14,ES_AUTOHSCROLL | NOT WS_VISIBLE + DEFPUSHBUTTON "OK",IDOK,145,74,71,14 + PUSHBUTTON "Cancel",IDCANCEL,222,74,50,14 + LTEXT "&Identity name",IDC_MED_LBL,7,27,130,8,NOT WS_VISIBLE + EDITTEXT IDC_MED_CTL,141,24,131,14,ES_AUTOHSCROLL | NOT WS_VISIBLE + LTEXT "&Identity name",IDC_LG_LBL,7,41,265,8,NOT WS_VISIBLE + EDITTEXT IDC_LG_CTL,141,50,131,14,ES_AUTOHSCROLL | NOT WS_VISIBLE END @@ -531,9 +535,9 @@ BEGIN IDD_CFG_ADDIDENT, DIALOG BEGIN LEFTMARGIN, 7 - RIGHTMARGIN, 318 + RIGHTMARGIN, 272 TOPMARGIN, 7 - BOTTOMMARGIN, 63 + BOTTOMMARGIN, 88 END END #endif // APSTUDIO_INVOKED @@ -777,6 +781,7 @@ END STRINGTABLE BEGIN IDS_NC_REN_FAILED_TITLE_I "Failed to renew creds for %s" + IDS_CFG_IDNAME_NON "No identity selected. Please select an identity and try again." END #endif // English (U.S.) resources diff --git a/src/windows/identity/ui/newcredwnd.c b/src/windows/identity/ui/newcredwnd.c index f5b302ec0..a52d09b41 100644 --- a/src/windows/identity/ui/newcredwnd.c +++ b/src/windows/identity/ui/newcredwnd.c @@ -522,7 +522,8 @@ nc_update_credtext(khui_nc_wnd_data * d) } if (!(d->nc->response & KHUI_NC_RESPONSE_PROCESSING)) { - if(validId || d->nc->subtype == KMSG_CRED_PASSWORD) { + if(validId || + d->nc->subtype == KMSG_CRED_PASSWORD) { /* TODO: check if all the required fields have valid values before enabling the Ok button */ okEnable = TRUE; @@ -876,9 +877,8 @@ nc_add_control_row(khui_nc_wnd_data * d, SetRectEmpty(&r_input); #ifdef DEBUG assert(FALSE); -#else - return; #endif + return; } if (label) diff --git a/src/windows/identity/ui/notifier.c b/src/windows/identity/ui/notifier.c index 12b746b1f..9804abfae 100644 --- a/src/windows/identity/ui/notifier.c +++ b/src/windows/identity/ui/notifier.c @@ -305,6 +305,7 @@ notifier_wnd_proc(HWND hwnd, khm_timer_fire(hwnd); } else if (wParam == KHUI_REFRESH_TIMER_ID) { KillTimer(hwnd, KHUI_REFRESH_TIMER_ID); + kcdb_identity_refresh_all(); khm_timer_refresh(hwnd); } } diff --git a/src/windows/identity/ui/resource.h b/src/windows/identity/ui/resource.h index 35b493e91..b8dc0ec04 100644 --- a/src/windows/identity/ui/resource.h +++ b/src/windows/identity/ui/resource.h @@ -293,6 +293,7 @@ #define IDS_NC_FAILED_TITLE_I 286 #define IDS_NC_PWD_FAILED_TITLE_I 287 #define IDS_NC_REN_FAILED_TITLE_I 288 +#define IDS_CFG_IDNAME_NON 289 #define IDC_NC_USERNAME 1007 #define IDC_NC_PASSWORD 1008 #define IDC_NC_CREDTEXT_LABEL 1009 @@ -389,7 +390,13 @@ #define IDC_CFG_ITALICS 1132 #define IDC_CFG_ADDIDENT 1133 #define IDC_CFG_IDNAME 1134 +#define IDC_SM_CTL 1134 #define IDC_CFG_SHOWLOG 1135 +#define IDC_MED_CTL 1135 +#define IDC_LG_CTL 1136 +#define IDC_SM_LBL 1137 +#define IDC_MED_LBL 1138 +#define IDC_LG_LBL 1139 #define IDA_ACTIVATE_MENU 40003 #define IDA_UP 40004 #define IDA_DOWN 40005 @@ -404,7 +411,7 @@ #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_NEXT_RESOURCE_VALUE 212 #define _APS_NEXT_COMMAND_VALUE 40010 -#define _APS_NEXT_CONTROL_VALUE 1136 +#define _APS_NEXT_CONTROL_VALUE 1140 #define _APS_NEXT_SYMED_VALUE 101 #endif #endif diff --git a/src/windows/identity/ui/timer.c b/src/windows/identity/ui/timer.c index 40464d5ad..3adf9e9a4 100644 --- a/src/windows/identity/ui/timer.c +++ b/src/windows/identity/ui/timer.c @@ -92,17 +92,21 @@ khm_timer_exit(void) { static void tmr_fire_timer(void) { int i; - unsigned __int64 curtime; - unsigned __int64 err; - unsigned __int64 next_event; + khm_int64 curtime; + khm_int64 err; + khm_int64 next_event; int tmr_count[KHUI_N_TTYPES]; - unsigned __int64 tmr_offset[KHUI_N_TTYPES]; + khm_int64 tmr_offset[KHUI_N_TTYPES]; int t; khm_handle eff_ident = NULL; khui_timer_type eff_type = 0; /* meaningless */ int fire_count = 0; FILETIME ft; + _begin_task(0); + _report_cs0(KHERR_DEBUG_1, L"Checking for expired timers"); + _describe(); + TimetToFileTimeInterval(KHUI_TIMEEQ_ERROR_SMALL, &ft); err = FtToInt(&ft); GetSystemTimeAsFileTime(&ft); @@ -119,10 +123,16 @@ tmr_fire_timer(void) { khui_timers[i].type != KHUI_TTYPE_ID_MARK && khui_timers[i].expire < curtime + err) { + _report_cs3(KHERR_DEBUG_1, L"Expiring timer index=%1!d!, type=%2!d!, key=%3!p!", + _int32(i), _int32(khui_timers[i].type), + _cptr(khui_timers[i].key)); + t = khui_timers[i].type; switch(t) { case KHUI_TTYPE_ID_RENEW: + _report_cs1(KHERR_DEBUG_1, L"Renewing identity %1!p!", + _cptr(khui_timers[i].key)); khm_cred_renew_identity(khui_timers[i].key); khui_timers[i].flags |= KHUI_TE_FLAG_EXPIRED; break; @@ -134,6 +144,8 @@ tmr_fire_timer(void) { we assume that it is safe to trigger a renew_cred call here without checking if there's an imminent renew_identity call. */ + _report_cs1(KHERR_DEBUG_1, L"Renewing credential %1!p!", + _cptr(khui_timers[i].key)); khm_cred_renew_cred(khui_timers[i].key); khui_timers[i].flags |= KHUI_TE_FLAG_EXPIRED; break; @@ -184,7 +196,7 @@ tmr_fire_timer(void) { wchar_t wtime[128]; wchar_t wmsg[256]; wchar_t wtitle[64]; - unsigned __int64 second; + khm_int64 second; khui_alert * alert = NULL; khm_size cb; @@ -249,6 +261,9 @@ tmr_fire_timer(void) { khui_alert_show(alert); khui_alert_release(alert); } + + _end_task(); + } void @@ -264,6 +279,85 @@ static int tmr_update(khm_handle key, khui_timer_type type, __int64 expire, __int64 offset, void * data, khm_boolean reinstate) { int i; + wchar_t name[KCDB_MAXCCH_NAME]; + wchar_t tstamp[128]; + wchar_t *type_str = NULL; + SYSTEMTIME st; + FILETIME ft; + FILETIME ftl; + khm_size cb; + + switch(type) { + case KHUI_TTYPE_ID_MARK: + type_str = L"marker"; + break; + + case KHUI_TTYPE_CRED_WARN: + case KHUI_TTYPE_ID_WARN: + type_str = L"warning"; + break; + + case KHUI_TTYPE_CRED_CRIT: + case KHUI_TTYPE_ID_CRIT: + type_str = L"critical"; + break; + + case KHUI_TTYPE_CRED_EXP: + case KHUI_TTYPE_ID_EXP: + type_str = L"expiry"; + break; + + case KHUI_TTYPE_CRED_RENEW: + case KHUI_TTYPE_ID_RENEW: + type_str = L"renew"; + break; + } + + ft = IntToFt(expire); + FileTimeToLocalFileTime(&ft, &ftl); + FileTimeToSystemTime(&ftl, &st); + StringCbPrintf(tstamp, sizeof(tstamp), + L"%d-%d-%d %d:%d:%d", + st.wYear, st.wMonth, st.wDay, + st.wHour, st.wMinute, st.wSecond); + + cb = sizeof(name); name[0] = L'\0'; + if (type_str == NULL) { + + _report_cs2(KHERR_DEBUG_1, + L"Updating uknown timer of type %1!d! exp(%2!s!)", + _int32(type), + _cstr(tstamp)); + _resolve(); + + } else if (type == KHUI_TTYPE_ID_MARK || + type == KHUI_TTYPE_ID_WARN || + type == KHUI_TTYPE_ID_CRIT || + type == KHUI_TTYPE_ID_EXP || + type == KHUI_TTYPE_ID_RENEW) { + + kcdb_identity_get_name(key, name, &cb); + _report_cs3(KHERR_DEBUG_1, + L"Updating identity %1!s! timer for %2!s! exp(%3!s!)", + _cstr(type_str), + _cstr(name), + _cstr(tstamp)); + _resolve(); + + } else if (type == KHUI_TTYPE_CRED_RENEW || + type == KHUI_TTYPE_CRED_WARN || + type == KHUI_TTYPE_CRED_CRIT || + type == KHUI_TTYPE_CRED_EXP) { + + kcdb_cred_get_name(key, name, &cb); + _report_cs3(KHERR_DEBUG_1, + L"Updating credential %1!s! timer for %2!s! exp(%3!s!)", + _cstr(type_str), + _cstr(name), + _cstr(tstamp)); + _resolve(); + + } for (i=0; i < (int) khui_n_timers; i++) { if (khui_timers[i].key == key && @@ -385,7 +479,7 @@ tmr_next_halflife_timeout(int idx, FILETIME * issue, FILETIME * expire) { not expired. However, we leave it to the caller to update the actual timer and mark it as not stale. */ if (idx >= 0 && - khui_timers[idx].expire < (khm_ui_8) iret) { + khui_timers[idx].expire < iret) { khui_timers[idx].flags &= ~KHUI_TE_FLAG_EXPIRED; khui_timers[idx].expire = iret; @@ -394,7 +488,8 @@ tmr_next_halflife_timeout(int idx, FILETIME * issue, FILETIME * expire) { return ret; } -/* called with cs_timers held */ +/* called with cs_timers held. Called once for each credential in the + root credentials set. */ static khm_int32 KHMAPI tmr_cred_apply_proc(khm_handle cred, void * rock) { khm_handle ident = NULL; @@ -410,40 +505,56 @@ tmr_cred_apply_proc(khm_handle cred, void * rock) { FILETIME fte; FILETIME ft_reinst; khm_size cb; + wchar_t wname[KCDB_MAXCCH_NAME]; + + cb = sizeof(wname); + wname[0] = L'\0'; + kcdb_cred_get_name(cred, wname, &cb); + + _report_cs1(KHERR_DEBUG_1, L"Looking at cred [%1!s!]", + _cstr(wname)); + _resolve(); kcdb_cred_get_identity(cred, &ident); #ifdef DEBUG assert(ident); #endif - /* now get the expiry */ + /* now get the expiry for the identity*/ cb = sizeof(ft_expiry); if (KHM_FAILED(kcdb_identity_get_attr(ident, KCDB_ATTR_EXPIRE, NULL, &ft_expiry, &cb))) { + + /* failing which, we get the expiry for this credential */ cb = sizeof(ft_expiry); if (KHM_FAILED(kcdb_cred_get_attr(cred, KCDB_ATTR_EXPIRE, NULL, &ft_expiry, &cb))) { /* we don't have an expiry time to work with */ + _report_cs1(KHERR_DEBUG_1, L"Skipping cred [%1!s!]. No expiry time", + _cstr(wname)); + _resolve(); + kcdb_identity_release(ident); return KHM_ERROR_SUCCESS; + } else { + /* and the time of issue */ + cb = sizeof(ft_issue); + if (KHM_FAILED(kcdb_cred_get_attr(cred, KCDB_ATTR_ISSUE, + NULL, &ft_issue, &cb))) + ZeroMemory(&ft_issue, sizeof(ft_issue)); } - } - cb = sizeof(ft_issue); - if (KHM_FAILED(kcdb_identity_get_attr(ident, KCDB_ATTR_ISSUE, - NULL, - &ft_issue, &cb))) { + } else { + /* also try to get the time of issue. */ cb = sizeof(ft_issue); - if (KHM_FAILED(kcdb_cred_get_attr(cred, KCDB_ATTR_ISSUE, - NULL, - &ft_issue, &cb))) { - /* we don't really abandon the timer. In this case, we - fall back to using the threshold value to set the - expiry timer. */ + if (KHM_FAILED(kcdb_identity_get_attr(ident, KCDB_ATTR_ISSUE, + NULL, &ft_issue, &cb))) + /* if we fail, we just zero out the time of issue and + failover to using the threshold value to set the expiry + timer instead of the half life algorithm. */ ZeroMemory(&ft_issue, sizeof(ft_issue)); - } } /* and the current time */ @@ -540,7 +651,8 @@ tmr_cred_apply_proc(khm_handle cred, void * rock) { prev = tmr_find(ident, KHUI_TTYPE_ID_RENEW, 0, 0); - if (do_halflife) + if (do_halflife && (ft_issue.dwLowDateTime != 0 || + ft_issue.dwHighDateTime != 0)) fte = tmr_next_halflife_timeout(prev, &ft_issue, &ft_expiry); else fte = FtSub(&ft_expiry, &ft); @@ -613,15 +725,22 @@ tmr_cred_apply_proc(khm_handle cred, void * rock) { if (KHM_FAILED(kcdb_cred_get_attr(cred, KCDB_ATTR_EXPIRE, NULL, &ft_cred_expiry, - &cb))) + &cb))) { + _report_cs1(KHERR_DEBUG_1, L"Skipping cred [%1!s!]. Can't lookup cred expiry", + _cstr(wname)); + _resolve(); goto _cleanup; + } cb = sizeof(ft_cred_issue); if (KHM_FAILED(kcdb_cred_get_attr(cred, KCDB_ATTR_ISSUE, NULL, &ft_cred_issue, - &cb))) - goto _cleanup; + &cb))) { + + ZeroMemory(&ft_cred_issue, sizeof(ft_cred_issue)); + + } TimetToFileTimeInterval(KHUI_TIMEEQ_ERROR, &ft); @@ -636,8 +755,14 @@ tmr_cred_apply_proc(khm_handle cred, void * rock) { ft_delta = FtSub(&ft_expiry, &ft_cred_expiry); if (CompareFileTime(&ft_cred_expiry, &ft_expiry) >= 0 || - CompareFileTime(&ft_delta, &ft) < 0) + CompareFileTime(&ft_delta, &ft) < 0) { + + _report_cs1(KHERR_DEBUG_1, + L"Skipping credential [%1!s!]. The expiry time is too close to the identity expiry.", + _cstr(wname)); + _resolve(); goto _cleanup; + } } if ((idx = tmr_find(ident, KHUI_TTYPE_ID_WARN, 0, 0)) >= 0 && @@ -669,8 +794,34 @@ tmr_cred_apply_proc(khm_handle cred, void * rock) { if ((idx = tmr_find(ident, KHUI_TTYPE_ID_RENEW, 0, 0)) >= 0 && !(khui_timers[idx].flags & KHUI_TE_FLAG_STALE)) { - //fte = IntToFt(FtToInt(&ft_cred_expiry) - khui_timers[idx].offset); - fte = tmr_next_halflife_timeout(idx, &ft_cred_issue, &ft_cred_expiry); + int cidx = tmr_find(cred, KHUI_TTYPE_CRED_RENEW, 0, 0); + + if (ft_cred_issue.dwLowDateTime == 0 && + ft_cred_issue.dwHighDateTime == 0) { + fte = IntToFt(FtToInt(&ft_cred_expiry) - khui_timers[idx].offset); + /* a special case, for a credential whose remaining + lifetime is less than the offset, we try half life on + the current time and the expiry. */ + if (CompareFileTime(&fte, &ft_current) <= 0 && + CompareFileTime(&ft_current, &ft_expiry) < 0) { + fte = tmr_next_halflife_timeout(cidx, &ft_current, &ft_cred_expiry); +#if 0 + /* now, if we already have a renew timer for this + credential that hasn't expired yet and that is set + for earlier than fte, we let it be. */ + if (cidx >= 0 && + khui_timers[cidx].expire < FtToInt(&fte) && + khui_timers[cidx].expire > FtToInt(&ft_current) && + !(khui_timers[cidx].flags & KHUI_TE_FLAG_EXPIRED)) { + + fte = IntToFt(khui_timers[cidx].expire); + + } +#endif + } + } else { + fte = tmr_next_halflife_timeout(cidx, &ft_cred_issue, &ft_cred_expiry); + } if (CompareFileTime(&fte, &ft_current) > 0) { tmr_update(cred, KHUI_TTYPE_CRED_RENEW, @@ -754,13 +905,18 @@ tmr_purge(void) { khui_n_timers = j; } -/* go through all the credentials and set timers as appropriate. */ +/* go through all the credentials and set timers as appropriate. hwnd + is the window that will receive the timer events.*/ void khm_timer_refresh(HWND hwnd) { int i; - unsigned __int64 next_event = 0; - unsigned __int64 curtime; - unsigned __int64 diff; + khm_int64 next_event = 0; + khm_int64 curtime; + khm_int64 diff; + + _begin_task(0); + _report_cs0(KHERR_DEBUG_1, L"Refreshing timers"); + _describe(); EnterCriticalSection(&cs_timers); @@ -788,12 +944,18 @@ khm_timer_refresh(HWND hwnd) { #endif } + _report_cs1(KHERR_DEBUG_1, L"Starting with %1!d! timers", + _int32(khui_n_timers)); + kcdb_credset_apply(NULL, tmr_cred_apply_proc, NULL); tmr_purge(); + _report_cs1(KHERR_DEBUG_1, L"Leaving with %1!d! timers", + _int32(khui_n_timers)); + _check_next_event: /* Before we return, we should check if any timers are set to @@ -805,9 +967,11 @@ khm_timer_refresh(HWND hwnd) { if (!(khui_timers[i].flags & KHUI_TE_FLAG_EXPIRED) && khui_timers[i].type != KHUI_TTYPE_ID_MARK && (next_event == 0 || - next_event > khui_timers[i].expire)) + next_event > khui_timers[i].expire)) { next_event = khui_timers[i].expire; + + } } if (next_event != 0) { @@ -833,4 +997,6 @@ khm_timer_refresh(HWND hwnd) { } LeaveCriticalSection(&cs_timers); + + _end_task(); } diff --git a/src/windows/identity/ui/timer.h b/src/windows/identity/ui/timer.h index 081d27852..130ae999a 100644 --- a/src/windows/identity/ui/timer.h +++ b/src/windows/identity/ui/timer.h @@ -58,9 +58,9 @@ typedef struct tag_khui_timer_event { khm_handle key; khui_timer_type type; - unsigned __int64 expire; /* time at which the timer expires */ - unsigned __int64 offset; /* time offset at which the event that - the timer warns of happens */ + khm_int64 expire; /* time at which the timer expires */ + khm_int64 offset; /* time offset at which the event that the + timer warns of happens */ void * data; khm_int32 flags; } khui_timer_event; diff --git a/src/windows/identity/uilib/configui.c b/src/windows/identity/uilib/configui.c index 79e570820..c8c61f5cb 100644 --- a/src/windows/identity/uilib/configui.c +++ b/src/windows/identity/uilib/configui.c @@ -349,7 +349,9 @@ khui_cfg_get_first_child(khui_config_node vparent, if (parent) { for(c = TFIRSTCHILD(parent); - c && (c->reg.flags & KHUI_CNFLAG_SUBPANEL); + c && + ((c->reg.flags & KHUI_CNFLAG_SUBPANEL) || + (c->flags & KHUI_CN_FLAG_DELETED)); c = LNEXT(c)); } else { c = NULL; @@ -390,7 +392,9 @@ khui_cfg_get_first_subpanel(khui_config_node vparent, if (parent) { for(c = TFIRSTCHILD(parent); - c && !(c->reg.flags & KHUI_CNFLAG_SUBPANEL); + c && + (!(c->reg.flags & KHUI_CNFLAG_SUBPANEL) || + (c->flags & KHUI_CN_FLAG_DELETED)); c = LNEXT(c)); } else { c = NULL; @@ -458,8 +462,9 @@ khui_cfg_get_next_release(khui_config_node * pvnode) { node = cfgui_node_i_from_handle(*pvnode); for(nxt_node = LNEXT(node); nxt_node && - ((node->reg.flags ^ nxt_node->reg.flags) & - KHUI_CNFLAG_SUBPANEL); + (((node->reg.flags ^ nxt_node->reg.flags) & + KHUI_CNFLAG_SUBPANEL) || + (nxt_node->flags & KHUI_CN_FLAG_DELETED)); nxt_node = LNEXT(nxt_node)); if (nxt_node) cfgui_hold_node(nxt_node); diff --git a/src/windows/identity/uilib/creddlg.c b/src/windows/identity/uilib/creddlg.c index 84d6e17ed..1d36d3c5b 100644 --- a/src/windows/identity/uilib/creddlg.c +++ b/src/windows/identity/uilib/creddlg.c @@ -57,6 +57,8 @@ khui_cw_create_cred_blob(khui_new_creds ** ppnc) c->result = KHUI_NC_RESULT_CANCEL; c->mode = KHUI_NC_MODE_MINI; + khui_context_create(&c->ctx, KHUI_SCOPE_NONE, NULL, KCDB_CREDTYPE_INVALID, NULL); + *ppnc = c; return KHM_ERROR_SUCCESS; diff --git a/src/windows/identity/uilib/khprops.h b/src/windows/identity/uilib/khprops.h index fc5629dc9..c0977b80c 100644 --- a/src/windows/identity/uilib/khprops.h +++ b/src/windows/identity/uilib/khprops.h @@ -27,6 +27,8 @@ #ifndef __KHIMAIRA_KHPROPS_H #define __KHIMAIRA_KHPROPS_H +#include + /********************************************************************* Property sheets **********************************************************************/