diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/windows/identity/plugins/krb5/krb5configid.c | 17 | ||||
| -rw-r--r-- | src/windows/identity/plugins/krb5/krb5funcs.c | 135 | ||||
| -rw-r--r-- | src/windows/identity/plugins/krb5/krb5newcreds.c | 70 | ||||
| -rw-r--r-- | src/windows/identity/plugins/krb5/krbconfig.csv | 1 |
4 files changed, 163 insertions, 60 deletions
diff --git a/src/windows/identity/plugins/krb5/krb5configid.c b/src/windows/identity/plugins/krb5/krb5configid.c index a2688e1e7..2f3fe62c8 100644 --- a/src/windows/identity/plugins/krb5/krb5configid.c +++ b/src/windows/identity/plugins/krb5/krb5configid.c @@ -61,8 +61,7 @@ k5_id_read_params(k5_id_dlg_data * d) { khm_size cb; khm_int32 rv; khm_int32 t; - khm_handle csp_ident; - khm_handle csp_idroot = NULL; + khm_handle csp_ident = NULL; cb = sizeof(idname); rv = khui_cfg_get_name(d->cfg.ctx_node, idname, &cb); @@ -75,17 +74,7 @@ k5_id_read_params(k5_id_dlg_data * d) { assert(KHM_SUCCEEDED(rv)); #endif - rv = kcdb_identity_get_config(d->ident, 0, &csp_idroot); - if (KHM_SUCCEEDED(rv) && - KHM_SUCCEEDED(khc_open_space(csp_idroot, CSNAME_KRB5CRED, 0, - &csp_ident))) { - khc_shadow_space(csp_ident, csp_params); - } else { - csp_ident = csp_params; - } - - if (csp_idroot) - khc_close_space(csp_idroot); + khm_krb5_get_identity_config(d->ident, 0, &csp_ident); rv = khc_read_int32(csp_ident, L"DefaultLifetime", &t); if (KHM_SUCCEEDED(rv)) @@ -146,7 +135,7 @@ k5_id_read_params(k5_id_dlg_data * d) { d->tc_renew.min = 0; d->tc_renew.max = 3600 * 24 * 30; - if (csp_ident != csp_params) + if (csp_ident) khc_close_space(csp_ident); } diff --git a/src/windows/identity/plugins/krb5/krb5funcs.c b/src/windows/identity/plugins/krb5/krb5funcs.c index 4dc854845..9c8db7509 100644 --- a/src/windows/identity/plugins/krb5/krb5funcs.c +++ b/src/windows/identity/plugins/krb5/krb5funcs.c @@ -515,8 +515,6 @@ static long get_tickets_from_cache(krb5_context ctx, #ifdef KRB5_TC_NOTICKET flags = KRB5_TC_NOTICKET; -#else - flags = 0; #endif { @@ -1005,6 +1003,7 @@ khm_krb5_renew_cred(khm_handle cred) khm_boolean istgt = FALSE; khm_int32 flags; + int ccflags = 0; cbname = sizeof(wname); kcdb_cred_get_name(cred, wname, &cbname); @@ -1055,9 +1054,8 @@ khm_krb5_renew_cred(khm_handle cred) in_creds.client = me; in_creds.server = server; -#ifdef KRB5_TC_NOTICKET - pkrb5_cc_set_flags(ctx, cc, 0); -#endif + ccflags = KRB5_TC_OPENCLOSE; + pkrb5_cc_set_flags(ctx, cc, ccflags); if (strlen("krbtgt") != krb5_princ_name(ctx, server)->length || strncmp("krbtgt", krb5_princ_name(ctx, server)->data, krb5_princ_name(ctx, server)->length)) @@ -1080,9 +1078,6 @@ khm_krb5_renew_cred(khm_handle cred) code = pkrb5_get_renewed_creds(ctx, &cc_creds, me, cc, NULL); } -#ifdef KRB5_TC_NOTICKET - pkrb5_cc_set_flags(ctx, cc, KRB5_TC_NOTICKET); -#endif if (code) { if ( code != KRB5KDC_ERR_ETYPE_NOSUPP || code != KRB5_KDC_UNREACH) @@ -1094,6 +1089,8 @@ khm_krb5_renew_cred(khm_handle cred) code = pkrb5_cc_initialize(ctx, cc, me); if (code) goto cleanup; + ccflags = KRB5_TC_OPENCLOSE; + pkrb5_cc_set_flags(ctx, cc, ccflags); } code = pkrb5_cc_store_cred(ctx, cc, istgt ? &cc_creds : out_creds); @@ -1101,7 +1098,6 @@ khm_krb5_renew_cred(khm_handle cred) cleanup: - if (in_creds.client == me) in_creds.client = NULL; if (in_creds.server == server) @@ -1147,6 +1143,7 @@ khm_krb5_renew_ident(khm_handle identity) wchar_t idname[KCDB_IDENT_MAXCCH_NAME]; khm_size cb; khm_int32 k5_flags; + int ccflags; memset(&my_creds, 0, sizeof(krb5_creds)); @@ -1304,13 +1301,13 @@ khm_krb5_renew_ident(khm_handle identity) my_creds.client = me; my_creds.server = server; -#ifdef KRB5_TC_NOTICKET - pkrb5_cc_set_flags(ctx, cc, 0); -#endif + pkrb5_cc_set_flags(ctx, cc, KRB5_TC_OPENCLOSE); code = pkrb5_get_renewed_creds(ctx, &my_creds, me, cc, NULL); + ccflags = KRB5_TC_OPENCLOSE; #ifdef KRB5_TC_NOTICKET - pkrb5_cc_set_flags(ctx, cc, KRB5_TC_NOTICKET); + ccflags |= KRB5_TC_NOTICKET; #endif + pkrb5_cc_set_flags(ctx, cc, ccflags); if (code) { if ( code != KRB5KDC_ERR_ETYPE_NOSUPP || code != KRB5_KDC_UNREACH) @@ -1321,6 +1318,9 @@ khm_krb5_renew_ident(khm_handle identity) code = pkrb5_cc_initialize(ctx, cc, me); if (code) goto cleanup; + code = pkrb5_cc_set_flags(ctx, cc, KRB5_TC_OPENCLOSE); + if (code) goto cleanup; + code = pkrb5_cc_store_cred(ctx, cc, &my_creds); if (code) goto cleanup; @@ -3057,31 +3057,130 @@ get_libdefault_string(profile_t profile, const char * realm, return code; } + +const struct escape_char_sequences { + wchar_t character; + wchar_t escape; +} file_cc_escapes[] = { + + /* in ASCII order */ + + {L'\"', L'd'}, + {L'$', L'$'}, + {L'%', L'r'}, + {L'\'', L'i'}, + {L'*', L's'}, + {L'/', L'f'}, + {L':', L'c'}, + {L'<', L'l'}, + {L'>', L'g'}, + {L'?', L'q'}, + {L'\\', L'b'}, + {L'|', L'p'} +}; + +static void +escape_string_for_filename(const wchar_t * s, + wchar_t * buf, + khm_size cb_buf) +{ + wchar_t * d; + int i; + + for (d = buf; *s && cb_buf > sizeof(wchar_t) * 3; s++) { + if (iswpunct(*s)) { + for (i=0; i < ARRAYLENGTH(file_cc_escapes); i++) { + if (*s == file_cc_escapes[i].character) + break; + } + + if (i < ARRAYLENGTH(file_cc_escapes)) { + *d++ = L'$'; + *d++ = file_cc_escapes[i].escape; + cb_buf -= sizeof(wchar_t) * 2; + continue; + } + } + + *d++ = *s; + cb_buf -= sizeof(wchar_t); + } + +#ifdef DEBUG + assert(cb_buf >= sizeof(wchar_t)); +#endif + *d++ = L'\0'; +} + +static khm_int32 +get_default_file_cache_for_identity(const wchar_t * idname, + wchar_t * ccname, + khm_size * pcb) +{ + wchar_t escf[MAX_PATH] = L""; + wchar_t tmppath[MAX_PATH] = L""; + wchar_t tccname[MAX_PATH]; + khm_size cb; + + escape_string_for_filename(idname, escf, sizeof(escf)); + GetTempPath(ARRAYLENGTH(tmppath), tmppath); + + StringCbPrintf(tccname, sizeof(tccname), L"FILE:%s\\krb5cc.%s", tmppath, escf); + StringCbLength(tccname, sizeof(tccname), &cb); + cb += sizeof(wchar_t); + + if (ccname && *pcb >= cb) { + StringCbCopy(ccname, *pcb, tccname); + *pcb = cb; + return KHM_ERROR_SUCCESS; + } else { + *pcb = cb; + return KHM_ERROR_TOO_LONG; + } +} + khm_int32 khm_krb5_get_identity_default_ccache(khm_handle ident, wchar_t * buf, khm_size * pcb) { khm_handle csp_id = NULL; khm_int32 rv = KHM_ERROR_SUCCESS; + khm_size cbt; rv = khm_krb5_get_identity_config(ident, 0, &csp_id); + cbt = *pcb; if (KHM_SUCCEEDED(rv)) - rv = khc_read_string(csp_id, L"DefaultCCName", buf, pcb); + rv = khc_read_string(csp_id, L"DefaultCCName", buf, &cbt); - if (KHM_FAILED(rv) && rv != KHM_ERROR_TOO_LONG) { + if ((KHM_FAILED(rv) && rv != KHM_ERROR_TOO_LONG) || + (KHM_SUCCEEDED(rv) && buf[0] == L'\0')) { /* we need to figure out the default ccache from the principal name */ wchar_t idname[KCDB_IDENT_MAXCCH_NAME]; wchar_t ccname[MAX_PATH]; khm_size cb; + khm_int32 use_file_cache = 0; + + khc_read_int32(csp_id, L"DefaultToFileCache", &use_file_cache); cb = sizeof(idname); kcdb_identity_get_name(ident, idname, &cb); - StringCbCopy(ccname, sizeof(ccname), idname); + + if (use_file_cache) { + cb = sizeof(ccname); + rv = get_default_file_cache_for_identity(idname, ccname, &cb); +#ifdef DEBUG + assert(KHM_SUCCEEDED(rv)); +#endif + } else { /* generate an API: cache */ + StringCbPrintf(ccname, sizeof(ccname), L"API:%s", idname); + } khm_krb5_canon_cc_name(ccname, sizeof(ccname)); - StringCbLength(ccname, sizeof(ccname), &cb); _reportf(L"Setting CCache [%s] for identity [%s]", ccname, idname); + StringCbLength(ccname, sizeof(ccname), &cb); + cb += sizeof(wchar_t); + if (buf && *pcb >= cb) { StringCbCopy(buf, *pcb, ccname); *pcb = cb; @@ -3094,6 +3193,8 @@ khm_krb5_get_identity_default_ccache(khm_handle ident, wchar_t * buf, khm_size * wchar_t idname[KCDB_IDENT_MAXCCH_NAME]; khm_size cb; + *pcb = cbt; + cb = sizeof(idname); kcdb_identity_get_name(ident, idname, &cb); diff --git a/src/windows/identity/plugins/krb5/krb5newcreds.c b/src/windows/identity/plugins/krb5/krb5newcreds.c index 67fb8dac0..410393caf 100644 --- a/src/windows/identity/plugins/krb5/krb5newcreds.c +++ b/src/windows/identity/plugins/krb5/krb5newcreds.c @@ -181,7 +181,7 @@ k5_handle_wmnc_notify(HWND hwnd, case WMNC_DIALOG_MOVE: { k5_dlg_data * d; - + d = (k5_dlg_data *)(LONG_PTR) GetWindowLongPtr(hwnd, DWLP_USER); @@ -1355,34 +1355,9 @@ k5_read_dlg_params(k5_dlg_data * d, khm_handle identity) d->sync = FALSE; } -void -k5_write_dlg_params(k5_dlg_data * d, khm_handle identity, char * ccache) +void +k5_ensure_identity_ccache_is_watched(khm_handle identity, char * ccache) { - - k5_params p; - - ZeroMemory(&p, sizeof(p)); - - p.source_reg = K5PARAM_FM_ALL; /* we want to write all the - settings to the registry, if - necessary. */ - - p.renewable = d->renewable; - p.forwardable = d->forwardable; - p.proxiable = d->proxiable; - p.addressless = d->addressless; - p.publicIP = d->publicIP; - - p.lifetime = (krb5_deltat) d->tc_lifetime.current; - p.lifetime_max = (krb5_deltat) d->tc_lifetime.max; - p.lifetime_min = (krb5_deltat) d->tc_lifetime.min; - - p.renew_life = (krb5_deltat) d->tc_renew.current; - p.renew_life_max = (krb5_deltat) d->tc_renew.max; - p.renew_life_min = (krb5_deltat) d->tc_renew.min; - - khm_krb5_set_identity_params(identity, &p); - /* if we used a FILE: ccache, we should add it to FileCCList. Otherwise the tickets are not going to get listed. */ do { @@ -1462,6 +1437,37 @@ k5_write_dlg_params(k5_dlg_data * d, khm_handle identity, char * ccache) PFREE(mlist); } while(FALSE); +} + +void +k5_write_dlg_params(k5_dlg_data * d, khm_handle identity, char * ccache) +{ + + k5_params p; + + ZeroMemory(&p, sizeof(p)); + + p.source_reg = K5PARAM_FM_ALL; /* we want to write all the + settings to the registry, if + necessary. */ + + p.renewable = d->renewable; + p.forwardable = d->forwardable; + p.proxiable = d->proxiable; + p.addressless = d->addressless; + p.publicIP = d->publicIP; + + p.lifetime = (krb5_deltat) d->tc_lifetime.current; + p.lifetime_max = (krb5_deltat) d->tc_lifetime.max; + p.lifetime_min = (krb5_deltat) d->tc_lifetime.min; + + p.renew_life = (krb5_deltat) d->tc_renew.current; + p.renew_life_max = (krb5_deltat) d->tc_renew.max; + p.renew_life_min = (krb5_deltat) d->tc_renew.min; + + khm_krb5_set_identity_params(identity, &p); + + k5_ensure_identity_ccache_is_watched(identity, ccache); /* as in k5_read_dlg_params, once we write the data in, the local data is no longer dirty */ @@ -2059,6 +2065,9 @@ k5_msg_cred_dialog(khm_int32 msg_type, if(g_fjob.state == FIBER_STATE_NONE) { wchar_t msg[KHUI_MAXCCH_BANNER]; khm_size cb; + int code; + + code = g_fjob.code; /* Special case. If the users' password has expired, we force a password change dialog on @@ -2143,7 +2152,7 @@ k5_msg_cred_dialog(khm_int32 msg_type, k5_free_kinit_job(); if (is_k5_identpro) { - if (g_fjob.code == 0) + if (code == 0) kcdb_identity_set_flags(ident, KCDB_IDENT_FLAG_VALID, KCDB_IDENT_FLAG_VALID); @@ -2832,6 +2841,9 @@ k5_msg_cred_dialog(khm_int32 msg_type, imported = khm_krb5_ms2mit(NULL, (t == K5_LSAIMPORT_MATCH), TRUE, &id_imported); if (imported) { + if (id_imported) + k5_ensure_identity_ccache_is_watched(id_imported, NULL); + khm_krb5_list_tickets(&ctx); if (ctx) diff --git a/src/windows/identity/plugins/krb5/krbconfig.csv b/src/windows/identity/plugins/krb5/krbconfig.csv index 4dc5b7d72..cb4a860d9 100644 --- a/src/windows/identity/plugins/krb5/krbconfig.csv +++ b/src/windows/identity/plugins/krb5/krbconfig.csv @@ -27,6 +27,7 @@ Krb5Cred,KC_SPACE,0,Kerberos V Credentials Provider LastDefaultIdent,KC_STRING,,Last known default identity
PromptCacheLifetime,KC_INT32,172800,Lifetime of the prompt cache in seconds
DefaultCCName,KC_STRING,,Default CC name (only per identity)
+ DefaultToFileCache,KC_INT32,0,"If no DefaultCCName is specified for an identity, use a generated FILE: cache instead of an API: cache"
PromptCache,KC_SPACE,0,Cache of prompts (only per identity)
Name,KC_STRING,,
Banner,KC_STRING,,
|
