#ifdef KRB5_TC_NOTICKET
flags = KRB5_TC_NOTICKET;
-#else
- flags = 0;
#endif
{
khm_boolean istgt = FALSE;
khm_int32 flags;
+ int ccflags = 0;
cbname = sizeof(wname);
kcdb_cred_get_name(cred, wname, &cbname);
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))
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)
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);
cleanup:
-
if (in_creds.client == me)
in_creds.client = NULL;
if (in_creds.server == server)
wchar_t idname[KCDB_IDENT_MAXCCH_NAME];
khm_size cb;
khm_int32 k5_flags;
+ int ccflags;
memset(&my_creds, 0, sizeof(krb5_creds));
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)
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;
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;
wchar_t idname[KCDB_IDENT_MAXCCH_NAME];
khm_size cb;
+ *pcb = cbt;
+
cb = sizeof(idname);
kcdb_identity_get_name(ident, idname, &cb);
case WMNC_DIALOG_MOVE:
{
k5_dlg_data * d;
-
+
d = (k5_dlg_data *)(LONG_PTR)
GetWindowLongPtr(hwnd, DWLP_USER);
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 {
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 */
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
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);
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)