static khm_int32 KHMAPI collect_cell_names(khm_handle cred, void * rock) { wchar_t *str = (wchar_t *) rock; wchar_t cell[KCDB_MAXCCH_NAME] = L""; FILETIME ft_now; FILETIME ft_expire; khm_size cb; cb = sizeof(ft_expire); if (KHM_FAILED(kcdb_cred_get_attr(cred, KCDB_ATTR_EXPIRE, NULL, &ft_expire, &cb))) return KHM_ERROR_SUCCESS; GetSystemTimeAsFileTime(&ft_now); if (CompareFileTime(&ft_now, &ft_expire) >= 0) return KHM_ERROR_SUCCESS; cb = sizeof(cell); if (KHM_SUCCEEDED(kcdb_cred_get_attr(cred, afs_attr_cell, NULL, cell, &cb)) && cell[0]) { StringCchCat(str, COLLECT_STR_LEN, cell); StringCchCat(str, COLLECT_STR_LEN, L"\n"); } return KHM_ERROR_SUCCESS; }
KHMEXP khm_int32 KHMAPI kcdb_buf_get_attr( khm_handle record, khm_int32 attr_id, khm_int32 * attr_type, void * buffer, khm_size * pcb_buf) { if(kcdb_cred_is_active_cred(record)) return kcdb_cred_get_attr(record, attr_id, attr_type, buffer, pcb_buf); else if(kcdb_is_active_identity(record)) return kcdb_identity_get_attr(record, attr_id, attr_type, buffer, pcb_buf); else return KHM_ERROR_INVALID_PARAM; }
khm_int32 krb4_msg_newcred(khm_int32 msg_type, khm_int32 msg_subtype, khm_ui_4 uparam, void * vparam) { switch(msg_subtype) { case KMSG_CRED_NEW_CREDS: { khui_new_creds * nc; khui_new_creds_by_type * nct; khm_size cbsize; wchar_t wbuf[256]; nc = (khui_new_creds *) vparam; nct = PMALLOC(sizeof(*nct)); #ifdef DEBUG assert(nct); #endif ZeroMemory(nct, sizeof(*nct)); nct->type = credtype_id_krb4; nct->ordinal = 3; LoadString(hResModule, IDS_NC_K4_SHORT, wbuf, ARRAYLENGTH(wbuf)); StringCbLength(wbuf, sizeof(wbuf), &cbsize); cbsize += sizeof(wchar_t); nct->name = PMALLOC(cbsize); StringCbCopy(nct->name, cbsize, wbuf); nct->type_deps[nct->n_type_deps++] = credtype_id_krb5; nct->h_module = hResModule; nct->dlg_proc = k4_nc_dlg_proc; nct->dlg_template = MAKEINTRESOURCE(IDD_NC_KRB4); khui_cw_add_type(nc, nct); } break; case KMSG_CRED_RENEW_CREDS: { khui_new_creds * nc; khui_new_creds_by_type * nct; khm_size cbsize; wchar_t wbuf[256]; khui_action_context * pctx = NULL; nc = (khui_new_creds *) vparam; pctx = khui_cw_get_ctx(nc); if (!pctx->identity) break; nct = PMALLOC(sizeof(*nct)); #ifdef DEBUG assert(nct); #endif ZeroMemory(nct, sizeof(*nct)); nct->type = credtype_id_krb4; nct->ordinal = 3; LoadString(hResModule, IDS_NC_K4_SHORT, wbuf, ARRAYLENGTH(wbuf)); StringCbLength(wbuf, sizeof(wbuf), &cbsize); cbsize += sizeof(wchar_t); nct->name = PMALLOC(cbsize); StringCbCopy(nct->name, cbsize, wbuf); nct->type_deps[nct->n_type_deps++] = credtype_id_krb5; khui_cw_add_type(nc, nct); } break; case KMSG_CRED_DIALOG_SETUP: break; case KMSG_CRED_PROCESS: { khui_new_creds * nc; khui_new_creds_by_type * nct = NULL; khm_handle ident = NULL; khui_action_context * pctx = NULL; k4_dlg_data * d = NULL; long code = 0; wchar_t idname[KCDB_IDENT_MAXCCH_NAME]; khm_size cb; khm_int32 subtype; nc = (khui_new_creds *) vparam; if (KHM_FAILED(khui_cw_find_type(nc, credtype_id_krb4, &nct))) break; subtype = khui_cw_get_subtype(nc); if (subtype == KMSG_CRED_NEW_CREDS || subtype == KMSG_CRED_RENEW_CREDS) { khm_int32 method; if (subtype == KMSG_CRED_NEW_CREDS) { d = (k4_dlg_data *) nct->aux; if (KHM_FAILED(khui_cw_get_primary_id(nc, &ident))) break; if (!d || khui_cw_get_result(nc) != KHUI_NC_RESULT_PROCESS) { khui_cw_set_response(nc, credtype_id_krb4, KHUI_NC_RESPONSE_SUCCESS | KHUI_NC_RESPONSE_EXIT); kcdb_identity_release(ident); break; } if (!d->k4_enabled) { k4_write_identity_data(d); khui_cw_set_response(nc, credtype_id_krb4, KHUI_NC_RESPONSE_SUCCESS | KHUI_NC_RESPONSE_EXIT); kcdb_identity_release(ident); break; } method = d->method; cb = sizeof(idname); kcdb_identity_get_name(ident, idname, &cb); _begin_task(0); _report_sr0(KHERR_NONE, IDS_MSG_K4NEW); _resolve(); _describe(); } else if (subtype == KMSG_CRED_RENEW_CREDS) { pctx = khui_cw_get_ctx(nc); if ((pctx->scope == KHUI_SCOPE_IDENT && pctx->identity != NULL) || (pctx->scope == KHUI_SCOPE_CREDTYPE && pctx->cred_type == credtype_id_krb4 && pctx->identity != NULL) || (pctx->scope == KHUI_SCOPE_CRED && pctx->cred_type == credtype_id_krb4 && pctx->identity != NULL && pctx->cred != NULL)) { ident = pctx->identity; kcdb_identity_hold(ident); if (!k4_should_identity_get_k4(ident)) { _reportf(L"Kerberos 4 is not enabled for this identity. Skipping"); khui_cw_set_response(nc, credtype_id_krb4, KHUI_NC_RESPONSE_FAILED | KHUI_NC_RESPONSE_EXIT); kcdb_identity_release(ident); break; } } else { _reportf(L"Kerberos 4 is not within renewal scope. Skipping"); khui_cw_set_response(nc, credtype_id_krb4, KHUI_NC_RESPONSE_FAILED | KHUI_NC_RESPONSE_EXIT); break; } method = K4_METHOD_K524; /* only k524 is supported for renewals */ _begin_task(0); cb = sizeof(idname); kcdb_identity_get_name(ident, idname, &cb); _report_sr0(KHERR_NONE, IDS_MSG_K4RENEW); _resolve(); _describe(); } else { assert(FALSE); break; } _progress(0,1); if ((method == K4_METHOD_AUTO || method == K4_METHOD_K524) && khui_cw_type_succeeded(nc, credtype_id_krb5)) { khm_handle tgt; FILETIME ft_prev; FILETIME ft_new; khm_size cb; _report_cs0(KHERR_INFO, L"Trying K524..."); tgt = khm_krb4_find_tgt(NULL, ident); _progress(1,3); if (tgt) { cb = sizeof(ft_prev); if (KHM_FAILED(kcdb_cred_get_attr(tgt, KCDB_ATTR_EXPIRE, NULL, &ft_prev, &cb))) ZeroMemory(&ft_prev, sizeof(ft_prev)); kcdb_cred_release(tgt); } code = khm_convert524(ident); _progress(2,3); _reportf(L"khm_convert524 returns code %d", code); if (code == 0) { khui_cw_set_response(nc, credtype_id_krb4, KHUI_NC_RESPONSE_SUCCESS | KHUI_NC_RESPONSE_EXIT); if (subtype == KMSG_CRED_NEW_CREDS) { assert(d != NULL); k4_write_identity_data(d); } else if (subtype == KMSG_CRED_RENEW_CREDS && (pctx->scope == KHUI_SCOPE_CREDTYPE || pctx->scope == KHUI_SCOPE_CRED)) { khm_krb4_list_tickets(); tgt = khm_krb4_find_tgt(NULL, ident); if (tgt) { cb = sizeof(ft_new); ZeroMemory(&ft_new, sizeof(ft_new)); kcdb_cred_get_attr(tgt, KCDB_ATTR_EXPIRE, NULL, &ft_new, &cb); kcdb_cred_release(tgt); } if (!tgt || CompareFileTime(&ft_new, &ft_prev) <= 0) { /* The new TGT wasn't much of an improvement over what we already had. We should go out and try to renew the identity now. */ khui_action_context ctx; _reportf(L"Renewal of Krb4 creds failed to get a longer TGT. Triggering identity renewal"); khui_context_create(&ctx, KHUI_SCOPE_IDENT, pctx->identity, KCDB_CREDTYPE_INVALID, NULL); khui_action_trigger(KHUI_ACTION_RENEW_CRED, &ctx); khui_context_release(&ctx); } } _progress(1,1); _end_task(); if (ident) kcdb_identity_release(ident); break; } else if (method == K4_METHOD_K524) { khui_cw_set_response(nc, credtype_id_krb4, KHUI_NC_RESPONSE_FAILED | KHUI_NC_RESPONSE_EXIT); if (subtype == KMSG_CRED_RENEW_CREDS && (pctx->scope == KHUI_SCOPE_CREDTYPE || pctx->scope == KHUI_SCOPE_CRED)) { /* We were trying to get a new Krb4 TGT for this identity. Sometimes this fails because of restrictions placed on K524d regarding the lifetime of the issued K4 TGT. In this case, we trigger a renewal of the identity in the hope that the new K5 TGT will allow us to successfully get a new K4 TGT next time over using the new K5 TGT. */ khui_action_context ctx; _reportf(L"Renewal of Krb4 creds failed using k524. Triggerring identity renewal."); khui_context_create(&ctx, KHUI_SCOPE_IDENT, pctx->identity, KCDB_CREDTYPE_INVALID, NULL); khui_action_trigger(KHUI_ACTION_RENEW_CRED, &ctx); khui_context_release(&ctx); } _progress(1,1); _end_task(); if (ident) kcdb_identity_release(ident); break; } } /* only supported for new credentials */ if (method == K4_METHOD_AUTO || method == K4_METHOD_PASSWORD) { khm_size n_prompts = 0; khm_size idx; khm_size cb; wchar_t wpwd[KHUI_MAXCCH_PROMPT_VALUE]; char pwd[KHUI_MAXCCH_PROMPT_VALUE]; wchar_t widname[KCDB_IDENT_MAXCCH_NAME]; char idname[KCDB_IDENT_MAXCCH_NAME]; char * aname = NULL; char * inst = NULL; char * realm = NULL; assert(subtype == KMSG_CRED_NEW_CREDS); _report_cs0(KHERR_INFO, L"Trying password ..."); code = TRUE; /* just has to be non-zero */ khui_cw_get_prompt_count(nc, &n_prompts); if (n_prompts == 0) goto _skip_pwd; for (idx = 0; idx < n_prompts; idx++) { khui_new_creds_prompt * p; if (KHM_FAILED(khui_cw_get_prompt(nc, idx, &p))) continue; if (p->type == KHUI_NCPROMPT_TYPE_PASSWORD) break; } if (idx >= n_prompts) { _reportf(L"Password prompt not found"); goto _skip_pwd; } khui_cw_sync_prompt_values(nc); cb = sizeof(wpwd); if (KHM_FAILED(khui_cw_get_prompt_value(nc, idx, wpwd, &cb))) { _reportf(L"Failed to obtain password value"); goto _skip_pwd; } UnicodeStrToAnsi(pwd, sizeof(pwd), wpwd); cb = sizeof(widname); kcdb_identity_get_name(ident, widname, &cb); UnicodeStrToAnsi(idname, sizeof(idname), widname); { char * atsign; atsign = strchr(idname, '@'); if (atsign == NULL) { _reportf(L"Identity name does not contain an '@'"); goto _skip_pwd; } *atsign++ = 0; realm = atsign; } { char * slash; slash = strchr(idname, '/'); if (slash != NULL) { *slash++ = 0; inst = slash; } else { inst = ""; } } aname = idname; code = khm_krb4_kinit(aname, inst, realm, (long) d->lifetime, pwd); _progress(2,3); _reportf(L"khm_krb4_kinit returns code %d", code); _skip_pwd: if (code) { khui_cw_set_response(nc, credtype_id_krb4, KHUI_NC_RESPONSE_EXIT | KHUI_NC_RESPONSE_FAILED); } else { khui_cw_set_response(nc, credtype_id_krb4, KHUI_NC_RESPONSE_EXIT | KHUI_NC_RESPONSE_SUCCESS); if (subtype == KMSG_CRED_NEW_CREDS) { assert(d != NULL); k4_write_identity_data(d); } } } _progress(1,1); _end_task(); } if (ident) kcdb_identity_release(ident); } break; case KMSG_CRED_END: { khui_new_creds * nc; khui_new_creds_by_type * nct = NULL; nc = (khui_new_creds *) vparam; if (KHM_FAILED(khui_cw_find_type(nc, credtype_id_krb4, &nct))) break; khui_cw_del_type(nc, credtype_id_krb4); if (nct->name) PFREE(nct->name); if (nct->credtext) PFREE(nct->credtext); PFREE(nct); } break; } return KHM_ERROR_SUCCESS; }
/* Dialog procedure for the property sheet. This will run under the UI thread when a property sheet is being displayed for one of our credentials.. */ INT_PTR CALLBACK pp_cred_dlg_proc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { khui_property_sheet * ps; switch (uMsg) { case WM_INITDIALOG: { PROPSHEETPAGE * p; wchar_t notavailable[128]; p = (PROPSHEETPAGE *) lParam; ps = (khui_property_sheet *) p->lParam; #pragma warning(push) #pragma warning(disable: 4244) SetWindowLongPtr(hwnd, DWLP_USER, (LONG_PTR) ps); #pragma warning(pop) if (ps->cred) { wchar_t tbuf[512]; khm_size cb; khm_handle ident = NULL; LoadString(hResModule, IDS_NOTAVAILABLE, notavailable, ARRAYLENGTH(notavailable)); cb = sizeof(tbuf); if (KHM_SUCCEEDED(kcdb_cred_get_attr_string(ps->cred, attr_id_subj_email, tbuf, &cb, KCDB_TS_LONG))) { SetDlgItemText(hwnd, IDC_PP_SUBJ_E, tbuf); } else { SetDlgItemText(hwnd, IDC_PP_SUBJ_E, notavailable); } cb = sizeof(tbuf); if (KHM_SUCCEEDED(kcdb_cred_get_attr_string(ps->cred, attr_id_subj_display, tbuf, &cb, KCDB_TS_LONG))) { SetDlgItemText(hwnd, IDC_PP_SUBJ_D, tbuf); } else { SetDlgItemText(hwnd, IDC_PP_SUBJ_D, notavailable); } cb = sizeof(tbuf); if (KHM_SUCCEEDED(kcdb_cred_get_attr_string(ps->cred, attr_id_auth_realm, tbuf, &cb, KCDB_TS_LONG))) { SetDlgItemText(hwnd, IDC_PP_REALM, tbuf); } else { SetDlgItemText(hwnd, IDC_PP_REALM, notavailable); } cb = sizeof(tbuf); if (KHM_SUCCEEDED(kcdb_cred_get_attr_string(ps->cred, attr_id_issuer_display, tbuf, &cb, KCDB_TS_LONG))) { SetDlgItemText(hwnd, IDC_PP_ISSUER, tbuf); } else { SetDlgItemText(hwnd, IDC_PP_ISSUER, notavailable); } cb = sizeof(tbuf); if (KHM_SUCCEEDED(kcdb_cred_get_attr_string(ps->cred, KCDB_ATTR_ISSUE, tbuf, &cb, KCDB_TS_LONG))) { SetDlgItemText(hwnd, IDC_PP_NOTBEFORE, tbuf); } else { SetDlgItemText(hwnd, IDC_PP_NOTBEFORE, notavailable); } cb = sizeof(tbuf); if (KHM_SUCCEEDED(kcdb_cred_get_attr_string(ps->cred, KCDB_ATTR_EXPIRE, tbuf, &cb, KCDB_TS_LONG))) { SetDlgItemText(hwnd, IDC_PP_NOTAFTER, tbuf); } else { SetDlgItemText(hwnd, IDC_PP_NOTAFTER, notavailable); } } else { #ifdef DEBUG /* we really shouldn't get here */ DebugBreak(); #endif } } return FALSE; case WM_COMMAND: { HCERTSTORE hStoreHandle = NULL; PCCERT_CONTEXT pCertContext = NULL; CERT_ID certId; BYTE sn_buf[1024]; BYTE issuer_buf[1024]; CRYPTUI_VIEWCERTIFICATE_STRUCT vcs; wchar_t title_fmt[128]; wchar_t cert_name[128]; wchar_t title[256]; BOOL b; khm_size cb; if (wParam != MAKEWPARAM(IDC_PP_DETAILS, BN_CLICKED)) break; ps = (khui_property_sheet *) GetWindowLongPtr(hwnd, DWLP_USER); if (ps == NULL || ps->cred == NULL) { #ifdef DEBUG DebugBreak(); #endif break; } /* we need to display the standard UI for this certificate */ ZeroMemory(&certId, sizeof(certId)); cb = sizeof(sn_buf); if (KHM_FAILED(kcdb_cred_get_attr(ps->cred, attr_id_serial_number, NULL, sn_buf, &cb))) { break; } certId.IssuerSerialNumber.SerialNumber.cbData = (DWORD)cb; certId.IssuerSerialNumber.SerialNumber.pbData = sn_buf; cb = sizeof(issuer_buf); if (KHM_FAILED(kcdb_cred_get_attr(ps->cred, attr_id_issuer_name, NULL, issuer_buf, &cb))) { break; } certId.IssuerSerialNumber.Issuer.cbData = (DWORD)cb; certId.IssuerSerialNumber.Issuer.pbData = issuer_buf; certId.dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER; if (!(hStoreHandle = CertOpenSystemStore(0, WIN32MYCERT_STORE))) { log_printf("Unable to access the system store"); return TRUE; } pCertContext = CertFindCertificateInStore(hStoreHandle, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0, CERT_FIND_CERT_ID, &certId, NULL); if (!pCertContext) { /* the certificate was not found */ EnableWindow(GetDlgItem(hwnd, IDC_PP_DETAILS), FALSE); goto _clean_dt; } ZeroMemory(&vcs, sizeof(vcs)); vcs.dwSize = sizeof(vcs); vcs.hwndParent = hwnd; vcs.dwFlags = 0; LoadString(hResModule, IDS_PP_TITLE, title_fmt, ARRAYLENGTH(title_fmt)); cb = sizeof(cert_name); if (KHM_FAILED(kcdb_cred_get_attr(ps->cred, attr_id_auth_realm, NULL, cert_name, &cb))) { cb = sizeof(cert_name); if (KHM_FAILED(kcdb_cred_get_attr(ps->cred, attr_id_subj_email, NULL, cert_name, &cb))) { cb = sizeof(cert_name); kcdb_get_resource(ps->cred, KCDB_RES_DISPLAYNAME, 0, NULL, NULL, cert_name, &cb); } } StringCbPrintf(title, sizeof(title), title_fmt, cert_name); vcs.szTitle = title; vcs.pCertContext = pCertContext; CryptUIDlgViewCertificate(&vcs, &b); _clean_dt: if (pCertContext) { CertFreeCertificateContext(pCertContext); pCertContext = NULL; } if (hStoreHandle) { CertCloseStore(hStoreHandle, 0); hStoreHandle = NULL; } return TRUE; } break; } return FALSE; }
/* Property page Runs in the context of the UI thread. */ INT_PTR CALLBACK krb5_pp_proc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) { switch(uMsg) { case WM_INITDIALOG: { khui_property_sheet * s; PROPSHEETPAGE * p; wchar_t buf[512]; wchar_t unavailable[64]; khm_size cbsize; khm_int32 rv; khm_int32 tflags; p = (PROPSHEETPAGE *) lParam; s = (khui_property_sheet *) p->lParam; #pragma warning(push) #pragma warning(disable: 4244) SetWindowLongPtr(hwnd, DWLP_USER, (LONG_PTR) s); #pragma warning(pop) LoadString(hResModule, IDS_UNAVAILABLE, unavailable, ARRAYLENGTH(unavailable)); if(s->cred) { cbsize = sizeof(buf); kcdb_cred_get_name(s->cred, buf, &cbsize); SetDlgItemText(hwnd, IDC_PPK5_NAME, buf); cbsize = sizeof(buf); rv = kcdb_cred_get_attr_string(s->cred, KCDB_ATTR_ISSUE, buf, &cbsize, 0); if (KHM_SUCCEEDED(rv)) SetDlgItemText(hwnd, IDC_PPK5_ISSUE, buf); else SetDlgItemText(hwnd, IDC_PPK5_ISSUE, unavailable); cbsize = sizeof(buf); rv = kcdb_cred_get_attr_string(s->cred, KCDB_ATTR_EXPIRE, buf, &cbsize, 0); if (KHM_SUCCEEDED(rv)) SetDlgItemText(hwnd, IDC_PPK5_VALID, buf); else SetDlgItemText(hwnd, IDC_PPK5_VALID, unavailable); cbsize = sizeof(buf); rv = kcdb_cred_get_attr_string(s->cred, KCDB_ATTR_RENEW_EXPIRE, buf, &cbsize, 0); if (KHM_SUCCEEDED(rv)) SetDlgItemText(hwnd, IDC_PPK5_RENEW, buf); else SetDlgItemText(hwnd, IDC_PPK5_RENEW, unavailable); tflags = 0; cbsize = sizeof(tflags); rv = kcdb_cred_get_attr(s->cred, attr_id_krb5_flags, NULL, &tflags, &cbsize); if (KHM_SUCCEEDED(rv)) { #define ADDBITFLAG(f,s) \ if (tflags & f) { \ LoadString(hResModule, s, buf, ARRAYLENGTH(buf)); \ SendDlgItemMessage(hwnd, IDC_PPK5_FLAGS, LB_ADDSTRING, 0, (LPARAM) buf); \ } ADDBITFLAG(TKT_FLG_FORWARDABLE, IDS_FLG_FORWARDABLE); ADDBITFLAG(TKT_FLG_FORWARDED, IDS_FLG_FORWARDED); ADDBITFLAG(TKT_FLG_PROXIABLE, IDS_FLG_PROXIABLE); ADDBITFLAG(TKT_FLG_PROXY, IDS_FLG_PROXY); ADDBITFLAG(TKT_FLG_MAY_POSTDATE, IDS_FLG_MAY_POSTDATE); ADDBITFLAG(TKT_FLG_POSTDATED, IDS_FLG_POSTDATED); ADDBITFLAG(TKT_FLG_INVALID, IDS_FLG_INVALID); ADDBITFLAG(TKT_FLG_RENEWABLE, IDS_FLG_RENEWABLE); ADDBITFLAG(TKT_FLG_INITIAL, IDS_FLG_INITIAL); ADDBITFLAG(TKT_FLG_PRE_AUTH, IDS_FLG_PRE_AUTH); ADDBITFLAG(TKT_FLG_HW_AUTH, IDS_FLG_HW_AUTH); ADDBITFLAG(TKT_FLG_TRANSIT_POLICY_CHECKED, IDS_FLG_TRANSIT_POL); ADDBITFLAG(TKT_FLG_OK_AS_DELEGATE, IDS_FLG_OK_DELEGATE); ADDBITFLAG(TKT_FLG_ANONYMOUS, IDS_FLG_ANONYMOUS); #undef ADDBITFLAG } } else { #ifdef DEBUG assert(FALSE); #endif } } return FALSE; } return FALSE; }