commits for KFW 3.1 Beta 4
authorJeffrey Altman <jaltman@secure-endpoints.com>
Fri, 17 Nov 2006 17:23:24 +0000 (17:23 +0000)
committerJeffrey Altman <jaltman@secure-endpoints.com>
Fri, 17 Nov 2006 17:23:24 +0000 (17:23 +0000)
     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

15 files changed:
src/windows/identity/config/Makefile.w2k
src/windows/identity/config/Makefile.w32
src/windows/identity/kcreddb/identity.c
src/windows/identity/plugins/krb5/krb5funcs.c
src/windows/identity/plugins/krb5/krb5funcs.h
src/windows/identity/plugins/krb5/krb5identpro.c
src/windows/identity/plugins/krb5/krb5main.c
src/windows/identity/plugins/krb5/krb5newcreds.c
src/windows/identity/plugins/krb5/krb5plugin.c
src/windows/identity/plugins/krb5/krbcred.h
src/windows/identity/ui/credwnd.c
src/windows/identity/ui/main.c
src/windows/identity/ui/mainwnd.c
src/windows/identity/ui/newcredwnd.c
src/windows/identity/ui/uiconfig.csv

index 9e62821ba08d60dbeba0602f935c9e959e61666f..c3c7f030f91050d802981f0fab54ee417be4fa21 100644 (file)
@@ -47,7 +47,7 @@ KHIMAIRA_WIN32_CONFIG=1
 # Version info\r
 NETIDMGR_VERSION_MAJOR=1\r
 NETIDMGR_VERSION_MINOR=1\r
-NETIDMGR_VERSION_PATCH=4\r
+NETIDMGR_VERSION_PATCH=6\r
 NETIDMGR_VERSION_AUX=0\r
 NETIDMGR_RELEASEDESC=\r
 \r
index c63ed0d117bf3c119a136779b0e3d81456c8dde8..e5bb18f9a946e538a117129729d5ded66fadae10 100644 (file)
@@ -47,7 +47,7 @@ KHIMAIRA_WIN32_CONFIG=1
 # Version info\r
 NETIDMGR_VERSION_MAJOR=1\r
 NETIDMGR_VERSION_MINOR=1\r
-NETIDMGR_VERSION_PATCH=4\r
+NETIDMGR_VERSION_PATCH=6\r
 NETIDMGR_VERSION_AUX=0\r
 NETIDMGR_RELEASEDESC=\r
 \r
index 3e9f394ec137130887ff72c7cabff9dfdb068015..6057b6f2c238a5cee70da9ae4f7f76731c0d0b90 100644 (file)
@@ -64,7 +64,7 @@ kcdb_identity_set_provider(khm_handle sub)
         kcdb_ident_sub = sub;\r
 \r
         if (kcdb_ident_sub)\r
-            kmq_post_sub_msg(kcdb_ident_sub,\r
+            kmq_send_sub_msg(kcdb_ident_sub,\r
                              KMSG_IDENT,\r
                              KMSG_IDENT_INIT,\r
                              0,\r
index 331e789dcda531572c94bf5bc7cd713129bcc2af..0ce676caf99530403995d2317f46a352354b8e90 100644 (file)
@@ -36,6 +36,7 @@ modified and adapted for NetIDMgr */
 \r
 #include <string.h>\r
 #include <time.h>\r
+#include <stdlib.h>\r
 #include <assert.h>\r
 #include <strsafe.h>\r
 \r
@@ -199,6 +200,150 @@ int com_addr(void)
 } \r
 #endif\r
 \r
+/* we use these structures to keep track of identities that we find\r
+   while going through the API, FILE and MSLSA caches and enumerating\r
+   credentials.  The only identities we want to keep track of are the\r
+   ones that have an initial ticket.  We collect information for each\r
+   of the identities we find that we have initial tickets for and\r
+   then set the properties for the identities at once. */\r
+\r
+typedef struct tag_ident_data {\r
+    khm_handle  ident;          /* handle to the identity */\r
+    khm_int32 count;            /* number of initial tickets we have\r
+                                   found for this identity. */\r
+    wchar_t   ccname[MAX_PATH];\r
+    FILETIME  ft_issue;\r
+    FILETIME  ft_expire;\r
+    FILETIME  ft_renewexpire;\r
+    khm_int32 krb5_flags;\r
+} ident_data;\r
+\r
+typedef struct tag_identlist {\r
+    ident_data * list;\r
+    khm_size     n_list;\r
+    khm_size     nc_list;\r
+} identlist;\r
+\r
+#define IDLIST_ALLOC_INCR 8\r
+\r
+static void\r
+tc_prep_idlist(identlist * idlist) {\r
+    idlist->list = NULL;\r
+    idlist->n_list = 0;\r
+    idlist->nc_list = 0;\r
+}\r
+\r
+static ident_data *\r
+tc_add_ident_to_list(identlist * idlist, khm_handle ident) {\r
+    khm_size i;\r
+    ident_data * d;\r
+\r
+    for (i=0; i < idlist->n_list; i++) {\r
+        if (kcdb_identity_is_equal(ident, idlist->list[i].ident))\r
+            break;\r
+    }\r
+\r
+    if (i < idlist->n_list) {\r
+        /* we already have this identity on our list.  Increment the\r
+           count */\r
+        idlist->list[i].count++;\r
+        return &idlist->list[i];\r
+    }\r
+\r
+    /* it wasn't in our list.  Add it */\r
+\r
+    if (idlist->n_list + 1 > idlist->nc_list) {\r
+        idlist->nc_list = UBOUNDSS(idlist->n_list + 1,\r
+                                   IDLIST_ALLOC_INCR,\r
+                                   IDLIST_ALLOC_INCR);\r
+#ifdef DEBUG\r
+        assert(idlist->n_list + 1 <= idlist->nc_list);\r
+#endif\r
+        idlist->list = PREALLOC(idlist->list,\r
+                                sizeof(idlist->list[0]) * idlist->nc_list);\r
+#ifdef DEBUG\r
+        assert(idlist->list);\r
+#endif\r
+        ZeroMemory(&idlist->list[idlist->n_list],\r
+                   sizeof(idlist->list[0]) *\r
+                   (idlist->nc_list - idlist->n_list));\r
+    }\r
+\r
+    d = &idlist->list[idlist->n_list];\r
+\r
+    ZeroMemory(d, sizeof(*d));\r
+\r
+    d->ident = ident;\r
+    d->count = 1;\r
+\r
+    idlist->n_list++;\r
+\r
+    kcdb_identity_hold(ident);\r
+\r
+    return d;\r
+}\r
+\r
+static void\r
+tc_set_ident_data(identlist * idlist) {\r
+    khm_size i;\r
+\r
+    for (i=0; i < idlist->n_list; i++) {\r
+#ifdef DEBUG\r
+        assert(idlist->list[i].ident);\r
+#endif\r
+\r
+        kcdb_identity_set_attr(idlist->list[i].ident,\r
+                               attr_id_krb5_ccname,\r
+                               idlist->list[i].ccname,\r
+                               KCDB_CBSIZE_AUTO);\r
+\r
+        kcdb_identity_set_attr(idlist->list[i].ident,\r
+                               KCDB_ATTR_EXPIRE,\r
+                               &idlist->list[i].ft_expire,\r
+                               sizeof(idlist->list[i].ft_expire));\r
+\r
+        kcdb_identity_set_attr(idlist->list[i].ident,\r
+                               KCDB_ATTR_ISSUE,\r
+                               &idlist->list[i].ft_issue,\r
+                               sizeof(idlist->list[i].ft_issue));\r
+\r
+        kcdb_identity_set_attr(idlist->list[i].ident,\r
+                               attr_id_krb5_flags,\r
+                               &idlist->list[i].krb5_flags,\r
+                               sizeof(idlist->list[i].krb5_flags));\r
+\r
+        if (idlist->list[i].ft_renewexpire.dwLowDateTime == 0 &&\r
+            idlist->list[i].ft_renewexpire.dwHighDateTime == 0) {\r
+            kcdb_identity_set_attr(idlist->list[i].ident,\r
+                                   KCDB_ATTR_RENEW_EXPIRE,\r
+                                   NULL, 0);\r
+        } else {\r
+            kcdb_identity_set_attr(idlist->list[i].ident,\r
+                                   KCDB_ATTR_RENEW_EXPIRE,\r
+                                   &idlist->list[i].ft_renewexpire,\r
+                                   sizeof(idlist->list[i].ft_renewexpire));\r
+        }\r
+    }\r
+}\r
+\r
+static void\r
+tc_free_idlist(identlist * idlist) {\r
+    khm_size i;\r
+\r
+    for (i=0; i < idlist->n_list; i++) {\r
+        if (idlist->list[i].ident != NULL) {\r
+            kcdb_identity_release(idlist->list[i].ident);\r
+            idlist->list[i].ident = NULL;\r
+        }\r
+    }\r
+\r
+    if (idlist->list)\r
+        PFREE(idlist->list);\r
+    idlist->list = NULL;\r
+    idlist->n_list = 0;\r
+    idlist->nc_list = 0;\r
+}\r
+\r
 #ifndef ENCTYPE_LOCAL_RC4_MD4\r
 #define ENCTYPE_LOCAL_RC4_MD4    0xFFFFFF80\r
 #endif\r
@@ -206,7 +351,8 @@ int com_addr(void)
 #define MAX_ADDRS 256\r
 \r
 static long get_tickets_from_cache(krb5_context ctx, \r
-                                   krb5_ccache cache)\r
+                                   krb5_ccache cache,\r
+                                   identlist * idlist)\r
 {\r
     krb5_error_code code;\r
     krb5_principal  KRBv5Principal;\r
@@ -257,6 +403,8 @@ static long get_tickets_from_cache(krb5_context ctx,
         }\r
     }\r
 \r
