summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/windows/identity/plugins/krb5/krb5configid.c17
-rw-r--r--src/windows/identity/plugins/krb5/krb5funcs.c135
-rw-r--r--src/windows/identity/plugins/krb5/krb5newcreds.c70
-rw-r--r--src/windows/identity/plugins/krb5/krbconfig.csv1
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,,