aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeffrey Altman <jaltman@secure-endpoints.com>2006-11-17 17:23:24 +0000
committerJeffrey Altman <jaltman@secure-endpoints.com>2006-11-17 17:23:24 +0000
commitf893735bf76cee0a7fea6bb092e4ee4bc84eac9c (patch)
treeb5e74aef9b42ba8e82de615e605c12468c341e4c
parent8dfa77032485a51aed1aafba747b27234875c423 (diff)
downloadkrb5-f893735bf76cee0a7fea6bb092e4ee4bc84eac9c.zip
krb5-f893735bf76cee0a7fea6bb092e4ee4bc84eac9c.tar.gz
krb5-f893735bf76cee0a7fea6bb092e4ee4bc84eac9c.tar.bz2
commits for KFW 3.1 Beta 4
KfW 3.1 beta 4 (NetIDMgr 1.1.6.0) nidmgr32.dll (1.1.6.0) - Fix a race condition where the initialization process might be flagged as complete even if the identity provider hasn't finished initialization yet. krb5cred.dll (1.1.6.0) - When assigning the default credentials cache for each identity, favor API and FILE caches over MSLSA if they exist. - When renewing an identity which was the result of importing credentials from the MSLSA cache, attempt to re-import the credentials from MSLSA instead of renewing the imported credentials. - Prevent possible crash if a Kerberos 5 context could not be obtained during the renewal operation. - Prevent memory leak in the credentials destroy handler due to the failure to free a Kerberos 5 context. - Properly match principals and realms when importing credentials from the MSLSA cache. - Determine the correct credentials cache to place imported credentials in by checking the configuration for preferred cache name. - Keep track of identities where credentials imports have occurred. - When setting the default identity, ignore the KRB5CCNAME environment variable. - Do not re-compute the credentials cache and timestamps when updating an identity. The cache and timestamp information is computed when listing credentials and do not change between listing and identity update. - When refreshing the default identity, also handle the case where the default credentials cache does not contain a principal, but the name of the cache can be used to infer the principal name. - Invoke a listing of credentials after a successful import. - Do not free a Kerberos 5 context prematurely during plug-in initialization. netidmgr.exe (1.1.6.0) - Fix the UI context logic to handle layouts which aren't based around identities. - Don't try to show a property sheet when there are no property pages supplied for the corresponding UI context. - Use consistent context menus. - Bring a modal dialog box to the foreground when it should be active. - Do not accept action triggers when the application is not ready to process actions yet. - Do not force the new credentials dialog to the top if there's already a modal dialog box showing. - Change the default per-identity layout to also group by location. ticket: new tags: pullup git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@18828 dc483132-0cff-0310-8789-dd5450dbe970
-rw-r--r--src/windows/identity/config/Makefile.w2k2
-rw-r--r--src/windows/identity/config/Makefile.w322
-rw-r--r--src/windows/identity/kcreddb/identity.c2
-rw-r--r--src/windows/identity/plugins/krb5/krb5funcs.c447
-rw-r--r--src/windows/identity/plugins/krb5/krb5funcs.h15
-rw-r--r--src/windows/identity/plugins/krb5/krb5identpro.c254
-rw-r--r--src/windows/identity/plugins/krb5/krb5main.c28
-rw-r--r--src/windows/identity/plugins/krb5/krb5newcreds.c13
-rw-r--r--src/windows/identity/plugins/krb5/krb5plugin.c6
-rw-r--r--src/windows/identity/plugins/krb5/krbcred.h7
-rw-r--r--src/windows/identity/ui/credwnd.c65
-rw-r--r--src/windows/identity/ui/main.c9
-rw-r--r--src/windows/identity/ui/mainwnd.c15
-rw-r--r--src/windows/identity/ui/newcredwnd.c11
-rw-r--r--src/windows/identity/ui/uiconfig.csv9
15 files changed, 679 insertions, 206 deletions
diff --git a/src/windows/identity/config/Makefile.w2k b/src/windows/identity/config/Makefile.w2k
index 9e62821..c3c7f03 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=4
+NETIDMGR_VERSION_PATCH=6
NETIDMGR_VERSION_AUX=0
NETIDMGR_RELEASEDESC=
diff --git a/src/windows/identity/config/Makefile.w32 b/src/windows/identity/config/Makefile.w32
index c63ed0d..e5bb18f 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=4
+NETIDMGR_VERSION_PATCH=6
NETIDMGR_VERSION_AUX=0
NETIDMGR_RELEASEDESC=
diff --git a/src/windows/identity/kcreddb/identity.c b/src/windows/identity/kcreddb/identity.c
index 3e9f394..6057b6f 100644
--- a/src/windows/identity/kcreddb/identity.c
+++ b/src/windows/identity/kcreddb/identity.c
@@ -64,7 +64,7 @@ kcdb_identity_set_provider(khm_handle sub)
kcdb_ident_sub = sub;
if (kcdb_ident_sub)
- kmq_post_sub_msg(kcdb_ident_sub,
+ kmq_send_sub_msg(kcdb_ident_sub,
KMSG_IDENT,
KMSG_IDENT_INIT,
0,
diff --git a/src/windows/identity/plugins/krb5/krb5funcs.c b/src/windows/identity/plugins/krb5/krb5funcs.c
index 331e789..0ce676c 100644
--- a/src/windows/identity/plugins/krb5/krb5funcs.c
+++ b/src/windows/identity/plugins/krb5/krb5funcs.c
@@ -36,6 +36,7 @@ modified and adapted for NetIDMgr */
#include <string.h>
#include <time.h>
+#include <stdlib.h>
#include <assert.h>
#include <strsafe.h>
@@ -199,6 +200,150 @@ int com_addr(void)
}
#endif
+/* we use these structures to keep track of identities that we find
+ while going through the API, FILE and MSLSA caches and enumerating
+ credentials. The only identities we want to keep track of are the
+ ones that have an initial ticket. We collect information for each
+ of the identities we find that we have initial tickets for and
+ then set the properties for the identities at once. */
+
+typedef struct tag_ident_data {
+ khm_handle ident; /* handle to the identity */
+ khm_int32 count; /* number of initial tickets we have
+ found for this identity. */
+ wchar_t ccname[MAX_PATH];
+ FILETIME ft_issue;
+ FILETIME ft_expire;
+ FILETIME ft_renewexpire;
+ khm_int32 krb5_flags;
+} ident_data;
+
+typedef struct tag_identlist {
+ ident_data * list;
+ khm_size n_list;
+ khm_size nc_list;
+} identlist;
+
+#define IDLIST_ALLOC_INCR 8
+
+static void
+tc_prep_idlist(identlist * idlist) {
+ idlist->list = NULL;
+ idlist->n_list = 0;
+ idlist->nc_list = 0;
+}
+
+static ident_data *
+tc_add_ident_to_list(identlist * idlist, khm_handle ident) {
+ khm_size i;
+ ident_data * d;
+
+ for (i=0; i < idlist->n_list; i++) {
+ if (kcdb_identity_is_equal(ident, idlist->list[i].ident))
+ break;
+ }
+
+ if (i < idlist->n_list) {
+ /* we already have this identity on our list. Increment the
+ count */
+ idlist->list[i].count++;
+ return &idlist->list[i];
+ }
+
+ /* it wasn't in our list. Add it */
+
+ if (idlist->n_list + 1 > idlist->nc_list) {
+ idlist->nc_list = UBOUNDSS(idlist->n_list + 1,
+ IDLIST_ALLOC_INCR,
+ IDLIST_ALLOC_INCR);
+#ifdef DEBUG
+ assert(idlist->n_list + 1 <= idlist->nc_list);
+#endif
+ idlist->list = PREALLOC(idlist->list,
+ sizeof(idlist->list[0]) * idlist->nc_list);
+#ifdef DEBUG
+ assert(idlist->list);
+#endif
+ ZeroMemory(&idlist->list[idlist->n_list],
+ sizeof(idlist->list[0]) *
+ (idlist->nc_list - idlist->n_list));
+ }
+
+ d = &idlist->list[idlist->n_list];
+
+ ZeroMemory(d, sizeof(*d));
+
+ d->ident = ident;
+ d->count = 1;
+
+ idlist->n_list++;
+
+ kcdb_identity_hold(ident);
+
+ return d;
+}
+
+static void
+tc_set_ident_data(identlist * idlist) {
+ khm_size i;
+
+ for (i=0; i < idlist->n_list; i++) {
+#ifdef DEBUG
+ assert(idlist->list[i].ident);
+#endif
+
+ kcdb_identity_set_attr(idlist->list[i].ident,
+ attr_id_krb5_ccname,
+ idlist->list[i].ccname,
+ KCDB_CBSIZE_AUTO);
+
+ kcdb_identity_set_attr(idlist->list[i].ident,
+ KCDB_ATTR_EXPIRE,
+ &idlist->list[i].ft_expire,
+ sizeof(idlist->list[i].ft_expire));
+
+ kcdb_identity_set_attr(idlist->list[i].ident,
+ KCDB_ATTR_ISSUE,
+ &idlist->list[i].ft_issue,
+ sizeof(idlist->list[i].ft_issue));
+
+ kcdb_identity_set_attr(idlist->list[i].ident,
+ attr_id_krb5_flags,
+ &idlist->list[i].krb5_flags,
+ sizeof(idlist->list[i].krb5_flags));
+
+ if (idlist->list[i].ft_renewexpire.dwLowDateTime == 0 &&
+ idlist->list[i].ft_renewexpire.dwHighDateTime == 0) {
+ kcdb_identity_set_attr(idlist->list[i].ident,
+ KCDB_ATTR_RENEW_EXPIRE,
+ NULL, 0);
+ } else {
+ kcdb_identity_set_attr(idlist->list[i].ident,
+ KCDB_ATTR_RENEW_EXPIRE,
+ &idlist->list[i].ft_renewexpire,
+ sizeof(idlist->list[i].ft_renewexpire));
+ }
+ }
+}
+
+static void
+tc_free_idlist(identlist * idlist) {
+ khm_size i;
+
+ for (i=0; i < idlist->n_list; i++) {
+ if (idlist->list[i].ident != NULL) {
+ kcdb_identity_release(idlist->list[i].ident);
+ idlist->list[i].ident = NULL;
+ }
+ }
+
+ if (idlist->list)
+ PFREE(idlist->list);
+ idlist->list = NULL;
+ idlist->n_list = 0;
+ idlist->nc_list = 0;
+}
+
#ifndef ENCTYPE_LOCAL_RC4_MD4
#define ENCTYPE_LOCAL_RC4_MD4 0xFFFFFF80
#endif
@@ -206,7 +351,8 @@ int com_addr(void)
#define MAX_ADDRS 256
static long get_tickets_from_cache(krb5_context ctx,
- krb5_ccache cache)
+ krb5_ccache cache,
+ identlist * idlist)
{
krb5_error_code code;
krb5_principal KRBv5Principal;
@@ -257,6 +403,8 @@ static long get_tickets_from_cache(krb5_context ctx,
}
}
+ _reportf(L"Getting tickets from cache [%s]", wcc_name);
+
if ((code = (*pkrb5_cc_set_flags)(ctx, cache, flags)))
{
if (code != KRB5_FCC_NOFILE && code != KRB5_CC_NOTFOUND)
@@ -305,6 +453,8 @@ static long get_tickets_from_cache(krb5_context ctx,
goto _exit;
}
+ _reportf(L"Found principal [%s]", wbuf);
+
(*pkrb5_free_principal)(ctx, KRBv5Principal);
if ((code = (*pkrb5_cc_start_seq_get)(ctx, cache, &KRBv5Cursor)))
@@ -478,12 +628,15 @@ static long get_tickets_from_cache(krb5_context ctx,
FILETIME ft_issue_new;
FILETIME ft_expire_old;
FILETIME ft_expire_new;
- khm_size cb;
+ ident_data * d;
- /* an initial ticket! If we find one, we generally set
- the lifetime, and primary ccache based on this, but
- only if this initial cred has a greater lifetime than
- the current primary credential. */
+ /* an initial ticket! Add it to the list of identities we
+ have seen so far with initial tickets. */
+ d = tc_add_ident_to_list(idlist, ident);
+#ifdef DEBUG
+ assert(d);
+ assert(d->count > 0);
+#endif
tt = KRBv5Credentials.times.endtime;
TimetToFileTime(tt, &ft_expire_new);
@@ -491,37 +644,40 @@ static long get_tickets_from_cache(krb5_context ctx,
tt = KRBv5Credentials.times.starttime;
TimetToFileTime(tt, &ft_issue_new);
- cb = sizeof(ft_expire_old);
- if(KHM_FAILED(kcdb_identity_get_attr(tident,
- KCDB_ATTR_EXPIRE,
- NULL, &ft_expire_old,
- &cb))
- || CompareFileTime(&ft_expire_new, &ft_expire_old) > 0) {
-
- kcdb_identity_set_attr(tident, attr_id_krb5_ccname,
- wcc_name, KCDB_CBSIZE_AUTO);
- kcdb_identity_set_attr(tident, KCDB_ATTR_EXPIRE,
- &ft_expire_new,
- sizeof(ft_expire_new));
- kcdb_identity_set_attr(tident, KCDB_ATTR_ISSUE,
- &ft_issue_new,
- sizeof(ft_issue_new));
+ /* so now, we have to set the properties of the identity
+ based on the properties of this credential under the
+ following circumstances:
+
+ - If this is the first time we are hitting this
+ identity.
+
+ - If this is not the MSLSA: cache and the expiry time
+ for this credential is longer than the time already
+ found for this identity.
+ */
+
+ ft_expire_old = d->ft_expire;
+
+ if(d->count == 1
+ || (CompareFileTime(&ft_expire_new, &ft_expire_old) > 0 &&
+ wcscmp(wcc_name, L"MSLSA:") != 0)) {
+
+ _reportf(L"Setting properties for identity (count=%d)", d->count);
+
+ StringCbCopy(d->ccname, sizeof(d->ccname),
+ wcc_name);
+ d->ft_expire = ft_expire_new;
+ d->ft_issue = ft_issue_new;
if (KRBv5Credentials.times.renew_till > 0) {
tt = KRBv5Credentials.times.renew_till;
TimetToFileTime(tt, &ft);
- kcdb_identity_set_attr(tident,
- KCDB_ATTR_RENEW_EXPIRE,
- &ft, sizeof(ft));
+ d->ft_renewexpire = ft;
} else {
- kcdb_identity_set_attr(tident,
- KCDB_ATTR_RENEW_EXPIRE,
- NULL, 0);
+ ZeroMemory(&d->ft_renewexpire, sizeof(d->ft_renewexpire));
}
- ti = KRBv5Credentials.ticket_flags;
- kcdb_identity_set_attr(tident, attr_id_krb5_flags,
- &ti, sizeof(ti));
+ d->krb5_flags = KRBv5Credentials.ticket_flags;
}
}
@@ -583,8 +739,10 @@ khm_krb5_list_tickets(krb5_context *krbv5Context)
khm_int32 t;
wchar_t * ms = NULL;
khm_size cb;
+ identlist idl;
kcdb_credset_flush(krb5_credset);
+ tc_prep_idlist(&idl);
if((*krbv5Context == 0) && (code = (*pkrb5_init_context)(krbv5Context))) {
goto _exit;
@@ -621,7 +779,7 @@ khm_krb5_list_tickets(krb5_context *krbv5Context)
if (code)
continue;
- code = get_tickets_from_cache(ctx, cache);
+ code = get_tickets_from_cache(ctx, cache, &idl);
if(ctx != NULL && cache != NULL)
(*pkrb5_cc_close)(ctx, cache);
@@ -631,18 +789,6 @@ khm_krb5_list_tickets(krb5_context *krbv5Context)
_skip_cc_iter:
- if (KHM_SUCCEEDED(khc_read_int32(csp_params, L"MsLsaList", &t)) && t) {
- code = (*pkrb5_cc_resolve)(ctx, "MSLSA:", &cache);
-
- if (code == 0 && cache) {
- code = get_tickets_from_cache(ctx, cache);
- }
-
- if (ctx != NULL && cache != NULL)
- (*pkrb5_cc_close)(ctx, cache);
- cache = 0;
- }
-
if (khc_read_multi_string(csp_params, L"FileCCList", NULL, &cb)
== KHM_ERROR_TOO_LONG &&
cb > sizeof(wchar_t) * 2) {
@@ -664,7 +810,7 @@ khm_krb5_list_tickets(krb5_context *krbv5Context)
if (code)
continue;
- code = get_tickets_from_cache(ctx, cache);
+ code = get_tickets_from_cache(ctx, cache, &idl);
if (ctx != NULL && cache != NULL)
(*pkrb5_cc_close)(ctx, cache);
@@ -674,6 +820,18 @@ khm_krb5_list_tickets(krb5_context *krbv5Context)
PFREE(ms);
}
+ if (KHM_SUCCEEDED(khc_read_int32(csp_params, L"MsLsaList", &t)) && t) {
+ code = (*pkrb5_cc_resolve)(ctx, "MSLSA:", &cache);
+
+ if (code == 0 && cache) {
+ code = get_tickets_from_cache(ctx, cache, &idl);
+ }
+
+ if (ctx != NULL && cache != NULL)
+ (*pkrb5_cc_close)(ctx, cache);
+ cache = 0;
+ }
+
_exit:
if (pNCi)
(*pcc_free_NC_info)(cc_ctx, &pNCi);
@@ -681,6 +839,8 @@ _exit:
(*pcc_shutdown)(&cc_ctx);
kcdb_credset_collect(NULL, krb5_credset, NULL, credtype_id_krb5, NULL);
+ tc_set_ident_data(&idl);
+ tc_free_idlist(&idl);
return(code);
}
@@ -842,12 +1002,34 @@ khm_krb5_renew_ident(khm_handle identity)
krb5_principal server = NULL;
krb5_creds my_creds;
krb5_data *realm = NULL;
+ wchar_t idname[KCDB_IDENT_MAXCCH_NAME];
+ char cidname[KCDB_IDENT_MAXCCH_NAME];
+ khm_size cb;
memset(&my_creds, 0, sizeof(krb5_creds));
if ( !pkrb5_init_context )
goto cleanup;
+ cb = sizeof(idname);
+ kcdb_identity_get_name(identity, idname, &cb);
+
+ if (khm_krb5_get_identity_flags(identity) & K5IDFLAG_IMPORTED) {
+ /* we are trying to renew the identity that was imported from
+ MSLSA: */
+ BOOL imported;
+
+ UnicodeStrToAnsi(cidname, sizeof(cidname), idname);
+
+ imported = khm_krb5_ms2mit(cidname, FALSE, TRUE);
+
+ if (imported)
+ goto cleanup;
+
+ /* if the import failed, then we try to renew the identity via
+ the usual procedure. */
+ }
+
code = khm_krb5_initialize(identity, &ctx, &cc);
if (code)
goto cleanup;
@@ -896,16 +1078,18 @@ cleanup:
if (my_creds.server == server)
my_creds.server = NULL;
- pkrb5_free_cred_contents(ctx, &my_creds);
+ if (ctx) {
+ pkrb5_free_cred_contents(ctx, &my_creds);
- if (me)
- pkrb5_free_principal(ctx, me);
- if (server)
- pkrb5_free_principal(ctx, server);
- if (cc)
- pkrb5_cc_close(ctx, cc);
- if (ctx)
+ if (me)
+ pkrb5_free_principal(ctx, me);
+ if (server)
+ pkrb5_free_principal(ctx, server);
+ if (cc)
+ pkrb5_cc_close(ctx, cc);
pkrb5_free_context(ctx);
+ }
+
return(code);
}
@@ -1356,7 +1540,7 @@ khm_krb5_destroy_by_credset(khm_handle p_cs)
khm_handle d_cs = NULL;
khm_int32 rv = KHM_ERROR_SUCCESS;
khm_size s, cb;
- krb5_context ctx;
+ krb5_context ctx = NULL;
krb5_error_code code = 0;
int i;
wchar_t ccname[KRB5_MAXCCH_CCNAME];
@@ -1636,6 +1820,9 @@ khm_krb5_destroy_by_credset(khm_handle p_cs)
if (d_cs)
kcdb_credset_delete(&d_cs);
+ if (ctx != NULL)
+ pkrb5_free_context(ctx);
+
return rv;
}
@@ -1727,7 +1914,7 @@ IsKerberosLogon(VOID)
BOOL
-khm_krb5_ms2mit(BOOL save_creds)
+khm_krb5_ms2mit(char * match_princ, BOOL match_realm, BOOL save_creds)
{
#ifdef NO_KRB5
return(FALSE);
@@ -1739,6 +1926,9 @@ khm_krb5_ms2mit(BOOL save_creds)
krb5_creds creds;
krb5_cc_cursor cursor=0;
krb5_principal princ = 0;
+ khm_handle ident = NULL;
+ wchar_t wname[KCDB_IDENT_MAXCCH_NAME];
+ char cname[KCDB_IDENT_MAXCCH_NAME];
char *cache_name = NULL;
char *princ_name = NULL;
BOOL rc = FALSE;
@@ -1765,10 +1955,89 @@ khm_krb5_ms2mit(BOOL save_creds)
if (code = pkrb5_unparse_name(kcontext, princ, &princ_name))
goto cleanup;
- kherr_reportf(L"Unparsed [%S]. Resolving target cache\n", princ_name);
- /* TODO: actually look up the preferred ccache name */
- if (code = pkrb5_cc_resolve(kcontext, princ_name, &ccache)) {
- kherr_reportf(L"Cannot resolve cache [%S] with code=%d. Trying default.\n", princ_name, code);
+ AnsiStrToUnicode(wname, sizeof(wname), princ_name);
+
+ kherr_reportf(L"Unparsed name [%s]", wname);
+
+ /* see if we have to match a specific principal */
+ if (match_princ != NULL) {
+ if (strcmp(princ_name, match_princ)) {
+ kherr_reportf(L"Principal mismatch. Wanted [%S], found [%S]",
+ match_princ, princ_name);
+ goto cleanup;
+ }
+ } else if (match_realm) {
+ wchar_t * wdefrealm;
+ char defrealm[256];
+ krb5_data * princ_realm;
+
+ wdefrealm = khm_krb5_get_default_realm();
+ if (wdefrealm == NULL) {
+ kherr_reportf(L"Can't determine default realm");
+ goto cleanup;
+ }
+
+ princ_realm = krb5_princ_realm(kcontext, princ);
+ UnicodeStrToAnsi(defrealm, sizeof(defrealm), wdefrealm);
+
+ if (strncmp(defrealm, princ_realm->data, princ_realm->length)) {
+ kherr_reportf(L"Realm mismatch. Wanted [%S], found [%*S]",
+ defrealm, princ_realm->length, princ_realm->data);
+ PFREE(wdefrealm);
+ goto cleanup;
+ }
+
+ PFREE(wdefrealm);
+ }
+
+ if (KHM_SUCCEEDED(kcdb_identity_create(wname,
+ KCDB_IDENT_FLAG_CREATE,
+ &ident))) {
+ khm_handle idconfig = NULL;
+ khm_handle k5config = NULL;
+ khm_size cb;
+
+ wname[0] = L'\0';
+
+ kcdb_identity_get_config(ident, 0, &idconfig);
+ if (idconfig == NULL)
+ goto _done_checking_config;
+
+ khc_open_space(idconfig, CSNAME_KRB5CRED, 0, &k5config);
+ if (k5config == NULL)
+ goto _done_checking_config;
+
+ cb = sizeof(wname);
+ khc_read_string(k5config,
+ L"DefaultCCName",
+ wname, &cb);
+
+ _done_checking_config:
+
+ if (idconfig)
+ khc_close_space(idconfig);
+ if (k5config)
+ khc_close_space(k5config);
+
+ if (wname[0]) {
+ UnicodeStrToAnsi(cname, sizeof(cname), wname);
+ } else {
+ StringCbPrintfA(cname, sizeof(cname), "API:%s", princ_name);
+ }
+
+ cache_name = cname;
+
+ } else {
+ /* the identity could not be created. we just use the
+ name of the principal as the ccache name. */
+ StringCbPrintfA(cname, sizeof(cname), "API:%s", princ_name);
+ cache_name = cname;
+ }
+
+ kherr_reportf(L"Resolving target cache [%S]\n", cache_name);
+
+ if (code = pkrb5_cc_resolve(kcontext, cache_name, &ccache)) {
+ kherr_reportf(L"Cannot resolve cache [%S] with code=%d. Trying default.\n", cache_name, code);
if (code = pkrb5_cc_default(kcontext, &ccache)) {
kherr_reportf(L"Failed to resolve default ccache. Code=%d", code);
@@ -1784,6 +2053,11 @@ khm_krb5_ms2mit(BOOL save_creds)
if (code = pkrb5_cc_copy_creds(kcontext, mslsa_ccache, ccache))
goto cleanup;
+ /* and mark the identity as having been imported */
+ if (ident) {
+ khm_krb5_set_identity_flags(ident, K5IDFLAG_IMPORTED, K5IDFLAG_IMPORTED);
+ }
+
rc = TRUE;
} else {
/* Enumerate tickets from cache looking for an initial ticket */
@@ -2078,7 +2352,7 @@ khm_krb5_get_realm_list(void)
\brief Get the default realm
A string will be returned that specifies the default realm. The
- caller should free the string using free().
+ caller should free the string using PFREE().
Returns NULL if the operation fails.
*/
@@ -2259,3 +2533,58 @@ khm_krb5_creds_is_equal(khm_handle vcred1, khm_handle vcred2, void * dummy) {
else
return 0;
}
+
+void
+khm_krb5_set_identity_flags(khm_handle identity,
+ khm_int32 flag_mask,
+ khm_int32 flag_value) {
+
+ khm_int32 t = 0;
+ khm_size cb;
+
+ cb = sizeof(t);
+ if (KHM_FAILED(kcdb_identity_get_attr(identity,
+ attr_id_krb5_idflags,
+ NULL,
+ &t, &cb))) {
+ t = 0;
+ }
+
+ t &= ~flag_mask;
+ t |= flag_value | flag_mask;
+
+ kcdb_identity_set_attr(identity,
+ attr_id_krb5_idflags,
+ &t, sizeof(t));
+}
+
+khm_int32
+khm_krb5_get_identity_flags(khm_handle identity) {
+ khm_int32 t = 0;
+ khm_size cb;
+
+ cb = sizeof(t);
+ kcdb_identity_get_attr(identity,
+ attr_id_krb5_idflags,
+ NULL, &t, &cb);
+
+ return t;
+}
+
+long
+khm_krb5_get_temp_ccache(krb5_context ctx,
+ krb5_ccache * prcc) {
+ int rnd = rand();
+ char ccname[MAX_PATH];
+ long code = 0;
+ krb5_ccache cc = 0;
+
+ StringCbPrintfA(ccname, sizeof(ccname), "API:TempCache%8x", rnd);
+
+ code = pkrb5_cc_resolve(ctx, ccname, &cc);
+
+ if (code == 0)
+ *prcc = cc;
+
+ return code;
+}
diff --git a/src/windows/identity/plugins/krb5/krb5funcs.h b/src/windows/identity/plugins/krb5/krb5funcs.h
index d699508..ece4f79 100644
--- a/src/windows/identity/plugins/krb5/krb5funcs.h
+++ b/src/windows/identity/plugins/krb5/krb5funcs.h
@@ -53,7 +53,9 @@
// Function Prototypes.
BOOL
-khm_krb5_ms2mit(BOOL);
+khm_krb5_ms2mit(char * match_princ,
+ BOOL match_realm,
+ BOOL save_creds);
int
khm_krb5_kinit(krb5_context alt_ctx,
@@ -130,4 +132,15 @@ khm_krb5_get_temp_profile_file(LPSTR confname, UINT szConfname);
khm_int32 KHMAPI
khm_krb5_creds_is_equal(khm_handle vcred1, khm_handle vcred2, void * dummy);
+void
+khm_krb5_set_identity_flags(khm_handle identity,
+ khm_int32 flag_mask,
+ khm_int32 flag_value);
+
+khm_int32
+khm_krb5_get_identity_flags(khm_handle identity);
+
+long
+khm_krb5_get_temp_ccache(krb5_context ctx,
+ krb5_ccache * cc);
#endif
diff --git a/src/windows/identity/plugins/krb5/krb5identpro.c b/src/windows/identity/plugins/krb5/krb5identpro.c
index 05f93fc..a8c91f9 100644
--- a/src/windows/identity/plugins/krb5/krb5identpro.c
+++ b/src/windows/identity/plugins/krb5/krb5identpro.c
@@ -807,149 +807,120 @@ k5_ident_set_default(khm_int32 msg_type,
khm_ui_4 uparam,
void * vparam) {
- /* Logic for setting the default identity:
-
- When setting identity I as the default;
-
- - If KRB5CCNAME is set
- - If I["Krb5CCName"] == %KRB5CCNAME%
- - do nothing
- - Else
- - Copy the contents of I["Krb5CCName"] to %KRB5CCNAME
- - Set I["Krb5CCName"] to %KRB5CCNAME
- - Else
- - Set HKCU\Software\MIT\kerberos5,ccname to
- "API:".I["Krb5CCName"]
+ /*
+ Currently, setting the default identity simply sets the
+ "ccname" registry value at "Software\MIT\kerberos5".
*/
if (uparam) {
/* an identity is being made default */
khm_handle def_ident = (khm_handle) vparam;
- wchar_t env_ccname[KRB5_MAXCCH_CCNAME];
wchar_t id_ccname[KRB5_MAXCCH_CCNAME];
khm_size cb;
DWORD dw;
LONG l;
+ HKEY hk_ccname;
+ DWORD dwType;
+ DWORD dwSize;
+ wchar_t reg_ccname[KRB5_MAXCCH_CCNAME];
+
+ assert(FALSE);
#ifdef DEBUG
assert(def_ident != NULL);
#endif
+ {
+ wchar_t idname[KCDB_IDENT_MAXCCH_NAME];
+ khm_size cb;
+
+ cb = sizeof(idname);
+ kcdb_identity_get_name(def_ident, idname, &cb);
+
+ _begin_task(0);
+ _report_cs1(KHERR_DEBUG_1, L"Setting default identity [%1!s!]", _cstr(idname));
+ _describe();
+ }
+
cb = sizeof(id_ccname);
if (KHM_FAILED(kcdb_identity_get_attr(def_ident,
attr_id_krb5_ccname,
NULL,
id_ccname,
- &cb)))
- return KHM_ERROR_UNKNOWN;
+ &cb))) {
+ _reportf(L"The specified identity does not have the Krb5CCName property");
+ _end_task();
+ return KHM_ERROR_NOT_FOUND;
+ }
khm_krb5_canon_cc_name(id_ccname, sizeof(id_ccname));
+ _reportf(L"Found Krb5CCName property : %s", id_ccname);
+
StringCbLength(id_ccname, sizeof(id_ccname), &cb);
cb += sizeof(wchar_t);
- dw = GetEnvironmentVariable(L"KRB5CCNAME",
- env_ccname,
- ARRAYLENGTH(env_ccname));
-
- if (dw == 0 &&
- GetLastError() == ERROR_ENVVAR_NOT_FOUND) {
- /* KRB5CCNAME not set */
- HKEY hk_ccname;
- DWORD dwType;
- DWORD dwSize;
- wchar_t reg_ccname[KRB5_MAXCCH_CCNAME];
-
- l = RegOpenKeyEx(HKEY_CURRENT_USER,
- L"Software\\MIT\\kerberos5",
- 0,
- KEY_READ | KEY_WRITE,
- &hk_ccname);
-
- if (l != ERROR_SUCCESS)
- l = RegCreateKeyEx(HKEY_CURRENT_USER,
- L"Software\\MIT\\kerberos5",
- 0,
- NULL,
- REG_OPTION_NON_VOLATILE,
- KEY_READ | KEY_WRITE,
- NULL,
- &hk_ccname,
- &dw);
-
- if (l != ERROR_SUCCESS)
- return KHM_ERROR_UNKNOWN;
-
- dwSize = sizeof(reg_ccname);
+ _reportf(L"Setting default CC name in the registry");
+
+ l = RegOpenKeyEx(HKEY_CURRENT_USER,
+ L"Software\\MIT\\kerberos5",
+ 0,
+ KEY_READ | KEY_WRITE,
+ &hk_ccname);
+
+ if (l != ERROR_SUCCESS)
+ l = RegCreateKeyEx(HKEY_CURRENT_USER,
+ L"Software\\MIT\\kerberos5",
+ 0,
+ NULL,
+ REG_OPTION_NON_VOLATILE,
+ KEY_READ | KEY_WRITE,
+ NULL,
+ &hk_ccname,
+ &dw);
- l = RegQueryValueEx(hk_ccname,
- L"ccname",
- NULL,
- &dwType,
- (LPBYTE) reg_ccname,
- &dwSize);
+ if (l != ERROR_SUCCESS) {
+ _reportf(L"Can't create registry key : %d", l);
+ _end_task();
+ return KHM_ERROR_UNKNOWN;
+ }
- if (l != ERROR_SUCCESS ||
- dwType != REG_SZ ||
- khm_krb5_cc_name_cmp(reg_ccname, id_ccname)) {
+ dwSize = sizeof(reg_ccname);
- /* we have to write the new value in */
+ l = RegQueryValueEx(hk_ccname,
+ L"ccname",
+ NULL,
+ &dwType,
+ (LPBYTE) reg_ccname,
+ &dwSize);
- l = RegSetValueEx(hk_ccname,
- L"ccname",
- 0,
- REG_SZ,
- (BYTE *) id_ccname,
- (DWORD) cb);
- }
+ if (l != ERROR_SUCCESS ||
+ dwType != REG_SZ ||
+ khm_krb5_cc_name_cmp(reg_ccname, id_ccname)) {
- RegCloseKey(hk_ccname);
+ /* we have to write the new value in */
+
+ l = RegSetValueEx(hk_ccname,
+ L"ccname",
+ 0,
+ REG_SZ,
+ (BYTE *) id_ccname,
+ (DWORD) cb);
+ }
- if (l == ERROR_SUCCESS) {
- k5_update_last_default_identity(def_ident);
- return KHM_ERROR_SUCCESS;
- } else
- return KHM_ERROR_UNKNOWN;
+ RegCloseKey(hk_ccname);
- } else if (dw > ARRAYLENGTH(env_ccname)) {
- /* buffer was not enough */
-#ifdef DEBUG
- assert(FALSE);
-#else
- return KHM_ERROR_UNKNOWN;
-#endif
+ if (l == ERROR_SUCCESS) {
+ _reportf(L"Successfully set the default ccache");
+ k5_update_last_default_identity(def_ident);
+ _end_task();
+ return KHM_ERROR_SUCCESS;
} else {
- /* KRB5CCNAME is set */
- long code;
- krb5_context ctx;
-
- /* if the %KRB5CCNAME is the same as the identity
- ccache, then it is already the default. */
- if (!khm_krb5_cc_name_cmp(id_ccname, env_ccname)) {
- k5_update_last_default_identity(def_ident);
- return KHM_ERROR_SUCCESS;
- }
-
- /* if not, we have to copy the contents of id_ccname
- to env_ccname */
- code = pkrb5_init_context(&ctx);
- if (code)
- return KHM_ERROR_UNKNOWN;
-
- code = khm_krb5_copy_ccache_by_name(ctx,
- env_ccname,
- id_ccname);
-
- if (code == 0) {
- k5_update_last_default_identity(def_ident);
- khm_krb5_list_tickets(&ctx);
- }
-
- if (ctx)
- pkrb5_free_context(ctx);
-
- return (code == 0)?KHM_ERROR_SUCCESS:KHM_ERROR_UNKNOWN;
+ _reportf(L"Can't set the registry value : %d", l);
+ _end_task();
+ return KHM_ERROR_UNKNOWN;
}
+
} else {
/* the default identity is being forgotten */
@@ -1061,6 +1032,11 @@ struct k5_ident_update_data {
khm_int32 k5_flags;
};
+/* The logic here has to reflect the logic in khm_krb5_list_tickets().
+ We use this to handle an identity update request because some other
+ plug-in or maybe NetIDMgr itself is about to do something
+ important(tm) with the identity and needs to make sure that the
+ properties of the identity are up-to-date. */
static khm_int32 KHMAPI
k5_ident_update_apply_proc(khm_handle cred,
void * rock) {
@@ -1149,7 +1125,9 @@ k5_ident_update(khm_int32 msg_type,
khm_ui_4 uparam,
void * vparam) {
+#if 0
struct k5_ident_update_data d;
+#endif
khm_handle ident;
khm_handle tident;
krb5_ccache cc = NULL;
@@ -1163,6 +1141,13 @@ k5_ident_update(khm_int32 msg_type,
if (ident == NULL)
return KHM_ERROR_SUCCESS;
+#if 0
+ /* we are going to skip doing this here since
+ khm_krb5_list_tickets() performs this function for us each time
+ we enumerate tickets. Since it also gets run each time our
+ list of tickets changes and since we are basing this operation
+ on existing tickets, we are unlikely to find anything new
+ here. */
ZeroMemory(&d, sizeof(d));
d.identity = ident;
@@ -1209,6 +1194,7 @@ k5_ident_update(khm_int32 msg_type,
kcdb_identity_set_attr(ident, attr_id_krb5_flags, NULL, 0);
kcdb_identity_set_attr(ident, attr_id_krb5_ccname, NULL, 0);
}
+#endif
if (KHM_SUCCEEDED(kcdb_identity_get_default(&tident))) {
kcdb_identity_release(tident);
@@ -1258,18 +1244,54 @@ k5_refresh_default_identity(krb5_context ctx) {
krb5_principal princ = NULL;
char * princ_nameA = NULL;
wchar_t princ_nameW[KCDB_IDENT_MAXCCH_NAME];
+ char * ccname = NULL;
khm_handle ident = NULL;
khm_boolean found_default = FALSE;
assert(ctx != NULL);
+ _begin_task(0);
+ _report_cs0(KHERR_DEBUG_1, L"Refreshing default identity");
+ _describe();
+
code = pkrb5_cc_default(ctx, &cc);
- if (code)
+ if (code) {
+ _reportf(L"Can't open default ccache. code=%d", code);
goto _nc_cleanup;
+ }
code = pkrb5_cc_get_principal(ctx, cc, &princ);
- if (code)
+ if (code) {
+ /* try to determine the identity from the ccache name */
+ ccname = pkrb5_cc_get_name(ctx, cc);
+
+ if (ccname) {
+ char * namepart = strchr(ccname, ':');
+
+ _reportf(L"CC name is [%S]", ccname);
+
+ if (namepart == NULL)
+ namepart = ccname;
+ else
+ namepart++;
+
+ _reportf(L"Checking if [%S] is a valid identity name", namepart);
+
+ AnsiStrToUnicode(princ_nameW, sizeof(princ_nameW), namepart);
+ if (kcdb_identity_is_valid_name(princ_nameW)) {
+ kcdb_identity_create(princ_nameW, KCDB_IDENT_FLAG_CREATE, &ident);
+ if (ident) {
+ _reportf(L"Setting [%S] as the default identity", namepart);
+ kcdb_identity_set_default_int(ident);
+ found_default = TRUE;
+ }
+ }
+ } else {
+ _reportf(L"Can't determine ccache name");
+ }
+
goto _nc_cleanup;
+ }
code = pkrb5_unparse_name(ctx, princ, &princ_nameA);
if (code)
@@ -1277,14 +1299,22 @@ k5_refresh_default_identity(krb5_context ctx) {
AnsiStrToUnicode(princ_nameW, sizeof(princ_nameW), princ_nameA);
- if (KHM_FAILED(kcdb_identity_create(princ_nameW, 0, &ident)))
+ _reportf(L"Found principal [%s]", princ_nameW);
+
+ if (KHM_FAILED(kcdb_identity_create(princ_nameW, KCDB_IDENT_FLAG_CREATE, &ident))) {
+ _reportf(L"Failed to create identity");
goto _nc_cleanup;
+ }
+ _reportf(L"Setting default identity to [%s]", princ_nameW);
kcdb_identity_set_default_int(ident);
found_default = TRUE;
_nc_cleanup:
+
+ _end_task();
+
if (princ_nameA)
pkrb5_free_unparsed_name(ctx, princ_nameA);
diff --git a/src/windows/identity/plugins/krb5/krb5main.c b/src/windows/identity/plugins/krb5/krb5main.c
index f1b7f05..3d2f2c0 100644
--- a/src/windows/identity/plugins/krb5/krb5main.c
+++ b/src/windows/identity/plugins/krb5/krb5main.c
@@ -50,6 +50,7 @@ khm_int32 attr_id_addr_list = -1;
khm_int32 attr_id_krb5_flags = -1;
khm_int32 attr_id_krb5_ccname = -1;
khm_int32 attr_id_kvno = -1;
+khm_int32 attr_id_krb5_idflags = -1;
BOOL attr_regd_key_enctype = FALSE;
BOOL attr_regd_tkt_enctype = FALSE;
@@ -57,6 +58,7 @@ BOOL attr_regd_addr_list = FALSE;
BOOL attr_regd_krb5_flags = FALSE;
BOOL attr_regd_krb5_ccname = FALSE;
BOOL attr_regd_kvno = FALSE;
+BOOL attr_regd_krb5_idflags = FALSE;
khm_handle csp_plugins = NULL;
khm_handle csp_krbcred = NULL;
@@ -383,6 +385,30 @@ KHMEXP khm_int32 KHMAPI init_module(kmm_module h_module) {
attr_regd_kvno = TRUE;
}
+ if (KHM_FAILED(kcdb_attrib_get_id(ATTRNAME_KRB5_IDFLAGS, &attr_id_krb5_idflags))) {
+ kcdb_attrib attrib;
+
+ ZeroMemory(&attrib, sizeof(attrib));
+
+ attrib.name = ATTRNAME_KRB5_IDFLAGS;
+ attrib.id = KCDB_ATTR_INVALID;
+ attrib.type = KCDB_TYPE_INT32;
+ attrib.flags = KCDB_ATTR_FLAG_PROPERTY |
+ KCDB_ATTR_FLAG_HIDDEN;
+ /* we don't bother localizing these strings since the
+ attribute is hidden. The user will not see these
+ descriptions anyway. */
+ attrib.short_desc = L"Krb5 ID flags";
+ attrib.long_desc = L"Kerberos 5 Identity Flags";
+
+ rv = kcdb_attrib_register(&attrib, &attr_id_krb5_idflags);
+
+ if (KHM_FAILED(rv))
+ goto _exit;
+
+ attr_regd_krb5_idflags = TRUE;
+ }
+
rv = kmm_get_plugins_config(0, &csp_plugins);
if(KHM_FAILED(rv)) goto _exit;
@@ -416,6 +442,8 @@ KHMEXP khm_int32 KHMAPI exit_module(kmm_module h_module) {
kcdb_attrib_unregister(attr_id_krb5_ccname);
if(attr_regd_kvno)
kcdb_attrib_unregister(attr_id_kvno);
+ if(attr_regd_krb5_idflags)
+ kcdb_attrib_unregister(attr_id_krb5_idflags);
if(type_regd_enctype)
kcdb_type_unregister(type_id_enctype);
diff --git a/src/windows/identity/plugins/krb5/krb5newcreds.c b/src/windows/identity/plugins/krb5/krb5newcreds.c
index 1bff68e..9be8c89 100644
--- a/src/windows/identity/plugins/krb5/krb5newcreds.c
+++ b/src/windows/identity/plugins/krb5/krb5newcreds.c
@@ -2801,8 +2801,17 @@ k5_msg_cred_dialog(khm_int32 msg_type,
#endif
khc_read_int32(csp_params, L"MsLsaImport", &t);
- if (t == 1)
- khm_krb5_ms2mit(TRUE);
+ if (t != K5_LSAIMPORT_NEVER) {
+ krb5_context ctx = NULL;
+ BOOL imported;
+
+ imported = khm_krb5_ms2mit(NULL, (t == K5_LSAIMPORT_MATCH), TRUE);
+ if (imported) {
+ khm_krb5_list_tickets(&ctx);
+ if (ctx)
+ pkrb5_free_context(ctx);
+ }
+ }
}
break;
}
diff --git a/src/windows/identity/plugins/krb5/krb5plugin.c b/src/windows/identity/plugins/krb5/krb5plugin.c
index e80e01c..bb481e0 100644
--- a/src/windows/identity/plugins/krb5/krb5plugin.c
+++ b/src/windows/identity/plugins/krb5/krb5plugin.c
@@ -111,9 +111,6 @@ k5_msg_system(khm_int32 msg_type, khm_int32 msg_subtype,
krb5_initialized = TRUE;
- if(ctx != NULL)
- pkrb5_free_context(ctx);
-
/* now convert this thread to a fiber and create a
separate fiber to do kinit stuff */
k5_main_fiber = ConvertThreadToFiber(NULL);
@@ -126,6 +123,9 @@ k5_msg_system(khm_int32 msg_type, khm_int32 msg_subtype,
k5_register_config_panels();
khm_krb5_list_tickets(&ctx);
+
+ if(ctx != NULL)
+ pkrb5_free_context(ctx);
}
}
break;
diff --git a/src/windows/identity/plugins/krb5/krbcred.h b/src/windows/identity/plugins/krb5/krbcred.h
index 694323c..44b7733 100644
--- a/src/windows/identity/plugins/krb5/krbcred.h
+++ b/src/windows/identity/plugins/krb5/krbcred.h
@@ -64,6 +64,12 @@ typedef enum tag_k5_lsa_import {
#define ATTRNAME_KRB5_FLAGS L"Krb5Flags"
#define ATTRNAME_KRB5_CCNAME L"Krb5CCName"
#define ATTRNAME_KVNO L"Kvno"
+#define ATTRNAME_KRB5_IDFLAGS L"Krb5IDFlags"
+
+/* Flag bits for Krb5IDFlags property */
+
+/* identity was imported from MSLSA: */
+#define K5IDFLAG_IMPORTED 0x00000001
void init_krb();
void exit_krb();
@@ -90,6 +96,7 @@ extern khm_int32 attr_id_addr_list;
extern khm_int32 attr_id_krb5_flags;
extern khm_int32 attr_id_krb5_ccname;
extern khm_int32 attr_id_kvno;
+extern khm_int32 attr_id_krb5_idflags;
extern khm_ui_4 k5_commctl_version;
diff --git a/src/windows/identity/ui/credwnd.c b/src/windows/identity/ui/credwnd.c
index 36e0572..c9b314b 100644
--- a/src/windows/identity/ui/credwnd.c
+++ b/src/windows/identity/ui/credwnd.c
@@ -2981,15 +2981,7 @@ cw_set_row_context(khui_credwnd_tbl * tbl, int row)
o = (khui_credwnd_outline *) tbl->rows[row].data;
if (tbl->cols[o->col].attr_id == KCDB_ATTR_ID_NAME) {
- if (TPARENT(o) == NULL) { /* selected an identity */
- khui_context_set(KHUI_SCOPE_IDENT,
- (khm_handle) o->data,
- KCDB_CREDTYPE_INVALID,
- NULL,
- NULL,
- 0,
- tbl->credset);
- } else {
+ if (TPARENT(o) != NULL) {
khui_credwnd_outline * op;
op = TPARENT(o);
@@ -3005,8 +2997,30 @@ cw_set_row_context(khui_credwnd_tbl * tbl, int row)
0,
tbl->credset);
} else {
- set_context = FALSE;
+ /* we can't narrow it down using the standard set
+ of scopes. We consider this to be an identity
+ selection because the user right-clicked on an
+ identity header. */
+ khui_context_set(KHUI_SCOPE_IDENT,
+ (khm_handle) o->data,
+ KCDB_CREDTYPE_INVALID,
+ NULL,
+ NULL,
+ 0,
+ tbl->credset);
}
+ } else {
+ /* The user clicked on an identity header. Even
+ though not all credentials belonging to the
+ identity maybe within the scope right now, we still
+ consider this to be an identity scope. */
+ khui_context_set(KHUI_SCOPE_IDENT,
+ (khm_handle) o->data,
+ KCDB_CREDTYPE_INVALID,
+ NULL,
+ NULL,
+ 0,
+ tbl->credset);
}
} else if (tbl->cols[o->col].attr_id == KCDB_ATTR_TYPE_NAME) {
if (TPARENT(o) == NULL) {
@@ -3022,9 +3036,12 @@ cw_set_row_context(khui_credwnd_tbl * tbl, int row)
khui_credwnd_outline * op;
op = TPARENT(o);
- if (tbl->cols[op->col].attr_id == KCDB_ATTR_ID_NAME &&
- TPARENT(op) == NULL) {
- /* credtype under an identity */
+ if (tbl->cols[op->col].attr_id == KCDB_ATTR_ID_NAME) {
+ /* credtype under an identity. Even though not
+ all the credentials of this credtype belonging
+ to this identity might be within the scope, we
+ still consider this to be a type selection
+ under a specific identity. */
khui_context_set(KHUI_SCOPE_CREDTYPE,
(khm_handle) op->data,
(khm_int32) (DWORD_PTR) o->data,
@@ -4051,6 +4068,16 @@ cw_properties(HWND hwnd)
khm_size t = 0;
khm_int32 cred_type;
+ if (ctx.identity == NULL) {
+ /* currently, we can't show a property sheet at this point
+ since most credentials providers don't provide a
+ property sheet that works without an identity. */
+
+ khui_context_release(&ctx);
+ khui_ps_destroy_sheet(ps);
+ return TRUE;
+ }
+
cred_type = ctx.cred_type;
ps->header.hInstance = khm_hInstance;
@@ -4073,6 +4100,8 @@ cw_properties(HWND hwnd)
ps->header.pszCaption = NULL;
}
} else {
+ /* we don't actually reach here since we handle this case
+ above */
kcdb_credtype_describe(cred_type, NULL, &t, KCDB_TS_LONG);
if(t > 0) {
ps->header.pszCaption = PMALLOC(t);
@@ -4488,15 +4517,21 @@ cw_wm_contextmenu(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
cw_set_row_context(tbl, row);
+ khm_menu_show_panel(KHUI_MENU_IDENT_CTX, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
+
+#if 0
+ /* calling cw_set_row_context() should take care of enabling or
+ disabling actions as appropriate. We don't need to
+ differentiate between IDENT_CTX and TOK_CTX here. */
if((tbl->rows[row].flags & KHUI_CW_ROW_HEADER) &&
- (tbl->cols[tbl->rows[row].col].attr_id == KCDB_ATTR_ID_NAME))
- {
+ (tbl->cols[tbl->rows[row].col].attr_id == KCDB_ATTR_ID_NAME)) {
khm_menu_show_panel(KHUI_MENU_IDENT_CTX, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
//khui_context_reset();
} else {
khm_menu_show_panel(KHUI_MENU_TOK_CTX, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
//khui_context_reset();
}
+#endif
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
diff --git a/src/windows/identity/ui/main.c b/src/windows/identity/ui/main.c
index 80b7be3..e221078 100644
--- a/src/windows/identity/ui/main.c
+++ b/src/windows/identity/ui/main.c
@@ -192,12 +192,11 @@ void khm_add_dialog(HWND dlg) {
meaningful value until we enter a modal loop */
khui_dialogs[n_khui_dialogs].active = FALSE;
n_khui_dialogs++;
- }
+ } else {
#if DEBUG
- else {
- assert(FALSE);
- }
+ assert(FALSE);
#endif
+ }
}
/* should only be called from the UI thread */
@@ -254,6 +253,8 @@ void khm_enter_modal(HWND hwnd) {
EnableWindow(khm_hwnd_main, FALSE);
khui_modal_dialog = hwnd;
+
+ SetForegroundWindow(hwnd);
}
}
diff --git a/src/windows/identity/ui/mainwnd.c b/src/windows/identity/ui/mainwnd.c
index c03d47f..eba23e4 100644
--- a/src/windows/identity/ui/mainwnd.c
+++ b/src/windows/identity/ui/mainwnd.c
@@ -226,22 +226,37 @@ khm_main_wnd_proc(HWND hwnd,
return 0;
case KHUI_ACTION_PASSWD_ID:
+ if (khm_startup.processing)
+ return 0;
+
khm_cred_change_password(NULL);
return 0;
case KHUI_ACTION_NEW_CRED:
+ if (khm_startup.processing)
+ return 0;
+
khm_cred_obtain_new_creds(NULL);
return 0;
case KHUI_ACTION_RENEW_CRED:
+ if (khm_startup.processing)
+ return 0;
+
khm_cred_renew_creds();
return 0;
case KHUI_ACTION_DESTROY_CRED:
+ if (khm_startup.processing)
+ return 0;
+
khm_cred_destroy_creds(FALSE, FALSE);
return 0;
case KHUI_ACTION_SET_DEF_ID:
+ if (khm_startup.processing)
+ return 0;
+
khm_cred_set_default();
return 0;
diff --git a/src/windows/identity/ui/newcredwnd.c b/src/windows/identity/ui/newcredwnd.c
index a0472e2..7bad1e2 100644
--- a/src/windows/identity/ui/newcredwnd.c
+++ b/src/windows/identity/ui/newcredwnd.c
@@ -819,14 +819,12 @@ nc_handle_wm_create(HWND hwnd,
#endif
/* we defer the creation of the tab buttons for later */
- /* add this to the dialog chain */
- khm_add_dialog(hwnd);
-
/* bring the window to the top, if necessary */
if (KHM_SUCCEEDED(khc_read_int32(NULL,
L"CredWindow\\Windows\\NewCred\\ForceToTop",
&t)) &&
- t != 0) {
+ t != 0 &&
+ !khm_is_dialog_active()) {
/* if the main window is not visible, then the SetWindowPos()
call is sufficient to bring the new creds window to the
@@ -840,6 +838,9 @@ nc_handle_wm_create(HWND hwnd,
}
+ /* add this to the dialog chain */
+ khm_add_dialog(hwnd);
+
return TRUE;
}
@@ -1431,7 +1432,7 @@ static LRESULT nc_handle_wm_nc_notify(HWND hwnd,
nc_update_credtext(d);
- ShowWindow(hwnd, SW_SHOW);
+ ShowWindow(hwnd, SW_SHOWNOACTIVATE);
SetFocus(hwnd);
if (d->nc->n_identities == 0)
diff --git a/src/windows/identity/ui/uiconfig.csv b/src/windows/identity/ui/uiconfig.csv
index f1bb4b1..9f5e5e4 100644
--- a/src/windows/identity/ui/uiconfig.csv
+++ b/src/windows/identity/ui/uiconfig.csv
@@ -71,7 +71,7 @@ CredWindow,KC_SPACE,0,Options for the credentials window
Custom_0,KC_ENDSPACE,0,
ByIdentity,KC_SPACE,0,The default view
Description,KC_STRING,View grouped by identity and credential type,
- ColumnList,KC_STRING,"_CWFlags,IdentityName,TypeName,Name,TimeLeft",
+ ColumnList,KC_STRING,"_CWFlags,IdentityName,TypeName,Location,Name,TimeLeft",
Columns,KC_SPACE,0,Columns
_CWFlags,KC_SPACE,0,
Width,KC_INT32,20,
@@ -87,9 +87,14 @@ CredWindow,KC_SPACE,0,Options for the credentials window
SortIndex,KC_INT32,1
Flags,KC_INT32,11
TypeName,KC_ENDSPACE,0
+ Location,KC_SPACE,0,
+ Width,KC_INT32,50
+ SortIndex,KC_INT32,2
+ Flags,KC_INT32,11
+ Location,KC_ENDSPACE,0,
Name,KC_SPACE,0
Width,KC_INT32,200
- SortIndex,KC_INT32,2
+ SortIndex,KC_INT32,3
Flags,KC_INT32,3
Name,KC_ENDSPACE,0
TimeLeft,KC_SPACE,0