+    _reportf(L"Getting tickets from cache [%s]", wcc_name);\r
+\r
     if ((code = (*pkrb5_cc_set_flags)(ctx, cache, flags)))\r
     {\r
         if (code != KRB5_FCC_NOFILE && code != KRB5_CC_NOTFOUND)\r
@@ -305,6 +453,8 @@ static long get_tickets_from_cache(krb5_context ctx,
         goto _exit;\r
     }\r
 \r
+    _reportf(L"Found principal [%s]", wbuf);\r
+\r
     (*pkrb5_free_principal)(ctx, KRBv5Principal);\r
 \r
     if ((code = (*pkrb5_cc_start_seq_get)(ctx, cache, &KRBv5Cursor))) \r
@@ -478,12 +628,15 @@ static long get_tickets_from_cache(krb5_context ctx,
             FILETIME ft_issue_new;\r
             FILETIME ft_expire_old;\r
             FILETIME ft_expire_new;\r
-            khm_size cb;\r
+            ident_data * d;\r
 \r
-            /* an initial ticket!  If we find one, we generally set\r
-               the lifetime, and primary ccache based on this, but\r
-               only if this initial cred has a greater lifetime than\r
-               the current primary credential. */\r
+            /* an initial ticket!  Add it to the list of identities we\r
+               have seen so far with initial tickets. */\r
+            d = tc_add_ident_to_list(idlist, ident);\r
+#ifdef DEBUG\r
+            assert(d);\r
+            assert(d->count > 0);\r
+#endif\r
 \r
             tt = KRBv5Credentials.times.endtime;\r
             TimetToFileTime(tt, &ft_expire_new);\r
@@ -491,37 +644,40 @@ static long get_tickets_from_cache(krb5_context ctx,
             tt = KRBv5Credentials.times.starttime;\r
             TimetToFileTime(tt, &ft_issue_new);\r
 \r
-            cb = sizeof(ft_expire_old);\r
-            if(KHM_FAILED(kcdb_identity_get_attr(tident, \r
-                                                 KCDB_ATTR_EXPIRE, \r
-                                                 NULL, &ft_expire_old, \r
-                                                 &cb))\r
-               || CompareFileTime(&ft_expire_new, &ft_expire_old) > 0) {\r
-\r
-                kcdb_identity_set_attr(tident, attr_id_krb5_ccname, \r
-                                       wcc_name, KCDB_CBSIZE_AUTO);\r
-                kcdb_identity_set_attr(tident, KCDB_ATTR_EXPIRE, \r
-                                       &ft_expire_new, \r
-                                       sizeof(ft_expire_new));\r
-                kcdb_identity_set_attr(tident, KCDB_ATTR_ISSUE,\r
-                                       &ft_issue_new,\r
-                                       sizeof(ft_issue_new));\r
+            /* so now, we have to set the properties of the identity\r
+               based on the properties of this credential under the\r
+               following circumstances:\r
+\r
+               - If this is the first time we are hitting this\r
+                 identity.\r
+\r
+               - If this is not the MSLSA: cache and the expiry time\r
+                 for this credential is longer than the time already\r
+                 found for this identity.\r
+            */\r
+\r
+            ft_expire_old = d->ft_expire;\r
+\r
+            if(d->count == 1\r
+               || (CompareFileTime(&ft_expire_new, &ft_expire_old) > 0 &&\r
+                   wcscmp(wcc_name, L"MSLSA:") != 0)) {\r
+\r
+                _reportf(L"Setting properties for identity (count=%d)", d->count);\r
+\r
+                StringCbCopy(d->ccname, sizeof(d->ccname),\r
+                             wcc_name);\r
+                d->ft_expire = ft_expire_new;\r
+                d->ft_issue = ft_issue_new;\r
 \r
                 if (KRBv5Credentials.times.renew_till > 0) {\r
                     tt = KRBv5Credentials.times.renew_till;\r
                     TimetToFileTime(tt, &ft);\r
-                    kcdb_identity_set_attr(tident, \r
-                                           KCDB_ATTR_RENEW_EXPIRE, \r
-                                           &ft, sizeof(ft));\r
+                    d->ft_renewexpire = ft;\r
                 } else {\r
-                    kcdb_identity_set_attr(tident,\r
-                                           KCDB_ATTR_RENEW_EXPIRE,\r
-                                           NULL, 0);\r
+                    ZeroMemory(&d->ft_renewexpire, sizeof(d->ft_renewexpire));\r
                 }\r
 \r
-                ti = KRBv5Credentials.ticket_flags;\r
-                kcdb_identity_set_attr(tident, attr_id_krb5_flags, \r
-                                       &ti, sizeof(ti));\r
+                d->krb5_flags = KRBv5Credentials.ticket_flags;\r
             }\r
         }\r
 \r
@@ -583,8 +739,10 @@ khm_krb5_list_tickets(krb5_context *krbv5Context)
     khm_int32           t;\r
     wchar_t *           ms = NULL;\r
     khm_size            cb;\r
+    identlist           idl;\r
 \r
     kcdb_credset_flush(krb5_credset);\r
+    tc_prep_idlist(&idl);\r
 \r
     if((*krbv5Context == 0) && (code = (*pkrb5_init_context)(krbv5Context))) {\r
         goto _exit;\r
@@ -621,7 +779,7 @@ khm_krb5_list_tickets(krb5_context *krbv5Context)
         if (code)\r
             continue;\r
 \r
-        code = get_tickets_from_cache(ctx, cache);\r
+        code = get_tickets_from_cache(ctx, cache, &idl);\r
 \r
         if(ctx != NULL && cache != NULL)\r
             (*pkrb5_cc_close)(ctx, cache);\r
@@ -631,18 +789,6 @@ khm_krb5_list_tickets(krb5_context *krbv5Context)
 \r
  _skip_cc_iter:\r
 \r
-    if (KHM_SUCCEEDED(khc_read_int32(csp_params, L"MsLsaList", &t)) && t) {\r
-        code = (*pkrb5_cc_resolve)(ctx, "MSLSA:", &cache);\r
-\r
-        if (code == 0 && cache) {\r
-            code = get_tickets_from_cache(ctx, cache);\r
-        }\r
-\r
-        if (ctx != NULL && cache != NULL)\r
-            (*pkrb5_cc_close)(ctx, cache);\r
-        cache = 0;\r
-    }\r
-\r
     if (khc_read_multi_string(csp_params, L"FileCCList", NULL, &cb)\r
         == KHM_ERROR_TOO_LONG &&\r
         cb > sizeof(wchar_t) * 2) {\r
@@ -664,7 +810,7 @@ khm_krb5_list_tickets(krb5_context *krbv5Context)
             if (code)\r
                 continue;\r
 \r
-            code = get_tickets_from_cache(ctx, cache);\r
+            code = get_tickets_from_cache(ctx, cache, &idl);\r
 \r
             if (ctx != NULL && cache != NULL)\r
                 (*pkrb5_cc_close)(ctx, cache);\r
@@ -674,6 +820,18 @@ khm_krb5_list_tickets(krb5_context *krbv5Context)
         PFREE(ms);\r
     }\r
 \r
+    if (KHM_SUCCEEDED(khc_read_int32(csp_params, L"MsLsaList", &t)) && t) {\r
+        code = (*pkrb5_cc_resolve)(ctx, "MSLSA:", &cache);\r
+\r
+        if (code == 0 && cache) {\r
+            code = get_tickets_from_cache(ctx, cache, &idl);\r
+        }\r
+\r
+        if (ctx != NULL && cache != NULL)\r
+            (*pkrb5_cc_close)(ctx, cache);\r
+        cache = 0;\r
+    }\r
+\r
 _exit:\r
     if (pNCi)\r
         (*pcc_free_NC_info)(cc_ctx, &pNCi);\r
@@ -681,6 +839,8 @@ _exit:
         (*pcc_shutdown)(&cc_ctx);\r
 \r
     kcdb_credset_collect(NULL, krb5_credset, NULL, credtype_id_krb5, NULL);\r
+    tc_set_ident_data(&idl);\r
+    tc_free_idlist(&idl);\r
 \r
     return(code);\r
 }\r
@@ -842,12 +1002,34 @@ khm_krb5_renew_ident(khm_handle identity)
     krb5_principal      server = NULL;\r
     krb5_creds          my_creds;\r
     krb5_data           *realm = NULL;\r
+    wchar_t             idname[KCDB_IDENT_MAXCCH_NAME];\r
+    char                cidname[KCDB_IDENT_MAXCCH_NAME];\r
+    khm_size            cb;\r
 \r
     memset(&my_creds, 0, sizeof(krb5_creds));\r
 \r
     if ( !pkrb5_init_context )\r
         goto cleanup;\r
 \r
+    cb = sizeof(idname);\r
+    kcdb_identity_get_name(identity, idname, &cb);\r
+\r
+    if (khm_krb5_get_identity_flags(identity) & K5IDFLAG_IMPORTED) {\r
+        /* we are trying to renew the identity that was imported from\r
+           MSLSA: */\r
+        BOOL imported;\r
+\r
+        UnicodeStrToAnsi(cidname, sizeof(cidname), idname);\r
+\r
+        imported = khm_krb5_ms2mit(cidname, FALSE, TRUE);\r
+\r
+        if (imported)\r
+            goto cleanup;\r
+\r
+        /* if the import failed, then we try to renew the identity via\r
+           the usual procedure. */\r
+    }\r
+\r
     code = khm_krb5_initialize(identity, &ctx, &cc);\r
     if (code) \r
         goto cleanup;\r
@@ -896,16 +1078,18 @@ cleanup:
     if (my_creds.server == server)\r
         my_creds.server = NULL;\r
 \r
-    pkrb5_free_cred_contents(ctx, &my_creds);\r
+    if (ctx) {\r
+        pkrb5_free_cred_contents(ctx, &my_creds);\r
 \r
-    if (me)\r
-        pkrb5_free_principal(ctx, me);\r
-    if (server)\r
-        pkrb5_free_principal(ctx, server);\r
-    if (cc)\r
-        pkrb5_cc_close(ctx, cc);\r
-    if (ctx)\r
+        if (me)\r
+            pkrb5_free_principal(ctx, me);\r
+        if (server)\r
+            pkrb5_free_principal(ctx, server);\r
+        if (cc)\r
+            pkrb5_cc_close(ctx, cc);\r
         pkrb5_free_context(ctx);\r
+    }\r
+\r
     return(code);\r
 }\r
 \r
@@ -1356,7 +1540,7 @@ khm_krb5_destroy_by_credset(khm_handle p_cs)
     khm_handle d_cs = NULL;\r
     khm_int32 rv = KHM_ERROR_SUCCESS;\r
     khm_size s, cb;\r
-    krb5_context ctx;\r
+    krb5_context ctx = NULL;\r
     krb5_error_code code = 0;\r
     int i;\r
     wchar_t ccname[KRB5_MAXCCH_CCNAME];\r
@@ -1636,6 +1820,9 @@ khm_krb5_destroy_by_credset(khm_handle p_cs)
     if (d_cs)\r
         kcdb_credset_delete(&d_cs);\r
 \r
+    if (ctx != NULL)\r
+        pkrb5_free_context(ctx);\r
+\r
     return rv;\r
 }\r
 \r
@@ -1727,7 +1914,7 @@ IsKerberosLogon(VOID)
 \r
 \r
 BOOL\r
-khm_krb5_ms2mit(BOOL save_creds)\r
+khm_krb5_ms2mit(char * match_princ, BOOL match_realm, BOOL save_creds)\r
 {\r
 #ifdef NO_KRB5\r
     return(FALSE);\r
@@ -1739,6 +1926,9 @@ khm_krb5_ms2mit(BOOL save_creds)
     krb5_creds creds;\r
     krb5_cc_cursor cursor=0;\r
     krb5_principal princ = 0;\r
+    khm_handle ident = NULL;\r
+    wchar_t wname[KCDB_IDENT_MAXCCH_NAME];\r
+    char    cname[KCDB_IDENT_MAXCCH_NAME];\r
     char *cache_name = NULL;\r
     char *princ_name = NULL;\r
     BOOL rc = FALSE;\r
@@ -1765,10 +1955,89 @@ khm_krb5_ms2mit(BOOL save_creds)
         if (code = pkrb5_unparse_name(kcontext, princ, &princ_name))\r
             goto cleanup;\r
 \r
-        kherr_reportf(L"Unparsed [%S].  Resolving target cache\n", princ_name);\r
-        /* TODO: actually look up the preferred ccache name */\r
-        if (code = pkrb5_cc_resolve(kcontext, princ_name, &ccache)) {\r
-            kherr_reportf(L"Cannot resolve cache [%S] with code=%d.  Trying default.\n", princ_name, code);\r
+        AnsiStrToUnicode(wname, sizeof(wname), princ_name);\r
+\r
+        kherr_reportf(L"Unparsed name [%s]", wname);\r
+\r
+        /* see if we have to match a specific principal */\r
+        if (match_princ != NULL) {\r
+            if (strcmp(princ_name, match_princ)) {\r
+                kherr_reportf(L"Principal mismatch.  Wanted [%S], found [%S]",\r
+                              match_princ, princ_name);\r
+                goto cleanup;\r
+            }\r
+        } else if (match_realm) {\r
+            wchar_t * wdefrealm;\r
+            char defrealm[256];\r
+            krb5_data * princ_realm;\r
+\r
+            wdefrealm = khm_krb5_get_default_realm();\r
+            if (wdefrealm == NULL) {\r
+                kherr_reportf(L"Can't determine default realm");\r
+                goto cleanup;\r
+            }\r
+\r
+            princ_realm = krb5_princ_realm(kcontext, princ);\r
+            UnicodeStrToAnsi(defrealm, sizeof(defrealm), wdefrealm);\r
+\r
+            if (strncmp(defrealm, princ_realm->data, princ_realm->length)) {\r
+                kherr_reportf(L"Realm mismatch.  Wanted [%S], found [%*S]",\r
+                              defrealm, princ_realm->length, princ_realm->data);\r
+                PFREE(wdefrealm);\r
+                goto cleanup;\r
+            }\r
+\r
+            PFREE(wdefrealm);\r
+        }\r
+\r
+        if (KHM_SUCCEEDED(kcdb_identity_create(wname,\r
+                                               KCDB_IDENT_FLAG_CREATE,\r
+                                               &ident))) {\r
+            khm_handle idconfig = NULL;\r
+            khm_handle k5config = NULL;\r
+            khm_size cb;\r
+\r
+            wname[0] = L'\0';\r
+\r
+            kcdb_identity_get_config(ident, 0, &idconfig);\r
+            if (idconfig == NULL)\r
+                goto _done_checking_config;\r
+\r
+            khc_open_space(idconfig, CSNAME_KRB5CRED, 0, &k5config);\r
+            if (k5config == NULL)\r
+                goto _done_checking_config;\r
+\r
+            cb = sizeof(wname);\r
+            khc_read_string(k5config,\r
+                            L"DefaultCCName",\r
+                            wname, &cb);\r
+\r
+        _done_checking_config:\r
+\r
+            if (idconfig)\r
+                khc_close_space(idconfig);\r
+            if (k5config)\r
+                khc_close_space(k5config);\r
+\r
+            if (wname[0]) {\r
+                UnicodeStrToAnsi(cname, sizeof(cname), wname);\r
+            } else {\r
+                StringCbPrintfA(cname, sizeof(cname), "API:%s", princ_name);\r
+            }\r
+\r
+            cache_name = cname;\r
+\r
+        } else {\r
+            /* the identity could not be created.  we just use the\r
+               name of the principal as the ccache name. */\r
+            StringCbPrintfA(cname, sizeof(cname), "API:%s", princ_name);\r
+            cache_name = cname;\r
+        }\r
+\r
+        kherr_reportf(L"Resolving target cache [%S]\n", cache_name);\r
+\r
+        if (code = pkrb5_cc_resolve(kcontext, cache_name, &ccache)) {\r
+            kherr_reportf(L"Cannot resolve cache [%S] with code=%d.  Trying default.\n", cache_name, code);\r
 \r
             if (code = pkrb5_cc_default(kcontext, &ccache)) {\r
                 kherr_reportf(L"Failed to resolve default ccache. Code=%d", code);\r
@@ -1784,6 +2053,11 @@ khm_krb5_ms2mit(BOOL save_creds)
         if (code = pkrb5_cc_copy_creds(kcontext, mslsa_ccache, ccache))\r
             goto cleanup;\r
 \r
+        /* and mark the identity as having been imported */\r
+        if (ident) {\r
+            khm_krb5_set_identity_flags(ident, K5IDFLAG_IMPORTED, K5IDFLAG_IMPORTED);\r
+        }\r
+\r
         rc = TRUE;\r
     } else {\r
         /* Enumerate tickets from cache looking for an initial ticket */\r
@@ -2078,7 +2352,7 @@ khm_krb5_get_realm_list(void)
     \brief Get the default realm\r
 \r
     A string will be returned that specifies the default realm.  The\r
-    caller should free the string using free().\r
+    caller should free the string using PFREE().\r
 \r
     Returns NULL if the operation fails.\r
 */\r
@@ -2259,3 +2533,58 @@ khm_krb5_creds_is_equal(khm_handle vcred1, khm_handle vcred2, void * dummy) {
     else\r
         return 0;\r
 }\r
+\r
+void\r
+khm_krb5_set_identity_flags(khm_handle identity,\r
+                            khm_int32  flag_mask,\r
+                            khm_int32  flag_value) {\r
+\r
+    khm_int32 t = 0;\r
+    khm_size  cb;\r
+\r
+    cb = sizeof(t);\r
+    if (KHM_FAILED(kcdb_identity_get_attr(identity,\r
+                                          attr_id_krb5_idflags,\r
+                                          NULL,\r
+                                          &t, &cb))) {\r
+        t = 0;\r
+    }\r
+\r
+    t &= ~flag_mask;\r
+    t |= flag_value | flag_mask;\r
+\r
+    kcdb_identity_set_attr(identity,\r
+                           attr_id_krb5_idflags,\r
+                           &t, sizeof(t));\r
+}\r
+\r
+khm_int32\r
+khm_krb5_get_identity_flags(khm_handle identity) {\r
+    khm_int32 t = 0;\r
+    khm_size  cb;\r
+\r
+    cb = sizeof(t);\r
+    kcdb_identity_get_attr(identity,\r
+                           attr_id_krb5_idflags,\r
+                           NULL, &t, &cb);\r
+\r
+    return t;\r
+}\r
+\r
+long\r
+khm_krb5_get_temp_ccache(krb5_context ctx,\r
+                         krb5_ccache * prcc) {\r
+    int  rnd = rand();\r
+    char ccname[MAX_PATH];\r
+    long code = 0;\r
+    krb5_ccache cc = 0;\r
+\r
+    StringCbPrintfA(ccname, sizeof(ccname), "API:TempCache%8x", rnd);\r
+\r
+    code = pkrb5_cc_resolve(ctx, ccname, &cc);\r
+\r
+    if (code == 0)\r
+        *prcc = cc;\r
+\r
+    return code;\r
+}\r
index d699508367281979843f8aa444a4f0b1c74f74ef..ece4f79087d7422d0f74d9b53cf1ceba6d7eb6b7 100644 (file)
@@ -53,7 +53,9 @@
 // Function Prototypes.\r
 \r
 BOOL \r
-khm_krb5_ms2mit(BOOL);\r
+khm_krb5_ms2mit(char * match_princ,\r
+                BOOL   match_realm,\r
+                BOOL   save_creds);\r
 \r
 int\r
 khm_krb5_kinit(krb5_context       alt_ctx,\r
@@ -130,4 +132,15 @@ khm_krb5_get_temp_profile_file(LPSTR confname, UINT szConfname);
 khm_int32 KHMAPI\r
 khm_krb5_creds_is_equal(khm_handle vcred1, khm_handle vcred2, void * dummy);\r
 \r
+void\r
+khm_krb5_set_identity_flags(khm_handle identity,\r
+                            khm_int32  flag_mask,\r
+                            khm_int32  flag_value);\r
+\r
+khm_int32\r
+khm_krb5_get_identity_flags(khm_handle identity);\r
+\r
+long\r
+khm_krb5_get_temp_ccache(krb5_context ctx,\r
+                         krb5_ccache * cc);\r
 #endif\r
index 05f93fcd3603f623afcae6227197f205cfe4f305..a8c91f955ba0b7e1e10b8e246c9244e565353c34 100644 (file)
@@ -807,149 +807,120 @@ k5_ident_set_default(khm_int32 msg_type,
                      khm_ui_4 uparam,\r
                      void * vparam) {\r
 \r
-    /* Logic for setting the default identity:\r
-\r
-    When setting identity I as the default;\r
-\r
-    - If KRB5CCNAME is set\r
-    - If I["Krb5CCName"] == %KRB5CCNAME%\r
-    - do nothing\r
-    - Else\r
-    - Copy the contents of I["Krb5CCName"] to %KRB5CCNAME\r
-    - Set I["Krb5CCName"] to %KRB5CCNAME\r
-    - Else\r
-    - Set HKCU\Software\MIT\kerberos5,ccname to \r
-    "API:".I["Krb5CCName"]\r
+    /* \r
+       Currently, setting the default identity simply sets the\r
+       "ccname" registry value at "Software\MIT\kerberos5".\r
     */\r
 \r
     if (uparam) {\r
         /* an identity is being made default */\r
         khm_handle def_ident = (khm_handle) vparam;\r
-        wchar_t env_ccname[KRB5_MAXCCH_CCNAME];\r
         wchar_t id_ccname[KRB5_MAXCCH_CCNAME];\r
         khm_size cb;\r
         DWORD dw;\r
         LONG l;\r
+        HKEY hk_ccname;\r
+        DWORD dwType;\r
+        DWORD dwSize;\r
+        wchar_t reg_ccname[KRB5_MAXCCH_CCNAME];\r
+\r
+        assert(FALSE);\r
 \r
 #ifdef DEBUG\r
         assert(def_ident != NULL);\r
 #endif\r
 \r
+        {\r
+            wchar_t idname[KCDB_IDENT_MAXCCH_NAME];\r
+            khm_size cb;\r
+\r
+            cb = sizeof(idname);\r
+            kcdb_identity_get_name(def_ident, idname, &cb);\r
+\r
+            _begin_task(0);\r
+            _report_cs1(KHERR_DEBUG_1, L"Setting default identity [%1!s!]", _cstr(idname));\r
+            _describe();\r
+        }\r
+\r
         cb = sizeof(id_ccname);\r
         if (KHM_FAILED(kcdb_identity_get_attr(def_ident,\r
                                               attr_id_krb5_ccname,\r
                                               NULL,\r
                                               id_ccname,\r
-                                              &cb)))\r
-            return KHM_ERROR_UNKNOWN;\r
+                                              &cb))) {\r
+            _reportf(L"The specified identity does not have the Krb5CCName property");\r
+            _end_task();\r
+            return KHM_ERROR_NOT_FOUND;\r
+        }\r
 \r
         khm_krb5_canon_cc_name(id_ccname, sizeof(id_ccname));\r
 \r
+        _reportf(L"Found Krb5CCName property : %s", id_ccname);\r
+\r
         StringCbLength(id_ccname, sizeof(id_ccname), &cb);\r
         cb += sizeof(wchar_t);\r
 \r
-        dw = GetEnvironmentVariable(L"KRB5CCNAME",\r
-                                    env_ccname,\r
-                                    ARRAYLENGTH(env_ccname));\r
-\r
-        if (dw == 0 &&\r
-            GetLastError() == ERROR_ENVVAR_NOT_FOUND) {\r
-            /* KRB5CCNAME not set */\r
-            HKEY hk_ccname;\r
-            DWORD dwType;\r
-            DWORD dwSize;\r
-            wchar_t reg_ccname[KRB5_MAXCCH_CCNAME];\r
-\r
-            l = RegOpenKeyEx(HKEY_CURRENT_USER,\r
-                             L"Software\\MIT\\kerberos5",\r
-                             0,\r
-                             KEY_READ | KEY_WRITE,\r
-                             &hk_ccname);\r
-\r
-            if (l != ERROR_SUCCESS)\r
-                l = RegCreateKeyEx(HKEY_CURRENT_USER,\r
-                                   L"Software\\MIT\\kerberos5",\r
-                                   0,\r
-                                   NULL,\r
-                                   REG_OPTION_NON_VOLATILE,\r
-                                   KEY_READ | KEY_WRITE,\r
-                                   NULL,\r
-                                   &hk_ccname,\r
-                                   &dw);\r
-\r
-            if (l != ERROR_SUCCESS)\r
-                return KHM_ERROR_UNKNOWN;\r
-\r
-            dwSize = sizeof(reg_ccname);\r
+        _reportf(L"Setting default CC name in the registry");\r
+\r
+        l = RegOpenKeyEx(HKEY_CURRENT_USER,\r
+                         L"Software\\MIT\\kerberos5",\r
+                         0,\r
+                         KEY_READ | KEY_WRITE,\r
+                         &hk_ccname);\r
+\r
+        if (l != ERROR_SUCCESS)\r
+            l = RegCreateKeyEx(HKEY_CURRENT_USER,\r
+                               L"Software\\MIT\\kerberos5",\r
+                               0,\r
+                               NULL,\r
+                               REG_OPTION_NON_VOLATILE,\r
+                               KEY_READ | KEY_WRITE,\r
+                               NULL,\r
+                               &hk_ccname,\r
+                               &dw);\r
 \r
-            l = RegQueryValueEx(hk_ccname,\r
-                                L"ccname",\r
-                                NULL,\r
-                                &dwType,\r
-                                (LPBYTE) reg_ccname,\r
-                                &dwSize);\r
+        if (l != ERROR_SUCCESS) {\r
+            _reportf(L"Can't create registry key : %d", l);\r
+            _end_task();\r
+            return KHM_ERROR_UNKNOWN;\r
+        }\r
 \r
-            if (l != ERROR_SUCCESS ||\r
-                dwType != REG_SZ ||\r
-                khm_krb5_cc_name_cmp(reg_ccname, id_ccname)) {\r
+        dwSize = sizeof(reg_ccname);\r
 \r
-                /* we have to write the new value in */\r
+        l = RegQueryValueEx(hk_ccname,\r
+                            L"ccname",\r
+                            NULL,\r
+                            &dwType,\r
+                            (LPBYTE) reg_ccname,\r
+                            &dwSize);\r
 \r
-                l = RegSetValueEx(hk_ccname,\r
-                                  L"ccname",\r
-                                  0,\r
-                                  REG_SZ,\r
-                                  (BYTE *) id_ccname,\r
-                                  (DWORD) cb);\r
-            }\r
+        if (l != ERROR_SUCCESS ||\r
+            dwType != REG_SZ ||\r
+            khm_krb5_cc_name_cmp(reg_ccname, id_ccname)) {\r
 \r
-            RegCloseKey(hk_ccname);\r
+            /* we have to write the new value in */\r
+            \r
+            l = RegSetValueEx(hk_ccname,\r
+                              L"ccname",\r
+                              0,\r
+                              REG_SZ,\r
+                              (BYTE *) id_ccname,\r
+                              (DWORD) cb);\r
+        }\r
 \r
-            if (l == ERROR_SUCCESS) {\r
-                k5_update_last_default_identity(def_ident);\r
-                return KHM_ERROR_SUCCESS;\r
-            } else\r
-                return KHM_ERROR_UNKNOWN;\r
+        RegCloseKey(hk_ccname);\r
 \r
-        } else if (dw > ARRAYLENGTH(env_ccname)) {\r
-            /* buffer was not enough */\r
-#ifdef DEBUG\r
-            assert(FALSE);\r
-#else\r
-            return KHM_ERROR_UNKNOWN;\r
-#endif\r
+        if (l == ERROR_SUCCESS) {\r
+            _reportf(L"Successfully set the default ccache");\r
+            k5_update_last_default_identity(def_ident);\r
+            _end_task();\r
+            return KHM_ERROR_SUCCESS;\r
         } else {\r
-            /* KRB5CCNAME is set */\r
-            long code;\r
-            krb5_context ctx;\r
-\r
-            /* if the %KRB5CCNAME is the same as the identity\r
-               ccache, then it is already the default. */\r
-            if (!khm_krb5_cc_name_cmp(id_ccname, env_ccname)) {\r
-                k5_update_last_default_identity(def_ident);\r
-                return KHM_ERROR_SUCCESS;\r
-            }\r
-\r
-            /* if not, we have to copy the contents of id_ccname\r
-               to env_ccname */\r
-            code = pkrb5_init_context(&ctx);\r
-            if (code)\r
-                return KHM_ERROR_UNKNOWN;\r
-\r
-            code = khm_krb5_copy_ccache_by_name(ctx, \r
-                                                env_ccname, \r
-                                                id_ccname);\r
-\r
-            if (code == 0) {\r
-                k5_update_last_default_identity(def_ident);\r
-                khm_krb5_list_tickets(&ctx);\r
-            }\r
-\r
-            if (ctx)\r
-                pkrb5_free_context(ctx);\r
-\r
-            return (code == 0)?KHM_ERROR_SUCCESS:KHM_ERROR_UNKNOWN;\r
+            _reportf(L"Can't set the registry value : %d", l);\r
+            _end_task();\r
+            return KHM_ERROR_UNKNOWN;\r
         }\r
+\r
     } else {\r
         /* the default identity is being forgotten */\r
 \r
@@ -1061,6 +1032,11 @@ struct k5_ident_update_data {
     khm_int32  k5_flags;\r
 };\r
 \r
+/* The logic here has to reflect the logic in khm_krb5_list_tickets().\r
+   We use this to handle an identity update request because some other\r
+   plug-in or maybe NetIDMgr itself is about to do something\r
+   important(tm) with the identity and needs to make sure that the\r
+   properties of the identity are up-to-date. */\r
 static khm_int32 KHMAPI\r
 k5_ident_update_apply_proc(khm_handle cred,\r
                            void * rock) {\r
@@ -1149,7 +1125,9 @@ k5_ident_update(khm_int32 msg_type,
                 khm_ui_4 uparam,\r
                 void * vparam) {\r
 \r
+#if 0\r
     struct k5_ident_update_data d;\r
+#endif\r
     khm_handle ident;\r
     khm_handle tident;\r
     krb5_ccache cc = NULL;\r
@@ -1163,6 +1141,13 @@ k5_ident_update(khm_int32 msg_type,
     if (ident == NULL)\r
         return KHM_ERROR_SUCCESS;\r
 \r
+#if 0\r
+    /* we are going to skip doing this here since\r
+       khm_krb5_list_tickets() performs this function for us each time\r
+       we enumerate tickets.  Since it also gets run each time our\r
+       list of tickets changes and since we are basing this operation\r
+       on existing tickets, we are unlikely to find anything new\r
+       here.  */\r
     ZeroMemory(&d, sizeof(d));\r
     d.identity = ident;\r
 \r
@@ -1209,6 +1194,7 @@ k5_ident_update(khm_int32 msg_type,
         kcdb_identity_set_attr(ident, attr_id_krb5_flags, NULL, 0);\r
         kcdb_identity_set_attr(ident, attr_id_krb5_ccname, NULL, 0);\r
     }\r
+#endif\r
 \r
     if (KHM_SUCCEEDED(kcdb_identity_get_default(&tident))) {\r
         kcdb_identity_release(tident);\r
@@ -1258,18 +1244,54 @@ k5_refresh_default_identity(krb5_context ctx) {
     krb5_principal princ = NULL;\r
     char * princ_nameA = NULL;\r
     wchar_t princ_nameW[KCDB_IDENT_MAXCCH_NAME];\r
+    char * ccname = NULL;\r
     khm_handle ident = NULL;\r
     khm_boolean found_default = FALSE;\r
 \r
     assert(ctx != NULL);\r
 \r
+    _begin_task(0);\r
+    _report_cs0(KHERR_DEBUG_1, L"Refreshing default identity");\r
+    _describe();\r
+\r
     code = pkrb5_cc_default(ctx, &cc);\r
-    if (code)\r
+    if (code) {\r
+        _reportf(L"Can't open default ccache. code=%d", code);\r
         goto _nc_cleanup;\r
+    }\r
     \r
     code = pkrb5_cc_get_principal(ctx, cc, &princ);\r
-    if (code)\r
+    if (code) {\r
+        /* try to determine the identity from the ccache name */\r
+        ccname = pkrb5_cc_get_name(ctx, cc);\r
+\r
+        if (ccname) {\r
+            char * namepart = strchr(ccname, ':');\r
+\r
+            _reportf(L"CC name is [%S]", ccname);\r
+\r
+            if (namepart == NULL)\r
+                namepart = ccname;\r
+            else\r
+                namepart++;\r
+\r
+            _reportf(L"Checking if [%S] is a valid identity name", namepart);\r
+\r
+            AnsiStrToUnicode(princ_nameW, sizeof(princ_nameW), namepart);\r
+            if (kcdb_identity_is_valid_name(princ_nameW)) {\r
+                kcdb_identity_create(princ_nameW, KCDB_IDENT_FLAG_CREATE, &ident);\r
+                if (ident) {\r
+                    _reportf(L"Setting [%S] as the default identity", namepart);\r
+                    kcdb_identity_set_default_int(ident);\r
+                    found_default = TRUE;\r
+                }\r
+            }\r
+        } else {\r
+            _reportf(L"Can't determine ccache name");\r
+        }\r
+\r
         goto _nc_cleanup;\r
+    }\r
 \r
     code = pkrb5_unparse_name(ctx, princ, &princ_nameA);\r
     if (code)\r
@@ -1277,14 +1299,22 @@ k5_refresh_default_identity(krb5_context ctx) {
 \r
     AnsiStrToUnicode(princ_nameW, sizeof(princ_nameW), princ_nameA);\r
 \r
-    if (KHM_FAILED(kcdb_identity_create(princ_nameW, 0, &ident)))\r
+    _reportf(L"Found principal [%s]", princ_nameW);\r
+\r
+    if (KHM_FAILED(kcdb_identity_create(princ_nameW, KCDB_IDENT_FLAG_CREATE, &ident))) {\r
+        _reportf(L"Failed to create identity");\r
         goto _nc_cleanup;\r
+    }\r
 \r
+    _reportf(L"Setting default identity to [%s]", princ_nameW);\r
     kcdb_identity_set_default_int(ident);\r
 \r
     found_default = TRUE;\r
 \r
  _nc_cleanup:\r
+\r
+    _end_task();\r
+\r
     if (princ_nameA)\r
         pkrb5_free_unparsed_name(ctx, princ_nameA);\r
 \r
index f1b7f05491b174e5cf38093e01f66d605983962d..3d2f2c0e95da2110eee3a9ec5d33c17dde222514 100644 (file)
@@ -50,6 +50,7 @@ khm_int32 attr_id_addr_list     = -1;
 khm_int32 attr_id_krb5_flags    = -1;\r
 khm_int32 attr_id_krb5_ccname   = -1;\r
 khm_int32 attr_id_kvno          = -1;\r
+khm_int32 attr_id_krb5_idflags  = -1;\r
 \r
 BOOL attr_regd_key_enctype  = FALSE;\r
 BOOL attr_regd_tkt_enctype  = FALSE;\r
@@ -57,6 +58,7 @@ BOOL attr_regd_addr_list    = FALSE;
 BOOL attr_regd_krb5_flags   = FALSE;\r
 BOOL attr_regd_krb5_ccname  = FALSE;\r
 BOOL attr_regd_kvno         = FALSE;\r
+BOOL attr_regd_krb5_idflags = FALSE;\r
 \r
 khm_handle csp_plugins      = NULL;\r
 khm_handle csp_krbcred   = NULL;\r
@@ -383,6 +385,30 @@ KHMEXP khm_int32 KHMAPI init_module(kmm_module h_module) {
         attr_regd_kvno = TRUE;\r
     }\r
 \r
+    if (KHM_FAILED(kcdb_attrib_get_id(ATTRNAME_KRB5_IDFLAGS, &attr_id_krb5_idflags))) {\r
+        kcdb_attrib attrib;\r
+\r
+        ZeroMemory(&attrib, sizeof(attrib));\r
+\r
+        attrib.name = ATTRNAME_KRB5_IDFLAGS;\r
+        attrib.id = KCDB_ATTR_INVALID;\r
+        attrib.type = KCDB_TYPE_INT32;\r
+        attrib.flags = KCDB_ATTR_FLAG_PROPERTY |\r
+            KCDB_ATTR_FLAG_HIDDEN;\r
+        /* we don't bother localizing these strings since the\r
+           attribute is hidden.  The user will not see these\r
+           descriptions anyway. */\r
+        attrib.short_desc = L"Krb5 ID flags";\r
+        attrib.long_desc = L"Kerberos 5 Identity Flags";\r
+\r
+        rv = kcdb_attrib_register(&attrib, &attr_id_krb5_idflags);\r
+\r
+        if (KHM_FAILED(rv))\r
+            goto _exit;\r
+\r
+        attr_regd_krb5_idflags = TRUE;\r
+    }\r
+\r
     rv = kmm_get_plugins_config(0, &csp_plugins);\r
     if(KHM_FAILED(rv)) goto _exit;\r
 \r
@@ -416,6 +442,8 @@ KHMEXP khm_int32 KHMAPI exit_module(kmm_module h_module) {
         kcdb_attrib_unregister(attr_id_krb5_ccname);\r
     if(attr_regd_kvno)\r
         kcdb_attrib_unregister(attr_id_kvno);\r
+    if(attr_regd_krb5_idflags)\r
+        kcdb_attrib_unregister(attr_id_krb5_idflags);\r
 \r
     if(type_regd_enctype)\r
         kcdb_type_unregister(type_id_enctype);\r
index 1bff68e3c7d6ff6c6c4caaeae0246d12efa1299b..9be8c896a43c88602f9b82c0034dc24d43cc0029 100644 (file)
@@ -2801,8 +2801,17 @@ k5_msg_cred_dialog(khm_int32 msg_type,
 #endif\r
             khc_read_int32(csp_params, L"MsLsaImport", &t);\r
 \r
-            if (t == 1)\r
-                khm_krb5_ms2mit(TRUE);\r
+            if (t != K5_LSAIMPORT_NEVER) {\r
+                krb5_context ctx = NULL;\r
+                BOOL imported;\r
+\r
+                imported = khm_krb5_ms2mit(NULL, (t == K5_LSAIMPORT_MATCH), TRUE);\r
+                if (imported) {\r
+                    khm_krb5_list_tickets(&ctx);\r
+                    if (ctx)\r
+                        pkrb5_free_context(ctx);\r
+                }\r
+            }\r
         }\r
         break;\r
     }\r
index e80e01c47064158b4b2bbae080739b117b9cc368..bb481e0fbee01801d09d454685828661e04d9798 100644 (file)
@@ -111,9 +111,6 @@ k5_msg_system(khm_int32 msg_type, khm_int32 msg_subtype,
 \r
                 krb5_initialized = TRUE;\r
 \r
-                if(ctx != NULL)\r
-                    pkrb5_free_context(ctx);\r
-\r
                 /* now convert this thread to a fiber and create a\r
                    separate fiber to do kinit stuff */\r
                 k5_main_fiber = ConvertThreadToFiber(NULL);\r
@@ -126,6 +123,9 @@ k5_msg_system(khm_int32 msg_type, khm_int32 msg_subtype,
                 k5_register_config_panels();\r
 \r
                 khm_krb5_list_tickets(&ctx);\r
+\r
+                if(ctx != NULL)\r
+                    pkrb5_free_context(ctx);\r
             }\r
         }\r
         break;\r
index 694323ce3f3ca9e145c19cd04a8fb8e26dab066b..44b7733e343d602787b65bf6571550487f4da498 100644 (file)
@@ -64,6 +64,12 @@ typedef enum tag_k5_lsa_import {
 #define ATTRNAME_KRB5_FLAGS     L"Krb5Flags"\r
 #define ATTRNAME_KRB5_CCNAME    L"Krb5CCName"\r
 #define ATTRNAME_KVNO           L"Kvno"\r
+#define ATTRNAME_KRB5_IDFLAGS   L"Krb5IDFlags"\r
+\r
+/* Flag bits for Krb5IDFlags property */\r
+\r
+/* identity was imported from MSLSA: */\r
+#define K5IDFLAG_IMPORTED       0x00000001\r
 \r
 void init_krb();\r
 void exit_krb();\r
@@ -90,6 +96,7 @@ extern khm_int32 attr_id_addr_list;
 extern khm_int32 attr_id_krb5_flags;\r
 extern khm_int32 attr_id_krb5_ccname;\r
 extern khm_int32 attr_id_kvno;\r
+extern khm_int32 attr_id_krb5_idflags;\r
 \r
 extern khm_ui_4  k5_commctl_version;\r
 \r
index 36e0572febd2ef271b15eed16fa1759adf16e61f..c9b314b3d59a68d646fad085cea5428901d590ca 100644 (file)
@@ -2981,15 +2981,7 @@ cw_set_row_context(khui_credwnd_tbl * tbl, int row)
         o = (khui_credwnd_outline *) tbl->rows[row].data;\r
 \r
         if (tbl->cols[o->col].attr_id == KCDB_ATTR_ID_NAME) {\r
-            if (TPARENT(o) == NULL) { /* selected an identity */\r
-                khui_context_set(KHUI_SCOPE_IDENT,\r
-                                 (khm_handle) o->data,\r
-                                 KCDB_CREDTYPE_INVALID,\r
-                                 NULL,\r
-                                 NULL,\r
-                                 0,\r
-                                 tbl->credset);\r
-            } else {\r
+            if (TPARENT(o) != NULL) {\r
                 khui_credwnd_outline * op;\r
 \r
                 op = TPARENT(o);\r
@@ -3005,8 +2997,30 @@ cw_set_row_context(khui_credwnd_tbl * tbl, int row)
                                      0,\r
                                      tbl->credset);\r
                 } else {\r
-                    set_context = FALSE;\r
+                    /* we can't narrow it down using the standard set\r
+                       of scopes.  We consider this to be an identity\r
+                       selection because the user right-clicked on an\r
+                       identity header. */\r
+                    khui_context_set(KHUI_SCOPE_IDENT,\r
+                                     (khm_handle) o->data,\r
+                                     KCDB_CREDTYPE_INVALID,\r
+                                     NULL,\r
+                                     NULL,\r
+                                     0,\r
+                                     tbl->credset);\r
                 }\r
+            } else {\r
+                /* The user clicked on an identity header.  Even\r
+                   though not all credentials belonging to the\r
+                   identity maybe within the scope right now, we still\r
+                   consider this to be an identity scope. */\r
+                khui_context_set(KHUI_SCOPE_IDENT,\r
+                                 (khm_handle) o->data,\r
+                                 KCDB_CREDTYPE_INVALID,\r
+                                 NULL,\r
+                                 NULL,\r
+                                 0,\r
+                                 tbl->credset);\r
             }\r
         } else if (tbl->cols[o->col].attr_id == KCDB_ATTR_TYPE_NAME) {\r
             if (TPARENT(o) == NULL) {\r
@@ -3022,9 +3036,12 @@ cw_set_row_context(khui_credwnd_tbl * tbl, int row)
                 khui_credwnd_outline * op;\r
 \r
                 op = TPARENT(o);\r
-                if (tbl->cols[op->col].attr_id == KCDB_ATTR_ID_NAME &&\r
-                    TPARENT(op) == NULL) {\r
-                    /* credtype under an identity */\r
+                if (tbl->cols[op->col].attr_id == KCDB_ATTR_ID_NAME) {\r
+                    /* credtype under an identity.  Even though not\r
+                       all the credentials of this credtype belonging\r
+                       to this identity might be within the scope, we\r
+                       still consider this to be a type selection\r
+                       under a specific identity. */\r
                     khui_context_set(KHUI_SCOPE_CREDTYPE,\r
                                      (khm_handle) op->data,\r
                                      (khm_int32) (DWORD_PTR) o->data,\r
@@ -4051,6 +4068,16 @@ cw_properties(HWND hwnd)
         khm_size t = 0;\r
         khm_int32 cred_type;\r
 \r
+        if (ctx.identity == NULL) {\r
+            /* currently, we can't show a property sheet at this point\r
+               since most credentials providers don't provide a\r
+               property sheet that works without an identity. */\r
+\r
+            khui_context_release(&ctx);\r
+            khui_ps_destroy_sheet(ps);\r
+            return TRUE;\r
+        }\r
+\r
         cred_type = ctx.cred_type;\r
 \r
         ps->header.hInstance = khm_hInstance;\r
@@ -4073,6 +4100,8 @@ cw_properties(HWND hwnd)
                 ps->header.pszCaption = NULL;\r
             }\r
         } else {\r
+            /* we don't actually reach here since we handle this case\r
+               above */\r
             kcdb_credtype_describe(cred_type, NULL, &t, KCDB_TS_LONG);\r
             if(t > 0) {\r
                 ps->header.pszCaption = PMALLOC(t);\r
@@ -4488,15 +4517,21 @@ cw_wm_contextmenu(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
 \r
     cw_set_row_context(tbl, row);\r
 \r
+    khm_menu_show_panel(KHUI_MENU_IDENT_CTX, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));\r
+\r
+#if 0\r
+    /* calling cw_set_row_context() should take care of enabling or\r
+       disabling actions as appropriate.  We don't need to\r
+       differentiate between IDENT_CTX and TOK_CTX here. */\r
     if((tbl->rows[row].flags & KHUI_CW_ROW_HEADER) &&\r
-        (tbl->cols[tbl->rows[row].col].attr_id == KCDB_ATTR_ID_NAME))\r
-    {\r
+       (tbl->cols[tbl->rows[row].col].attr_id == KCDB_ATTR_ID_NAME)) {\r
         khm_menu_show_panel(KHUI_MENU_IDENT_CTX, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));\r
         //khui_context_reset();\r
     } else {\r
         khm_menu_show_panel(KHUI_MENU_TOK_CTX, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));\r
         //khui_context_reset();\r
     }\r
+#endif\r
 \r
     return DefWindowProc(hwnd, uMsg, wParam, lParam);\r
 }\r
index 80b7be3e5277472339ad4b7182f8dbc748e7a330..e2210782f4520f57896d9213228891b0d306ad7a 100644 (file)
@@ -192,12 +192,11 @@ void khm_add_dialog(HWND dlg) {
            meaningful value until we enter a modal loop */\r
         khui_dialogs[n_khui_dialogs].active = FALSE;\r
         n_khui_dialogs++;\r
-    }\r
+    } else {\r
 #if DEBUG\r
-    else {\r
-        assert(FALSE);\r
-    }\r
+          assert(FALSE);\r
 #endif\r
+    }\r
 }\r
 \r
 /* should only be called from the UI thread */\r
@@ -254,6 +253,8 @@ void khm_enter_modal(HWND hwnd) {
         EnableWindow(khm_hwnd_main, FALSE);\r
 \r
         khui_modal_dialog = hwnd;\r
+\r
+        SetForegroundWindow(hwnd);\r
     }\r
 }\r
 \r
index c03d47f1d71ee589c0c18e44ce79f86b46b258e9..eba23e40ed57afccd5762239b3c6f4ddb6a24f75 100644 (file)
@@ -226,22 +226,37 @@ khm_main_wnd_proc(HWND hwnd,
             return 0;\r
 \r
         case KHUI_ACTION_PASSWD_ID:\r
+            if (khm_startup.processing)\r
+                return 0;\r
+\r
             khm_cred_change_password(NULL);\r
             return 0;\r
 \r
         case KHUI_ACTION_NEW_CRED:\r
+            if (khm_startup.processing)\r
+                return 0;\r
+\r
             khm_cred_obtain_new_creds(NULL);\r
             return 0;\r
 \r
         case KHUI_ACTION_RENEW_CRED:\r
+            if (khm_startup.processing)\r
+                return 0;\r
+\r
             khm_cred_renew_creds();\r
             return 0;\r
 \r
         case KHUI_ACTION_DESTROY_CRED:\r
+            if (khm_startup.processing)\r
+                return 0;\r
+\r
             khm_cred_destroy_creds(FALSE, FALSE);\r
             return 0;\r
 \r
         case KHUI_ACTION_SET_DEF_ID:\r
+            if (khm_startup.processing)\r
+                return 0;\r
+\r
             khm_cred_set_default();\r
             return 0;\r
 \r
index a0472e2360241494c4588b4a726ee1a711be58b2..7bad1e24c04f67fd710f7e36bd038b7948dc60ed 100644 (file)
@@ -819,14 +819,12 @@ nc_handle_wm_create(HWND hwnd,
 #endif\r
     /* we defer the creation of the tab buttons for later */\r
 \r
-    /* add this to the dialog chain */\r
-    khm_add_dialog(hwnd);\r
-\r
     /* bring the window to the top, if necessary */\r
     if (KHM_SUCCEEDED(khc_read_int32(NULL,\r
                                      L"CredWindow\\Windows\\NewCred\\ForceToTop",\r
                                      &t)) &&\r
-        t != 0) {\r
+        t != 0 &&\r
+        !khm_is_dialog_active()) {\r
 \r
         /* if the main window is not visible, then the SetWindowPos()\r
            call is sufficient to bring the new creds window to the\r
@@ -840,6 +838,9 @@ nc_handle_wm_create(HWND hwnd,
 \r
     }\r
 \r
+    /* add this to the dialog chain */\r
+    khm_add_dialog(hwnd);\r
+\r
     return TRUE;\r
 }\r
 \r
@@ -1431,7 +1432,7 @@ static LRESULT nc_handle_wm_nc_notify(HWND hwnd,
 \r
             nc_update_credtext(d);\r
 \r
-            ShowWindow(hwnd, SW_SHOW);\r
+            ShowWindow(hwnd, SW_SHOWNOACTIVATE);\r
             SetFocus(hwnd);\r
 \r
             if (d->nc->n_identities == 0)\r
index f1bb4b19566d8c81395eb3af57ca3b98ffb97ebd..9f5e5e4b37bc14af31bb77fc5a0ba18fa60288a2 100644 (file)
@@ -71,7 +71,7 @@ CredWindow,KC_SPACE,0,Options for the credentials window
    Custom_0,KC_ENDSPACE,0,\r
    ByIdentity,KC_SPACE,0,The default view\r
     Description,KC_STRING,View grouped by identity and credential type,\r
-    ColumnList,KC_STRING,"_CWFlags,IdentityName,TypeName,Name,TimeLeft",\r
+    ColumnList,KC_STRING,"_CWFlags,IdentityName,TypeName,Location,Name,TimeLeft",\r
     Columns,KC_SPACE,0,Columns\r
       _CWFlags,KC_SPACE,0,\r
         Width,KC_INT32,20,\r
@@ -87,9 +87,14 @@ CredWindow,KC_SPACE,0,Options for the credentials window
         SortIndex,KC_INT32,1\r
         Flags,KC_INT32,11\r
       TypeName,KC_ENDSPACE,0\r
+      Location,KC_SPACE,0,\r
+        Width,KC_INT32,50\r
+        SortIndex,KC_INT32,2\r
+        Flags,KC_INT32,11\r
+      Location,KC_ENDSPACE,0,\r
       Name,KC_SPACE,0\r
         Width,KC_INT32,200\r
-        SortIndex,KC_INT32,2\r
+        SortIndex,KC_INT32,3\r
         Flags,KC_INT32,3\r
       Name,KC_ENDSPACE,0\r
       TimeLeft,KC_SPACE,0\r