/*! \internal \brief Initialize a plugin \note If kmmint_init_plugin() is called on a plugin, then kmmint_exit_plugin() \b must be called for the plugin. \note Should only be called from the context of the registrar thread */ void kmmint_init_plugin(kmm_plugin_i * p) { DWORD dummy; khm_handle csp_plugin = NULL; khm_handle csp_plugins = NULL; khm_int32 t; /* the following will be undone in kmmint_exit_plugin() */ kmm_hold_plugin(kmm_handle_from_plugin(p)); EnterCriticalSection(&cs_kmm); if(p->state != KMM_PLUGIN_STATE_REG && p->state != KMM_PLUGIN_STATE_HOLD) { LeaveCriticalSection(&cs_kmm); goto _exit; } _begin_task(0); _report_mr1(KHERR_NONE, MSG_IP_TASK_DESC, _cstr(p->p.name)); _describe(); if(p->state == KMM_PLUGIN_STATE_HOLD) { /* if this plugin was held, then we already had a hold from the initial attempt to start the plugin. Undo the hold we did a few lines earlier. */ kmm_release_plugin(kmm_handle_from_plugin(p)); /* same for the plugin count for the module. */ #ifdef DEBUG assert(p->flags & KMM_PLUGIN_FLAG_IN_MODCOUNT); #endif p->module->plugin_count--; p->flags &= ~KMM_PLUGIN_FLAG_IN_MODCOUNT; } p->state = KMM_PLUGIN_STATE_PREINIT; kmmint_delist_plugin(p); kmmint_list_plugin(p); LeaveCriticalSection(&cs_kmm); if(KHM_FAILED(kmm_get_plugins_config(0, &csp_plugins))) { _report_mr0(KHERR_ERROR, MSG_IP_GET_CONFIG); p->state = KMM_PLUGIN_STATE_FAIL_UNKNOWN; goto _exit; } if(KHM_FAILED(kmm_get_plugin_config(p->p.name, 0, &csp_plugin))) { if(KHM_FAILED(kmm_register_plugin(&(p->p), 0))) { _report_mr0(KHERR_ERROR, MSG_IP_NOT_REGISTERED); p->state = KMM_PLUGIN_STATE_FAIL_NOT_REGISTERED; goto _exit; } if(KHM_FAILED(kmm_get_plugin_config(p->p.name, 0, &csp_plugin))) { _report_mr0(KHERR_ERROR, MSG_IP_NOT_REGISTERED); p->state = KMM_PLUGIN_STATE_FAIL_NOT_REGISTERED; goto _exit; } } if (KHM_SUCCEEDED(khc_read_int32(csp_plugin, L"Disabled", &t)) && t) { p->flags |= KMM_PLUGIN_FLAG_DISABLED; p->state = KMM_PLUGIN_STATE_FAIL_DISABLED; goto _exit; } #if 0 /*TODO: check the failure count and act accordingly */ if(KHM_SUCCEEDED(khc_read_int32(csp_plugin, L"FailureCount", &t)) && (t > 0)) { } #endif EnterCriticalSection(&cs_kmm); p->n_depends = 0; p->n_unresolved = 0; do { wchar_t * deps = NULL; wchar_t * d; khm_size sz = 0; if(khc_read_multi_string(csp_plugin, L"Dependencies", NULL, &sz) != KHM_ERROR_TOO_LONG) break; deps = PMALLOC(sz); if(KHM_FAILED(khc_read_multi_string(csp_plugin, L"Dependencies", deps, &sz))) { if(deps) PFREE(deps); break; } for(d = deps; d && *d; d = multi_string_next(d)) { kmm_plugin_i * pd; int i; pd = kmmint_get_plugin_i(d); if(pd->state == KMM_PLUGIN_STATE_NONE) { /* the dependant was not previously known */ pd->state = KMM_PLUGIN_STATE_PLACEHOLDER; } for(i=0; i < pd->n_dependants; i++) { if(pd->dependants[i] == p) break; } if(i >= pd->n_dependants) { if( pd->n_dependants >= KMM_MAX_DEPENDANTS ) { /*TODO: handle this gracefully */ RaiseException(1, EXCEPTION_NONCONTINUABLE, 0, NULL); } /* released in kmmint_free_plugin() */ kmm_hold_plugin(kmm_handle_from_plugin(p)); pd->dependants[pd->n_dependants] = p; pd->n_dependants++; } p->n_depends++; if(pd->state != KMM_PLUGIN_STATE_RUNNING) { p->n_unresolved++; } } if(p->n_unresolved > 0) { p->state = KMM_PLUGIN_STATE_HOLD; } PFREE(deps); } while(FALSE); #ifdef DEBUG assert(!(p->flags & KMM_PLUGIN_FLAG_IN_MODCOUNT)); #endif p->flags |= KMM_PLUGIN_FLAG_IN_MODCOUNT; p->module->plugin_count++; LeaveCriticalSection(&cs_kmm); if(p->state == KMM_PLUGIN_STATE_HOLD) { _report_mr1(KHERR_INFO, MSG_IP_HOLD, _dupstr(p->p.name)); goto _exit_post; } kmmint_add_to_plugin_queue(p); p->ht_thread = CreateThread(NULL, 0, kmmint_plugin_broker, (LPVOID) p, CREATE_SUSPENDED, &dummy); p->state = KMM_PLUGIN_STATE_INIT; ResumeThread(p->ht_thread); _exit_post: if(csp_plugin != NULL) khc_close_space(csp_plugin); if(csp_plugins != NULL) khc_close_space(csp_plugins); _report_mr2(KHERR_INFO, MSG_IP_STATE, _dupstr(p->p.name), _int32(p->state)); _end_task(); return; /* jump here if an error condition happens before the plugin broker thread starts and the plugin should be unloaded */ _exit: if(csp_plugin != NULL) khc_close_space(csp_plugin); if(csp_plugins != NULL) khc_close_space(csp_plugins); _report_mr2(KHERR_WARNING, MSG_IP_EXITING, _dupstr(p->p.name), _int32(p->state)); _end_task(); #ifdef ASYNC_PLUGIN_UNLOAD_ON_FAILURE kmm_hold_plugin(kmm_handle_from_plugin(p)); kmq_post_message(KMSG_KMM, KMSG_KMM_I_REG, KMM_REG_EXIT_PLUGIN, (void *) p); #else kmmint_exit_plugin(p); #endif }
/*! \internal \brief Initialize a module \a m is not in the linked list yet. \note Should only be called from the context of the registrar thread. */ void kmmint_init_module(kmm_module_i * m) { HMODULE hm; init_module_t p_init_module; kmm_plugin_i * pi; khm_int32 rv; khm_handle csp_mod = NULL; khm_handle csp_mods = NULL; khm_size sz; khm_int32 i; /* error condition handling */ BOOL exit_module = FALSE; BOOL release_module = TRUE; BOOL record_failure = FALSE; /* failure handling */ khm_int32 max_fail_count = 0; khm_int64 fail_reset_time = 0; _begin_task(0); _report_mr1(KHERR_NONE, MSG_INIT_MODULE, _cstr(m->name)); _describe(); kmm_hold_module(kmm_handle_from_module(m)); if(KHM_FAILED(kmm_get_modules_config(0, &csp_mods))) { _report_mr0(KHERR_ERROR, MSG_IM_GET_CONFIG); _location(L"kmm_get_modules_config()"); m->state = KMM_MODULE_STATE_FAIL_UNKNOWN; goto _exit; } khc_read_int32(csp_mods, L"ModuleMaxFailureCount", &max_fail_count); khc_read_int64(csp_mods, L"ModuleFailureCountResetTime", &fail_reset_time); /* If the module is not in the pre-init state, we can't initialize it. */ if(m->state != KMM_MODULE_STATE_PREINIT) { _report_mr1(KHERR_INFO, MSG_IM_NOT_PREINIT, _int32(m->state)); goto _exit; } if(KHM_FAILED(kmm_get_module_config(m->name, 0, &csp_mod))) { _report_mr0(KHERR_ERROR, MSG_IM_NOT_REGISTERED); m->state = KMM_MODULE_STATE_FAIL_NOT_REGISTERED; goto _exit; } if(KHM_SUCCEEDED(khc_read_int32(csp_mod, L"Disabled", &i)) && i) { _report_mr0(KHERR_INFO, MSG_IM_DISABLED); m->state = KMM_MODULE_STATE_FAIL_DISABLED; goto _exit; } if(KHM_SUCCEEDED(khc_read_int32(csp_mod, L"NoUnload", &i)) && i) { m->flags |= KMM_MODULE_FLAG_NOUNLOAD; } if(KHM_SUCCEEDED(khc_read_int32(csp_mod, L"FailureCount", &i))) { khm_int64 tm; khm_int64 ct; FILETIME fct; khm_int32 last_reason = 0; /* reset the failure count if the failure count reset time period has elapsed */ tm = 0; khc_read_int64(csp_mod, L"FailureTime", &tm); GetSystemTimeAsFileTime(&fct); ct = (FtToInt(&fct) - tm) / 10000000i64; if(tm > 0 && ct > fail_reset_time) { i = 0; khc_write_int32(csp_mod, L"FailureCount", 0); khc_write_int64(csp_mod, L"FailureTime", 0); } khc_read_int32(csp_mod, L"FailureReason", &last_reason); /* did we exceed the max failure count? However, we ignore the max failure count if the reason why it didn't load the last time was because the module wasn't found. */ if(i > max_fail_count && last_reason != KMM_MODULE_STATE_FAIL_NOT_FOUND) { /* failed too many times */ _report_mr0(KHERR_INFO, MSG_IM_MAX_FAIL); m->state = KMM_MODULE_STATE_FAIL_MAX_FAILURE; goto _exit; } } if(khc_read_string(csp_mod, L"ImagePath", NULL, &sz) == KHM_ERROR_TOO_LONG) { if(m->path) PFREE(m->path); m->path = PMALLOC(sz); khc_read_string(csp_mod, L"ImagePath", m->path, &sz); } else { _report_mr0(KHERR_ERROR, MSG_IM_NOT_REGISTERED); m->state = KMM_MODULE_STATE_FAIL_NOT_REGISTERED; goto _exit; } rv = kmmint_read_module_info(m); if (KHM_FAILED(rv)) { if (rv == KHM_ERROR_INCOMPATIBLE) { _report_mr0(KHERR_ERROR, MSG_IM_INCOMPATIBLE); m->state = KMM_MODULE_STATE_FAIL_INCOMPAT; } else if (rv == KHM_ERROR_NOT_FOUND) { _report_mr1(KHERR_ERROR, MSG_IM_NOT_FOUND, _dupstr(m->path)); m->state = KMM_MODULE_STATE_FAIL_NOT_FOUND; } else { _report_mr0(KHERR_ERROR, MSG_IM_INVALID_MODULE); m->state = KMM_MODULE_STATE_FAIL_INV_MODULE; } goto _exit; } /* check again */ if(m->state != KMM_MODULE_STATE_PREINIT) { _report_mr0(KHERR_ERROR, MSG_IM_NOT_PREINIT); goto _exit; } /* from this point on, we must record any failure codes */ record_failure = TRUE; hm = LoadLibrary(m->path); if(!hm) { m->h_module = NULL; m->state = KMM_MODULE_STATE_FAIL_NOT_FOUND; _report_mr1(KHERR_ERROR, MSG_IM_NOT_FOUND, _dupstr(m->path)); goto _exit; } /* from this point on, we need to discard the module through exit_module */ ResetEvent(evt_exit); kmm_active_modules++; release_module = FALSE; exit_module = TRUE; m->flags |= KMM_MODULE_FLAG_LOADED; m->h_module = hm; /* TODO: check signatures */ p_init_module = (init_module_t) GetProcAddress(hm, EXP_INIT_MODULE); if(!p_init_module) { _report_mr1(KHERR_ERROR, MSG_IM_NO_ENTRY, _cstr(EXP_INIT_MODULE)); m->state = KMM_MODULE_STATE_FAIL_INVALID; goto _exit; } m->state = KMM_MODULE_STATE_INIT; /* call init_module() */ rv = (*p_init_module)(kmm_handle_from_module(m)); m->flags |= KMM_MODULE_FLAG_INITP; if(KHM_FAILED(rv)) { _report_mr1(KHERR_ERROR, MSG_IM_INIT_FAIL, _int32(rv)); m->state = KMM_MODULE_STATE_FAIL_LOAD; goto _exit; } if(!m->plugins) { _report_mr0(KHERR_ERROR, MSG_IM_NO_PLUGINS); m->state = KMM_MODULE_STATE_FAIL_NO_PLUGINS; record_failure = FALSE; goto _exit; } m->state = KMM_MODULE_STATE_INITPLUG; do { LPOP(&(m->plugins), &pi); if(pi) { pi->flags &= ~KMM_PLUGIN_FLAG_IN_MODLIST; kmmint_init_plugin(pi); /* release the hold obtained in kmm_provide_plugin() */ kmm_release_plugin(kmm_handle_from_plugin(pi)); } } while(pi); if(!m->plugin_count) { /* We don't want to report this case. This usually means that the plugins that were provided by the module were disabled. */ #ifdef REPORT_EMPTY_MODULES _report_mr0(KHERR_ERROR, MSG_IM_NO_PLUGINS); m->state = KMM_MODULE_STATE_FAIL_NO_PLUGINS; #endif record_failure = FALSE; goto _exit; } m->state = KMM_MODULE_STATE_RUNNING; exit_module = FALSE; record_failure = FALSE; _exit: if(csp_mod) { if(record_failure) { FILETIME fct; i = 0; khc_read_int32(csp_mod, L"FailureCount", &i); i++; khc_write_int32(csp_mod, L"FailureCount", i); if(i==1) { /* first fault */ GetSystemTimeAsFileTime(&fct); khc_write_int64(csp_mod, L"FailureTime", FtToInt(&fct)); } khc_write_int32(csp_mod, L"FailureReason", m->state); } khc_close_space(csp_mod); } if(csp_mods) khc_close_space(csp_mods); _report_mr2(KHERR_INFO, MSG_IM_MOD_STATE, _dupstr(m->name), _int32(m->state)); kmmint_remove_from_module_queue(); /* if something went wrong after init_module was called on the module code, we need to call exit_module */ if(exit_module) kmmint_exit_module(m); if(release_module) kmm_release_module(kmm_handle_from_module(m)); if (kherr_is_error()) { kherr_context * c; kherr_event * err_e = NULL; kherr_event * warn_e = NULL; kherr_event * e; c = kherr_peek_context(); err_e = kherr_get_err_event(c); for(e = kherr_get_first_event(c); e; e = kherr_get_next_event(e)) { if (e != err_e && e->severity == KHERR_WARNING) { warn_e = e; break; } } kherr_evaluate_event(err_e); if (warn_e) kherr_evaluate_event(warn_e); kherr_clear_error(); e = kherr_report(KHERR_ERROR, (wchar_t *) MSG_IMERR_TITLE, KHERR_FACILITY, NULL, err_e->long_desc, ((warn_e)? (wchar_t *)MSG_IMERR_SUGGEST: NULL), KHERR_FACILITY_ID, KHERR_SUGGEST_NONE, _cstr(m->name), ((warn_e)? _cstr(warn_e->long_desc):_vnull()), _vnull(),_vnull(), KHERR_RF_MSG_SHORT_DESC | ((warn_e)? KHERR_RF_MSG_SUGGEST: 0), KHERR_HMODULE); kherr_evaluate_event(e); kherr_release_context(c); } _end_task(); }
static void write_params_ident(ident_data * d) { khm_handle csp_ident; if (d->saved.monitor == d->work.monitor && d->saved.auto_renew == d->work.auto_renew && d->saved.sticky == d->work.sticky && !d->removed) return; if (KHM_FAILED(kcdb_identity_get_config(d->ident, KHM_PERM_WRITE, &csp_ident))) { #ifdef DEBUG assert(FALSE); #endif return; } if (d->removed) { khm_handle h = NULL; khm_int32 flags = 0; khc_remove_space(csp_ident); /* calling kcdb_identity_get_config() will update the KCDB_IDENT_FLAG_CONFIG flag for the identity to reflect the fact that it nolonger has a configuration. */ kcdb_identity_get_config(d->ident, 0, &h); if (h) { /* what the ? */ #ifdef DEBUG assert(FALSE); #endif khc_close_space(h); } #ifdef DEBUG kcdb_identity_get_flags(d->ident, &flags); assert(!(flags & KCDB_IDENT_FLAG_CONFIG)); #endif } else { if (d->saved.monitor != d->work.monitor) khc_write_int32(csp_ident, L"Monitor", !!d->work.monitor); if (d->saved.auto_renew != d->work.auto_renew) khc_write_int32(csp_ident, L"AllowAutoRenew", !!d->work.auto_renew); if (d->saved.sticky != d->work.sticky) { kcdb_identity_set_flags(d->ident, (d->work.sticky)?KCDB_IDENT_FLAG_STICKY:0, KCDB_IDENT_FLAG_STICKY); } } khc_close_space(csp_ident); d->saved = d->work; d->applied = TRUE; if (d->hwnd) PostMessage(d->hwnd, KHUI_WM_CFG_NOTIFY, MAKEWPARAM(0, WMCFG_UPDATE_STATE), 0); khm_refresh_config(); }
static kcdb_identpro_i * identpro_create_with_plugin(kmm_plugin plugin, khm_handle sub) { kmm_plugin_info pi; kcdb_identpro_i * p; size_t len; ZeroMemory(&pi, sizeof(pi)); if (KHM_FAILED(kmm_get_plugin_info_i(plugin, &pi))) return NULL; if (pi.reg.type != KHM_PITYPE_IDENT) { kmm_release_plugin_info_i(&pi); #ifdef DEBUG assert(FALSE); #endif return NULL; } if (FAILED(StringCbLength(pi.reg.name, KMM_MAXCB_NAME, &len))) return NULL; len += sizeof(wchar_t); /* we need to check if the plug-in is already there, both in the current and the deleted lists */ EnterCriticalSection(&cs_identpro); for (p = QTOP(&id_providers); p; p = QNEXT(p)) { if (p->plugin == plugin) break; } if (p == NULL) for (p = deleted_id_providers; p; p = LNEXT(p)) { if (p->plugin == plugin || !wcscmp(p->name, pi.reg.name)) break; } if (p) identpro_hold(p); if (p == NULL) { p = PMALLOC(sizeof(*p)); ZeroMemory(p, sizeof(*p)); p->magic = KCDB_IDENTPRO_MAGIC; p->name = PMALLOC(len); StringCbCopy(p->name, len, pi.reg.name); p->sub = sub; p->plugin = plugin; kmm_hold_plugin(plugin); p->refcount = 1; /* initially held */ QPUT(&id_providers, p); n_id_providers++; kcdbint_identpro_post_message(KCDB_OP_INSERT, p); } else if (p->flags & KCDB_IDENTPRO_FLAG_DELETED) { LDELETE(&deleted_id_providers, p); p->flags &= ~KCDB_IDENTPRO_FLAG_DELETED; if (p->plugin != plugin) { /* can happen if the plug-in was reloaded */ if (p->plugin) kmm_release_plugin_info_i(p->plugin); p->plugin = plugin; kmm_hold_plugin(plugin); } if (p->sub) { kmq_delete_subscription(p->sub); } p->sub = sub; QPUT(&id_providers, p); n_id_providers++; } identpro_check_and_set_default_provider(); LeaveCriticalSection(&cs_identpro); kmm_release_plugin_info_i(&pi); return p; }
static krb5_error_code KRB5_CALLCONV kinit_prompter(krb5_context context, void *data, const char *name, const char *banner, int num_prompts, krb5_prompt prompts[]) { int i; k5_kinit_task * kt; khm_size ncp; krb5_error_code code = 0; BOOL new_prompts = TRUE; khm_handle csp_prcache = NULL; kt = (k5_kinit_task *) data; assert(kt && kt->magic == K5_KINIT_TASK_MAGIC); EnterCriticalSection(&kt->cs); if (kt->state == K5_KINIT_STATE_ABORTED) { LeaveCriticalSection(&kt->cs); return KRB5_LIBOS_PWDINTR; } #ifdef DEBUG assert(kt->state == K5_KINIT_STATE_INCALL || kt->state == K5_KINIT_STATE_CONFIRM); _reportf(L"k5_kinit_prompter() received %d prompts with name=[%S] banner=[%S]", num_prompts, name, banner); for (i=0; i < num_prompts; i++) { _reportf(L"Prompt[%d]: string[%S]", i, prompts[i].prompt); } #endif /* we got prompts? Then we assume that the principal is valid */ if (!kt->is_valid_principal) { kt->is_valid_principal = TRUE; /* if the flags that were used to call kinit were restricted because we didn't know the validity of the principal, then we need to go back and retry the call with the correct flags. */ if (kt->params.forwardable || kt->params.proxiable || kt->params.renewable) { _reportf(L"Retrying kinit call due to restricted flags on first call."); kt->state = K5_KINIT_STATE_RETRY; LeaveCriticalSection(&kt->cs); return KRB5_LIBOS_PWDINTR; } } /* check if we are already showing the right prompts */ khui_cw_get_prompt_count(kt->nc, &ncp); if (num_prompts != (int) ncp && num_prompts != 0) goto _show_new_prompts; for (i=0; i < num_prompts; i++) { wchar_t wprompt[KHUI_MAXCCH_PROMPT]; khui_new_creds_prompt * p; if(prompts[i].prompt) { AnsiStrToUnicode(wprompt, sizeof(wprompt), prompts[i].prompt); } else { wprompt[0] = L'\0'; } if (KHM_FAILED(khui_cw_get_prompt(kt->nc, i, &p))) break; if ( /* if we received a prompt string, then it should be the same as the one that is displayed */ (wprompt[0] != L'\0' && (p->prompt == NULL || wcscmp(wprompt, p->prompt))) || /* if we didn't receive one, then there shouldn't be one displayed. This case really shouldn't happen in reality, but we check anyway. */ (wprompt[0] == L'\0' && p->prompt != NULL) || /* the type should match */ (prompts[i].type != p->type) || /* if this prompt should be hidden, then it must also be so */ (prompts[i].hidden && !(p->flags & KHUI_NCPROMPT_FLAG_HIDDEN)) || (!prompts[i].hidden && (p->flags & KHUI_NCPROMPT_FLAG_HIDDEN)) ) break; } if (i >= num_prompts) { new_prompts = FALSE; /* ok. looks like we are already showing the same set of prompts that we were supposed to show. Sync up the values and go ahead. */ goto _process_prompts; } _show_new_prompts: if (num_prompts == 0) { assert(FALSE); khui_cw_notify_identity_state(kt->nc, kt->nct->hwnd_panel, NULL, KHUI_CWNIS_READY | KHUI_CWNIS_NOPROGRESS | KHUI_CWNIS_VALIDATED, 0); code = 0; kt->is_null_password = TRUE; goto _process_prompts; } /* in addition to showing new prompts, we also cache the first set of prompts. */ if (kt->prompt_set_index == 0) { khm_handle csp_idconfig = NULL; khm_handle csp_idk5 = NULL; kcdb_identity_get_config(kt->identity, KHM_FLAG_CREATE, &csp_idconfig); if (csp_idconfig != NULL) khc_open_space(csp_idconfig, CSNAME_KRB5CRED, KHM_FLAG_CREATE, &csp_idk5); if (csp_idk5 != NULL) khc_open_space(csp_idk5, CSNAME_PROMPTCACHE, KHM_FLAG_CREATE, &csp_prcache); khc_close_space(csp_idconfig); khc_close_space(csp_idk5); } { wchar_t wbanner[KHUI_MAXCCH_BANNER]; wchar_t wname[KHUI_MAXCCH_PNAME]; if(banner) AnsiStrToUnicode(wbanner, sizeof(wbanner), banner); else wbanner[0] = L'\0'; if(name) AnsiStrToUnicode(wname, sizeof(wname), name); else LoadString(hResModule, IDS_PNAME_PW, wname, ARRAYLENGTH(wname)); khui_cw_clear_prompts(kt->nc); khui_cw_begin_custom_prompts(kt->nc, num_prompts, wbanner, wname); if (csp_prcache) { FILETIME current; FILETIME lifetime; FILETIME expiry; khm_int64 iexpiry; khm_int32 t = 0; khc_write_string(csp_prcache, L"Banner", wbanner); khc_write_string(csp_prcache, L"Name", (name)? wname: L""); khc_write_int32(csp_prcache, L"PromptCount", (khm_int32) num_prompts); GetSystemTimeAsFileTime(¤t); #ifdef USE_PROMPT_CACHE_LIFETIME khc_read_int32(csp_params, L"PromptCacheLifetime", &t); if (t == 0) t = 172800; /* 48 hours */ #else khc_read_int32(csp_params, L"MaxRenewLifetime", &t); if (t == 0) t = 2592000; /* 30 days */ t += 604800; /* + 7 days */ #endif TimetToFileTimeInterval(t, &lifetime); expiry = FtAdd(¤t, &lifetime); iexpiry = FtToInt(&expiry); khc_write_int64(csp_prcache, L"ExpiresOn", iexpiry); } } for(i=0; i < num_prompts; i++) { wchar_t wprompt[KHUI_MAXCCH_PROMPT]; if(prompts[i].prompt) { AnsiStrToUnicode(wprompt, sizeof(wprompt), prompts[i].prompt); } else { wprompt[0] = 0; } khui_cw_add_prompt(kt->nc, prompts[i].type, wprompt, NULL, (prompts[i].hidden?KHUI_NCPROMPT_FLAG_HIDDEN:0)); if (csp_prcache) { khm_handle csp_p = NULL; wchar_t wnum[8]; /* should be enough for 10 million prompts */ wnum[0] = 0; StringCbPrintf(wnum, sizeof(wnum), L"%d", i); khc_open_space(csp_prcache, wnum, KHM_FLAG_CREATE, &csp_p); if (csp_p) { khc_write_string(csp_p, L"Prompt", wprompt); khc_write_int32(csp_p, L"Type", prompts[i].type); khc_write_int32(csp_p, L"Flags", (prompts[i].hidden? KHUI_NCPROMPT_FLAG_HIDDEN:0)); khc_close_space(csp_p); } } } if (csp_prcache) { khc_close_space(csp_prcache); csp_prcache = NULL; } _process_prompts: if (new_prompts) { kt->state = K5_KINIT_STATE_WAIT; kcdb_identity_set_flags(kt->identity, KCDB_IDENT_FLAG_VALID | KCDB_IDENT_FLAG_KEY_EXPORT, KCDB_IDENT_FLAG_VALID | KCDB_IDENT_FLAG_KEY_EXPORT); khui_cw_notify_identity_state(kt->nc, kt->nct->hwnd_panel, L"", KHUI_CWNIS_VALIDATED | KHUI_CWNIS_READY, 0); SetEvent(kt->h_parent_wait); LeaveCriticalSection(&kt->cs); WaitForSingleObject(kt->h_task_wait, INFINITE); EnterCriticalSection(&kt->cs); } /* we get here after the user selects an action that either cancels the credentials acquisition operation or triggers the actual acquisition of credentials. */ if (kt->state != K5_KINIT_STATE_INCALL && kt->state != K5_KINIT_STATE_CONFIRM) { code = KRB5_LIBOS_PWDINTR; goto _exit; } kt->is_null_password = FALSE; /* otherwise, we need to get the data back from the UI and return 0 */ khui_cw_sync_prompt_values(kt->nc); for(i=0; i<num_prompts; i++) { krb5_data * d; wchar_t wbuf[512]; khm_size cbbuf; size_t cch; d = prompts[i].reply; cbbuf = sizeof(wbuf); if(KHM_SUCCEEDED(khui_cw_get_prompt_value(kt->nc, i, wbuf, &cbbuf))) { UnicodeStrToAnsi(d->data, d->length, wbuf); if(SUCCEEDED(StringCchLengthA(d->data, d->length, &cch))) d->length = (unsigned int) cch; else d->length = 0; } else { assert(FALSE); d->length = 0; } if (prompts[i].type == KRB5_PROMPT_TYPE_PASSWORD && d->length == 0) kt->is_null_password = TRUE; } if (khui_cw_get_persist_private_data(kt->nc) && num_prompts == 1 && prompts[0].type == KRB5_PROMPT_TYPE_PASSWORD && prompts[0].reply->length != 0) { k5_reply_to_acqpriv_id_request(kt->nc, prompts[0].reply); } _exit: kt->prompt_set_index++; LeaveCriticalSection(&kt->cs); /* entering a NULL password is equivalent to cancelling out */ if (kt->is_null_password) return KRB5_LIBOS_PWDINTR; else return code; }
static ident_data * find_ident_by_node(khui_config_node node) { khm_size cb; wchar_t idname[KCDB_IDENT_MAXCCH_NAME]; int i; khm_handle ident = NULL; cb = sizeof(idname); khui_cfg_get_name(node, idname, &cb); for (i=0; i < (int)cfg_idents.n_idents; i++) { if (!wcscmp(cfg_idents.idents[i].idname, idname)) break; } if (i < (int)cfg_idents.n_idents) return &cfg_idents.idents[i]; /* there is no identity data for this configuration node. We try to create it. */ if (KHM_FAILED(kcdb_identity_create(idname, 0, &ident))) return NULL; if (cfg_idents.n_idents >= cfg_idents.nc_idents) { cfg_idents.nc_idents = UBOUNDSS(cfg_idents.n_idents + 1, IDENTS_DATA_ALLOC_INCR, IDENTS_DATA_ALLOC_INCR); #ifdef DEBUG assert(cfg_idents.nc_idents > cfg_idents.n_idents); #endif cfg_idents.idents = PREALLOC(cfg_idents.idents, sizeof(*cfg_idents.idents) * cfg_idents.nc_idents); #ifdef DEBUG assert(cfg_idents.idents); #endif ZeroMemory(&(cfg_idents.idents[cfg_idents.n_idents]), sizeof(*cfg_idents.idents) * (cfg_idents.nc_idents - cfg_idents.n_idents)); } i = (int) cfg_idents.n_idents; StringCbLength(idname, KCDB_IDENT_MAXCB_NAME, &cb); cb += sizeof(wchar_t); cfg_idents.idents[i].idname = PMALLOC(cb); #ifdef DEBUG assert(cfg_idents.idents[i].idname); #endif StringCbCopy(cfg_idents.idents[i].idname, cb, idname); cfg_idents.idents[i].ident = ident; cfg_idents.idents[i].removed = FALSE; kcdb_identity_get_flags(ident, &cfg_idents.idents[i].flags); #ifdef DEBUG assert(cfg_idents.idents[i].flags & KCDB_IDENT_FLAG_CONFIG); #endif read_params_ident(&cfg_idents.idents[i]); cfg_idents.n_idents++; /* leave ident held. */ return &cfg_idents.idents[i]; }
/* Completion handler for KMSG_CRED messages. We control the overall logic of credentials acquisition and other operations here. Once a credentials operation is triggered, each successive message completion notification will be used to dispatch the messages for the next step in processing the operation. */ void KHMAPI kmsg_cred_completion(kmq_message *m) { khui_new_creds * nc; #ifdef DEBUG assert(m->type == KMSG_CRED); #else if(m->type != KMSG_CRED) return; /* huh? */ #endif switch(m->subtype) { case KMSG_CRED_PASSWORD: /* fallthrough */ case KMSG_CRED_NEW_CREDS: /* Cred types have attached themselves. Trigger the next phase. */ kmq_post_message(KMSG_CRED, KMSG_CRED_DIALOG_SETUP, 0, m->vparam); break; case KMSG_CRED_RENEW_CREDS: nc = (khui_new_creds *) m->vparam; /* khm_cred_dispatch_process_message() deals with the case where there are no credential types that wants to participate in this operation. */ khm_cred_dispatch_process_message(nc); break; case KMSG_CRED_DIALOG_SETUP: nc = (khui_new_creds *) m->vparam; khm_prep_newcredwnd(nc->hwnd); /* all the controls have been created. Now initialize them */ if (nc->n_types > 0) { kmq_post_subs_msg(nc->type_subs, nc->n_types, KMSG_CRED, KMSG_CRED_DIALOG_PRESTART, 0, m->vparam); } else { PostMessage(nc->hwnd, KHUI_WM_NC_NOTIFY, MAKEWPARAM(0, WMNC_DIALOG_PROCESS_COMPLETE), 0); } break; case KMSG_CRED_DIALOG_PRESTART: /* all prestart stuff is done. Now to activate the dialog */ nc = (khui_new_creds *) m->vparam; khm_show_newcredwnd(nc->hwnd); kmq_post_subs_msg(nc->type_subs, nc->n_types, KMSG_CRED, KMSG_CRED_DIALOG_START, 0, m->vparam); /* at this point, the dialog window takes over. We let it run the show until KMSG_CRED_DIALOG_END is posted by the dialog procedure. */ break; case KMSG_CRED_PROCESS: /* a wave of these messages have completed. We should check if there's more */ nc = (khui_new_creds *) m->vparam; /* if we are done processing all the plug-ins, then check if there were any errors reported. Otherwise we dispatch another set of messages. */ if(!khm_cred_dispatch_process_level(nc)) { if(kherr_is_error()) { khui_alert * alert; kherr_event * evt; kherr_context * ctx; wchar_t ws_tfmt[512]; wchar_t w_idname[KCDB_IDENT_MAXCCH_NAME]; wchar_t ws_title[ARRAYLENGTH(ws_tfmt) + KCDB_IDENT_MAXCCH_NAME]; khm_size cb; /* For renewals, we suppress the error message for the following case: - The renewal was for an identity - There are no identity credentials for the identity (no credentials that have the same type as the identity provider). */ if (nc->subtype == KMSG_CRED_RENEW_CREDS && nc->ctx.scope == KHUI_SCOPE_IDENT && nc->ctx.identity != NULL) { khm_handle tcs = NULL; /* credential set */ khm_size count = 0; khm_int32 id_ctype = KCDB_CREDTYPE_INVALID; khm_int32 delta = 0; kcdb_identity_get_type(&id_ctype); kcdb_credset_create(&tcs); kcdb_credset_collect(tcs, NULL, nc->ctx.identity, id_ctype, &delta); kcdb_credset_get_size(tcs, &count); kcdb_credset_delete(tcs); if (count == 0) { goto done_with_op; } } ctx = kherr_peek_context(); evt = kherr_get_err_event(ctx); kherr_evaluate_event(evt); khui_alert_create_empty(&alert); if (nc->subtype == KMSG_CRED_NEW_CREDS) { khui_alert_set_type(alert, KHUI_ALERTTYPE_ACQUIREFAIL); cb = sizeof(w_idname); if (nc->n_identities == 0 || KHM_FAILED(kcdb_identity_get_name(nc->identities[0], w_idname, &cb))) { /* an identity could not be determined */ LoadString(khm_hInstance, IDS_NC_FAILED_TITLE, ws_title, ARRAYLENGTH(ws_title)); } else { LoadString(khm_hInstance, IDS_NC_FAILED_TITLE_I, ws_tfmt, ARRAYLENGTH(ws_tfmt)); StringCbPrintf(ws_title, sizeof(ws_title), ws_tfmt, w_idname); khui_alert_set_ctx(alert, KHUI_SCOPE_IDENT, nc->identities[0], KCDB_CREDTYPE_INVALID, NULL); } } else if (nc->subtype == KMSG_CRED_PASSWORD) { khui_alert_set_type(alert, KHUI_ALERTTYPE_CHPW); cb = sizeof(w_idname); if (nc->n_identities == 0 || KHM_FAILED(kcdb_identity_get_name(nc->identities[0], w_idname, &cb))) { LoadString(khm_hInstance, IDS_NC_PWD_FAILED_TITLE, ws_title, ARRAYLENGTH(ws_title)); } else { LoadString(khm_hInstance, IDS_NC_PWD_FAILED_TITLE_I, ws_tfmt, ARRAYLENGTH(ws_tfmt)); StringCbPrintf(ws_title, sizeof(ws_title), ws_tfmt, w_idname); khui_alert_set_ctx(alert, KHUI_SCOPE_IDENT, nc->identities[0], KCDB_CREDTYPE_INVALID, NULL); } } else if (nc->subtype == KMSG_CRED_RENEW_CREDS) { khui_alert_set_type(alert, KHUI_ALERTTYPE_RENEWFAIL); cb = sizeof(w_idname); if (nc->ctx.identity == NULL || KHM_FAILED(kcdb_identity_get_name(nc->ctx.identity, w_idname, &cb))) { LoadString(khm_hInstance, IDS_NC_REN_FAILED_TITLE, ws_title, ARRAYLENGTH(ws_title)); } else { LoadString(khm_hInstance, IDS_NC_REN_FAILED_TITLE_I, ws_tfmt, ARRAYLENGTH(ws_tfmt)); StringCbPrintf(ws_title, sizeof(ws_title), ws_tfmt, w_idname); khui_alert_set_ctx(alert, KHUI_SCOPE_IDENT, nc->ctx.identity, KCDB_CREDTYPE_INVALID, NULL); } } else { #ifdef DEBUG assert(FALSE); #endif } khui_alert_set_title(alert, ws_title); khui_alert_set_severity(alert, evt->severity); if(!evt->long_desc) khui_alert_set_message(alert, evt->short_desc); else khui_alert_set_message(alert, evt->long_desc); if(evt->suggestion) khui_alert_set_suggestion(alert, evt->suggestion); if (nc->subtype == KMSG_CRED_RENEW_CREDS && nc->ctx.identity != NULL) { khm_int32 n_cmd; n_cmd = khm_get_identity_new_creds_action(nc->ctx.identity); if (n_cmd != 0) { khui_alert_add_command(alert, n_cmd); khui_alert_add_command(alert, KHUI_PACTION_CLOSE); khui_alert_set_flags(alert, KHUI_ALERT_FLAG_DISPATCH_CMD, KHUI_ALERT_FLAG_DISPATCH_CMD); } } khui_alert_show(alert); khui_alert_release(alert); kherr_release_context(ctx); kherr_clear_error(); } done_with_op: if (nc->subtype == KMSG_CRED_RENEW_CREDS) { kmq_post_message(KMSG_CRED, KMSG_CRED_END, 0, m->vparam); } else { PostMessage(nc->hwnd, KHUI_WM_NC_NOTIFY, MAKEWPARAM(0, WMNC_DIALOG_PROCESS_COMPLETE), 0); } } break; case KMSG_CRED_END: /* all is done. */ { khui_new_creds * nc; khm_boolean continue_cmdline = TRUE; nc = (khui_new_creds *) m->vparam; if (nc->subtype == KMSG_CRED_NEW_CREDS || nc->subtype == KMSG_CRED_PASSWORD) { khm_cred_end_dialog(nc); } else if (nc->subtype == KMSG_CRED_RENEW_CREDS) { /* if this is a renewal that was triggered while we were processing the commandline, then we need to update the pending renewal count. */ if (khm_startup.processing) { LONG renewals; renewals = InterlockedDecrement(&khm_startup.pending_renewals); if (renewals != 0) { continue_cmdline = FALSE; } } } khui_cw_destroy_cred_blob(nc); kmq_post_message(KMSG_CRED, KMSG_CRED_REFRESH, 0, 0); if (continue_cmdline) kmq_post_message(KMSG_ACT, KMSG_ACT_CONTINUE_CMDLINE, 0, 0); } break; /* property sheet stuff */ case KMSG_CRED_PP_BEGIN: /* all the pages should have been added by now. Just send out the precreate message */ kmq_post_message(KMSG_CRED, KMSG_CRED_PP_PRECREATE, 0, m->vparam); break; case KMSG_CRED_PP_END: kmq_post_message(KMSG_CRED, KMSG_CRED_PP_DESTROY, 0, m->vparam); break; case KMSG_CRED_DESTROY_CREDS: #ifdef DEBUG assert(m->vparam != NULL); #endif khui_context_release((khui_action_context *) m->vparam); PFREE(m->vparam); kmq_post_message(KMSG_CRED, KMSG_CRED_REFRESH, 0, 0); kmq_post_message(KMSG_ACT, KMSG_ACT_CONTINUE_CMDLINE, 0, 0); break; case KMSG_CRED_IMPORT: { khm_boolean continue_cmdline = FALSE; LONG pending_renewals; /* once an import operation ends, we have to trigger a renewal so that other plug-ins that didn't participate in the import operation can have a chance at getting the necessary credentials. If we are in the middle of processing the commandline, we have to be a little bit careful. We can't issue a commandline conituation message right now because the import action is still ongoing (since the renewals are part of the action). Once the renewals have completed, the completion handler will automatically issue a commandline continuation message. However, if there were no identities to renew, then we have to issue the message ourselves. */ InterlockedIncrement(&khm_startup.pending_renewals); khm_cred_renew_all_identities(); pending_renewals = InterlockedDecrement(&khm_startup.pending_renewals); if (pending_renewals == 0 && khm_startup.processing) kmq_post_message(KMSG_ACT, KMSG_ACT_CONTINUE_CMDLINE, 0, 0); } break; case KMSG_CRED_REFRESH: kcdb_identity_refresh_all(); break; } }
KHMEXP khm_int32 KHMAPI kcdb_credset_extract_filtered(khm_handle destcredset, khm_handle sourcecredset, kcdb_cred_filter_func filter, void * rock) { khm_int32 code = KHM_ERROR_SUCCESS; kcdb_credset * dest; kcdb_credset * src; int isRoot = 0; khm_size srcSize = 0; int i; if(!kcdb_credset_is_credset(destcredset)) return KHM_ERROR_INVALID_PARAM; if(sourcecredset) { if(!kcdb_credset_is_credset(sourcecredset)) return KHM_ERROR_INVALID_PARAM; } else { sourcecredset = kcdb_root_credset; isRoot = 1; } src = (kcdb_credset *) sourcecredset; dest = (kcdb_credset *) destcredset; if (kcdb_credset_is_sealed(dest)) return KHM_ERROR_INVALID_OPERATION; EnterCriticalSection(&(src->cs)); EnterCriticalSection(&(dest->cs)); #ifdef DEBUG assert(!(dest->flags & KCDB_CREDSET_FLAG_ENUM)); #endif if(KHM_FAILED(kcdb_credset_get_size(sourcecredset, &srcSize))) { code = KHM_ERROR_UNKNOWN; goto _exit; } kcdb_cred_lock_read(); dest->flags |= KCDB_CREDSET_FLAG_ENUM; for(i=0; i < (int) srcSize; i++) { kcdb_cred * c; c = src->clist[i].cred; if(kcdb_cred_is_active_cred((khm_handle) c) && filter(c, 0, rock)) { if(isRoot) { khm_handle newcred; kcdb_cred_unlock_read(); kcdb_cred_dup((khm_handle) c, &newcred); kcdb_credset_add_cred(destcredset, newcred, -1); kcdb_cred_release(newcred); kcdb_cred_lock_read(); } else { kcdb_cred_unlock_read(); kcdb_credset_add_cred(destcredset, (khm_handle) c, -1); kcdb_cred_lock_read(); } } } dest->flags &= ~KCDB_CREDSET_FLAG_ENUM; kcdb_cred_unlock_read(); _exit: LeaveCriticalSection(&(dest->cs)); LeaveCriticalSection(&(src->cs)); return code; }
int khm_krb5_initialize(khm_handle ident, krb5_context *ctx, krb5_ccache *cache) { #ifdef NO_KRB5 return(0); #else LPCSTR functionName = NULL; int freeContextFlag = 0; krb5_error_code rc = 0; krb5_flags flags = 0; if (pkrb5_init_context == NULL) return 1; if (*ctx == 0 && (rc = (*pkrb5_init_context)(ctx))) { functionName = "krb5_init_context()"; freeContextFlag = 0; goto on_error; } if(*cache == 0) { wchar_t wccname[MAX_PATH]; khm_size cbwccname; if(ident != NULL) { cbwccname = sizeof(wccname); do { char ccname[256]; if(KHM_FAILED(kcdb_identity_get_attrib(ident, L"Krb5CCName", NULL, wccname, &cbwccname))) { cbwccname = sizeof(wccname); if (KHM_FAILED (khm_krb5_find_ccache_for_identity(ident, ctx, wccname, &cbwccname))) { #ifdef DEBUG_LIKE_A_MADMAN assert(FALSE); #endif break; } } if(UnicodeStrToAnsi(ccname, sizeof(ccname), wccname) == 0) break; if((*pkrb5_cc_resolve)(*ctx, ccname, cache)) { functionName = "krb5_cc_resolve()"; freeContextFlag = 1; goto on_error; } } while(FALSE); } #ifndef FAILOVER_TO_DEFAULT_CCACHE rc = 1; #endif if (*cache == 0 #ifdef FAILOVER_TO_DEFAULT_CCACHE && (rc = (*pkrb5_cc_default)(*ctx, cache)) #endif ) { functionName = "krb5_cc_default()"; freeContextFlag = 1; goto on_error; } } #ifdef KRB5_TC_NOTICKET flags = KRB5_TC_NOTICKET; #endif if ((rc = (*pkrb5_cc_set_flags)(*ctx, *cache, flags))) { if (rc != KRB5_FCC_NOFILE && rc != KRB5_CC_NOTFOUND) khm_krb5_error(rc, "krb5_cc_set_flags()", 0, ctx, cache); else if ((rc == KRB5_FCC_NOFILE || rc == KRB5_CC_NOTFOUND) && *ctx != NULL) { if (*cache != NULL) { (*pkrb5_cc_close)(*ctx, *cache); *cache = NULL; } } return rc; } return 0; on_error: return khm_krb5_error(rc, functionName, freeContextFlag, ctx, cache); #endif //!NO_KRB5 }
void khm_cred_addr_change(void) { khm_handle csp_cw = NULL; khm_int32 check_net = 0; wchar_t * ids = NULL; wchar_t * t; khm_size cb; khm_size n_idents; FILETIME ft_now; FILETIME ft_exp; FILETIME ft_issue; if (KHM_SUCCEEDED(khc_open_space(NULL, L"CredWindow", 0, &csp_cw))) { khc_read_int32(csp_cw, L"AutoDetectNet", &check_net); khc_close_space(csp_cw); } if (!check_net) return; while(TRUE) { if (ids) PFREE(ids); ids = NULL; if (kcdb_identity_enum(KCDB_IDENT_FLAG_VALID | KCDB_IDENT_FLAG_RENEWABLE, KCDB_IDENT_FLAG_VALID | KCDB_IDENT_FLAG_RENEWABLE, NULL, &cb, &n_idents) != KHM_ERROR_TOO_LONG) break; ids = PMALLOC(cb); if (KHM_SUCCEEDED (kcdb_identity_enum(KCDB_IDENT_FLAG_VALID | KCDB_IDENT_FLAG_RENEWABLE, KCDB_IDENT_FLAG_VALID | KCDB_IDENT_FLAG_RENEWABLE, ids, &cb, &n_idents))) break; } if (!ids) return; GetSystemTimeAsFileTime(&ft_now); for (t=ids; t && *t; t = multi_string_next(t)) { khm_handle ident; if (KHM_FAILED (kcdb_identity_create(t, 0, &ident))) continue; cb = sizeof(ft_issue); if (KHM_SUCCEEDED (kcdb_identity_get_attr(ident, KCDB_ATTR_ISSUE, NULL, &ft_issue, &cb)) && (cb = sizeof(ft_exp)) && KHM_SUCCEEDED (kcdb_identity_get_attr(ident, KCDB_ATTR_EXPIRE, NULL, &ft_exp, &cb)) && CompareFileTime(&ft_now, &ft_exp) < 0) { khm_int64 i_issue; khm_int64 i_exp; khm_int64 i_now; i_issue = FtToInt(&ft_issue); i_exp = FtToInt(&ft_exp); i_now = FtToInt(&ft_now); if (i_now > (i_issue + i_exp) / 2) { khm_cred_renew_identity(ident); } } kcdb_identity_release(ident); } }
/* Handler for system messages. The only two we handle are KMSG_SYSTEM_INIT and KMSG_SYSTEM_EXIT. */ khm_int32 KHMAPI handle_kmsg_system(khm_int32 msg_type, khm_int32 msg_subtype, khm_ui_4 uparam, void * vparam) { khm_int32 rv = KHM_ERROR_SUCCESS; switch (msg_subtype) { /* This is the first message that will be received by a plugin. We use it to perform initialization operations such as registering any credential types, data types and attributes. */ case KMSG_SYSTEM_INIT: { kcdb_credtype ct; wchar_t short_desc[KCDB_MAXCCH_SHORT_DESC]; wchar_t long_desc[KCDB_MAXCCH_LONG_DESC]; khui_config_node cnode; khui_config_node_reg creg; /* First and foremost, we need to register a credential type. */ ZeroMemory(&ct, sizeof(ct)); ct.id = KCDB_CREDTYPE_AUTO; ct.name = MYCREDTYPE_NAMEW; short_desc[0] = L'\0'; LoadString(hResModule, IDS_CT_SHORT_DESC, short_desc, ARRAYLENGTH(short_desc)); long_desc[0] = L'\0'; LoadString(hResModule, IDS_CT_LONG_DESC, long_desc, ARRAYLENGTH(long_desc)); ct.icon = NULL; /* We skip the icon for now, but you can assign a handle to an icon here. The icon will be used to represent the credentials type.*/ kmq_create_subscription(plugin_msg_proc, &ct.sub); ct.is_equal = cred_is_equal; rv = kcdb_credtype_register(&ct, &credtype_id); /* We create a global credential set that we use in the plug-in thread. This alleviates the need to create one everytime we need one. Keep in mind that this should only be used in the plug-in thread and should not be touched from the UI thread or any other thread. */ kcdb_credset_create(&g_credset); /* TODO: Perform additional initialization operations. */ /* TODO: Also list out the credentials of this type that already exist. */ /* Now we register our configuration panels. */ /* This configuration panel is the one that controls general options. We leave the identity specific and identity defaults for other configuration panels. */ ZeroMemory(&creg, sizeof(creg)); short_desc[0] = L'\0'; LoadString(hResModule, IDS_CFG_SHORT_DESC, short_desc, ARRAYLENGTH(short_desc)); long_desc[0] = L'\0'; LoadString(hResModule, IDS_CFG_LONG_DESC, long_desc, ARRAYLENGTH(long_desc)); creg.name = CONFIGNODE_MAIN; creg.short_desc = short_desc; creg.long_desc = long_desc; creg.h_module = hResModule; creg.dlg_template = MAKEINTRESOURCE(IDD_CONFIG); creg.dlg_proc = config_dlgproc; creg.flags = 0; khui_cfg_register(NULL, &creg); /* Now we do the identity specific and identity default configuration panels. "KhmIdentities" is a predefined configuration node under which all the identity spcific configuration is managed. */ if (KHM_FAILED(khui_cfg_open(NULL, L"KhmIdentities", &cnode))) { /* this should always work */ assert(FALSE); rv = KHM_ERROR_NOT_FOUND; break; } /* First the tab panel for defaults for all identities */ ZeroMemory(&creg, sizeof(creg)); short_desc[0] = L'\0'; LoadString(hResModule, IDS_CFG_IDS_SHORT_DESC, short_desc, ARRAYLENGTH(short_desc)); long_desc[0] = L'\0'; LoadString(hResModule, IDS_CFG_IDS_LONG_DESC, long_desc, ARRAYLENGTH(long_desc)); creg.name = CONFIGNODE_ALL_ID; creg.short_desc = short_desc; creg.long_desc = long_desc; creg.h_module = hResModule; creg.dlg_template = MAKEINTRESOURCE(IDD_CONFIG_IDS); creg.dlg_proc = config_ids_dlgproc; creg.flags = KHUI_CNFLAG_SUBPANEL; khui_cfg_register(cnode, &creg); /* Now the panel for per identity configuration */ ZeroMemory(&creg, sizeof(creg)); short_desc[0] = L'\0'; LoadString(hResModule, IDS_CFG_ID_SHORT_DESC, short_desc, ARRAYLENGTH(short_desc)); long_desc[0] = L'\0'; LoadString(hResModule, IDS_CFG_ID_LONG_DESC, long_desc, ARRAYLENGTH(long_desc)); creg.name = CONFIGNODE_PER_ID; creg.short_desc = short_desc; creg.long_desc = long_desc; creg.h_module = hResModule; creg.dlg_template = MAKEINTRESOURCE(IDD_CONFIG_ID); creg.dlg_proc = config_id_dlgproc; creg.flags = KHUI_CNFLAG_SUBPANEL | KHUI_CNFLAG_INSTANCE; khui_cfg_register(cnode, &creg); khui_cfg_release(cnode); /* get IdentProvider handle to which this plugin belongs it is possible to use kcdb_identity_create_ex() function with proper h_idprov */ if (KHM_FAILED(kcdb_identpro_find(IDPROV_NAMEW, &h_idprov))) { return KHM_ERROR_UNKNOWN; } } break; /* This is the last message that will be received by the plugin. */ case KMSG_SYSTEM_EXIT: { khui_config_node cnode; khui_config_node cn_idents; /* It should not be assumed that initialization of the plugin went well at this point since we receive a KMSG_SYSTEM_EXIT even if the initialization failed. */ if (credtype_id != KCDB_CREDTYPE_INVALID) { kcdb_credtype_unregister(credtype_id); credtype_id = KCDB_CREDTYPE_INVALID; } if (g_credset) { kcdb_credset_delete(g_credset); g_credset = NULL; } /* Now unregister any configuration nodes we registered. */ if (KHM_SUCCEEDED(khui_cfg_open(NULL, CONFIGNODE_MAIN, &cnode))) { khui_cfg_remove(cnode); khui_cfg_release(cnode); } if (KHM_SUCCEEDED(khui_cfg_open(NULL, L"KhmIdentities", &cn_idents))) { if (KHM_SUCCEEDED(khui_cfg_open(cn_idents, CONFIGNODE_ALL_ID, &cnode))) { khui_cfg_remove(cnode); khui_cfg_release(cnode); } if (KHM_SUCCEEDED(khui_cfg_open(cn_idents, CONFIGNODE_PER_ID, &cnode))) { khui_cfg_remove(cnode); khui_cfg_release(cnode); } khui_cfg_release(cn_idents); } /* TODO: Perform additional uninitialization operations. */ kcdb_identpro_release(h_idprov); } break; } return rv; }
KHMEXP khm_int32 KHMAPI kcdb_identpro_set_default_identity(khm_handle videntity, khm_boolean ask_idpro) { khm_handle sub = NULL; khm_int32 rv = KHM_ERROR_SUCCESS; kcdb_identpro_i * p; if(!kcdb_is_identity(videntity)) return KHM_ERROR_INVALID_PARAM; p = identpro_get_provider_for_identity(videntity); EnterCriticalSection(&cs_identpro); if (!kcdb_is_active_identpro(p)) { rv = KHM_ERROR_INVALID_PARAM; } else { if (kcdb_identity_is_equal(videntity, p->default_id)) rv = KHM_ERROR_DUPLICATE; } LeaveCriticalSection(&cs_identpro); if (KHM_FAILED(rv)) { return (rv == KHM_ERROR_DUPLICATE)? KHM_ERROR_SUCCESS : rv; } if (ask_idpro) { sub = identpro_get_sub_for_identity(videntity); if(sub != NULL) { rv = kmq_send_sub_msg(sub, KMSG_IDENT, KMSG_IDENT_SET_DEFAULT, TRUE, (void *) videntity); } else { #ifdef DEBUG assert(FALSE); #endif rv = KHM_ERROR_NO_PROVIDER; } } if (KHM_SUCCEEDED(rv)) { khm_handle h_old_id = NULL; int new_default = FALSE; kcdb_identity * id; EnterCriticalSection(&cs_identpro); if (!kcdb_identity_is_equal(videntity, p->default_id)) { h_old_id = p->default_id; p->default_id = videntity; new_default = TRUE; } LeaveCriticalSection(&cs_identpro); EnterCriticalSection(&cs_ident); if (new_default) kcdb_identity_hold(videntity); id = (kcdb_identity *) videntity; id->flags |= KCDB_IDENT_FLAG_DEFAULT; if (h_old_id) { id = (kcdb_identity *) h_old_id; id->flags &= ~KCDB_IDENT_FLAG_DEFAULT; kcdb_identity_release(h_old_id); } LeaveCriticalSection(&cs_ident); if (new_default) { kcdb_identity_hold(videntity); kcdbint_ident_post_message(KCDB_OP_NEW_DEFAULT, (kcdb_identity *) videntity); } } return rv; }
KHMEXP khm_int32 KHMAPI kcdb_identity_set_provider(khm_handle sub) { kmm_plugin plugin = NULL; kcdb_identpro_i * p; khm_int32 rv = KHM_ERROR_SUCCESS; plugin = kmm_this_plugin(); if (plugin == NULL) { #ifdef DEBUG assert(FALSE); #endif return KHM_ERROR_INVALID_OPERATION; } p = identpro_find_by_plugin(plugin); if (p != NULL && sub != NULL) { rv = KHM_ERROR_DUPLICATE; #ifdef DEBUG assert(FALSE); #endif goto _exit; } #ifdef DEBUG assert(sub != NULL || p != NULL); #endif if (p == NULL) p = identpro_create_with_plugin(plugin, sub); if (p == NULL) { rv = KHM_ERROR_UNKNOWN; goto _exit; } if (sub) { rv = kmq_send_sub_msg(sub, KMSG_IDENT, KMSG_IDENT_INIT, 0, 0); if (KHM_FAILED(rv)) { kmq_send_sub_msg(sub, KMSG_IDENT, KMSG_IDENT_EXIT, 0, 0); identpro_mark_for_deletion(p); } else { EnterCriticalSection(&cs_identpro); p->flags |= KCDB_IDENTPRO_FLAG_READY; LeaveCriticalSection(&cs_identpro); } } else { EnterCriticalSection(&cs_identpro); sub = p->sub; LeaveCriticalSection(&cs_identpro); kmq_send_sub_msg(sub, KMSG_IDENT, KMSG_IDENT_EXIT, 0, 0); identpro_mark_for_deletion(p); } _exit: if (p) identpro_release(p); if (plugin) kmm_release_plugin(plugin); return rv; }
int main(int argc, char ** argv) { keystore_t * ks = NULL; int fd = -1; long len; void * buffer = NULL; int read_len; khm_int32 rv; __try { if (argc != 2) { usage(argv[0]); return 0; } fprintf(stderr, "Trying to open file %s\n", argv[1]); _sopen_s(&fd, argv[1], _O_RDONLY | _O_BINARY | _O_SEQUENTIAL, _SH_DENYNO, _S_IREAD); if (fd == -1) { perror("_open"); return 1; } len = _lseek(fd, 0, SEEK_END); if (len == -1) { perror("_lseek"); return 1; } _lseek(fd, 0, SEEK_SET); buffer = malloc(len); read_len = _read(fd, buffer, len); if (read_len == -1) { perror("_read"); return 1; } if (read_len != len) { fprintf(stderr, "Expected read len %ld. Actual len %d\n", len, read_len); return 1; } if (KHM_FAILED(rv = ks_keystore_unserialize(buffer, len, &ks))) { fprintf(stderr, "ks_keystore_unserialize() == %d\n", rv); return 1; } dump_keystore(ks); } __finally { if (fd != -1) _close(fd); if (buffer != NULL) free(buffer); if (ks != NULL) ks_keystore_release(ks); } return 0; }
void khm_cred_renew_all_identities(void) { khm_size count; khm_size cb = 0; khm_size n_idents = 0; khm_int32 rv; wchar_t * ident_names = NULL; wchar_t * this_ident; kcdb_credset_get_size(NULL, &count); /* if there are no credentials, we just skip over the renew action. */ if (count == 0) return; ident_names = NULL; while (TRUE) { if (ident_names) { PFREE(ident_names); ident_names = NULL; } cb = 0; rv = kcdb_identity_enum(KCDB_IDENT_FLAG_EMPTY, 0, NULL, &cb, &n_idents); if (n_idents == 0 || rv != KHM_ERROR_TOO_LONG || cb == 0) break; ident_names = PMALLOC(cb); ident_names[0] = L'\0'; rv = kcdb_identity_enum(KCDB_IDENT_FLAG_EMPTY, 0, ident_names, &cb, &n_idents); if (KHM_SUCCEEDED(rv)) break; } if (ident_names) { for (this_ident = ident_names; this_ident && *this_ident; this_ident = multi_string_next(this_ident)) { khm_handle ident; if (KHM_FAILED(kcdb_identity_create(this_ident, 0, &ident))) continue; khm_cred_renew_identity(ident); kcdb_identity_release(ident); } PFREE(ident_names); ident_names = NULL; } }
KHMEXP khm_int32 KHMAPI kmm_register_plugin(kmm_plugin_reg * plugin, khm_int32 config_flags) { khm_int32 rv = KHM_ERROR_SUCCESS; khm_handle csp_plugin = NULL; khm_handle csp_module = NULL; size_t cch; /* avoid accidently creating the module key if it doesn't exist */ config_flags &= ~KHM_FLAG_CREATE; if((plugin == NULL) || (plugin->dependencies && KHM_FAILED(multi_string_length_cch(plugin->dependencies, KMM_MAXCCH_DEPS, &cch))) || FAILED(StringCchLength(plugin->module, KMM_MAXCCH_NAME, &cch)) || (plugin->description && FAILED(StringCchLength(plugin->description, KMM_MAXCCH_DESC, &cch))) || FAILED(StringCchLength(plugin->name, KMM_MAXCCH_NAME, &cch))) { return KHM_ERROR_INVALID_PARAM; } /* note that we are retaining the length of the plugin name in chars in cch */ cch ++; #define CKRV if(KHM_FAILED(rv)) goto _exit rv = kmm_get_plugin_config(plugin->name, config_flags | KHM_FLAG_CREATE, &csp_plugin); CKRV; /* should fail if the module key doesn't exist */ rv = kmm_get_module_config(plugin->module, config_flags, &csp_module); CKRV; /*TODO: Make sure that the module registration is in the same config store as the one in which the plugin is going to be registered */ rv = khc_write_string(csp_plugin, L"Module", plugin->module); CKRV; if(plugin->description) { rv = khc_write_string(csp_plugin, L"Description", plugin->description); CKRV; } if(plugin->dependencies) { rv = khc_write_multi_string(csp_plugin, L"Dependencies", plugin->dependencies); CKRV; } rv = khc_write_int32(csp_plugin, L"Type", plugin->type); CKRV; rv = khc_write_int32(csp_plugin, L"Disabled", !!(plugin->flags & KMM_PLUGIN_FLAG_DISABLED)); CKRV; { khm_size cb = 0; wchar_t * pl = NULL; size_t scb = 0; rv = khc_read_multi_string(csp_module, L"PluginList", NULL, &cb); if(rv != KHM_ERROR_TOO_LONG) { if (rv == KHM_ERROR_NOT_FOUND) { scb = cb = (cch + 1) * sizeof(wchar_t); pl = PMALLOC(cb); multi_string_init(pl, cb); rv = KHM_ERROR_SUCCESS; goto add_plugin_to_list; } else { goto _exit; } } cb += cch * sizeof(wchar_t); scb = cb; pl = PMALLOC(cb); rv = khc_read_multi_string(csp_module, L"PluginList", pl, &cb); if(KHM_FAILED(rv)) { if(pl) PFREE(pl); goto _exit; } add_plugin_to_list: if(!multi_string_find(pl, plugin->name, 0)) { multi_string_append(pl, &scb, plugin->name); rv = khc_write_multi_string(csp_module, L"PluginList", pl); } PFREE(pl); CKRV; } #undef CKRV _exit: if(csp_plugin) khc_close_space(csp_plugin); if(csp_module) khc_close_space(csp_module); return rv; }
void pw_update_property_data(HWND hw, pw_data * d) { HWND hwnd_lv; khm_int32 * attrs = NULL; hwnd_lv = d->hwnd_lv; if(hwnd_lv == NULL) return; ListView_DeleteAllItems(hwnd_lv); if(d->record != NULL) { wchar_t * buffer; khm_size attr_count; khm_size i; khm_size cb_buf; khm_size t; LVITEM lvi; int idx; if(KHM_FAILED(kcdb_attrib_get_count( KCDB_ATTR_FLAG_VOLATILE | KCDB_ATTR_FLAG_HIDDEN, 0, &attr_count))) return; attrs = PMALLOC(sizeof(khm_int32) * attr_count); assert(attrs != NULL); kcdb_attrib_get_ids( KCDB_ATTR_FLAG_VOLATILE | KCDB_ATTR_FLAG_HIDDEN, 0, attrs, &attr_count); cb_buf = sizeof(wchar_t) * 2048; buffer = PMALLOC(cb_buf); assert(buffer != NULL); for(i=0; i<attr_count; i++) { if(KHM_FAILED(kcdb_buf_get_attr(d->record, attrs[i], NULL, NULL, NULL))) continue; ZeroMemory(&lvi, sizeof(lvi)); lvi.mask = LVIF_TEXT | LVIF_PARAM; lvi.iItem = (int) i; lvi.iSubItem = 0; lvi.pszText = buffer; lvi.lParam = (LPARAM) attrs[i]; t = cb_buf; kcdb_attrib_describe(attrs[i], buffer, &t, KCDB_TS_SHORT); idx = ListView_InsertItem(hwnd_lv, &lvi); ZeroMemory(&lvi, sizeof(lvi)); lvi.mask = LVIF_TEXT; lvi.iItem = idx; lvi.iSubItem = 1; lvi.pszText = buffer; t = cb_buf; kcdb_buf_get_attr_string(d->record, attrs[i], buffer, &t, 0); ListView_SetItem(hwnd_lv, &lvi); } PFREE(attrs); PFREE(buffer); } }
/* Returns true if we find cached prompts. Called with kt->cs held. */ static khm_boolean cached_kinit_prompter(k5_kinit_task * kt) { khm_boolean rv = FALSE; khm_handle csp_idconfig = NULL; khm_handle csp_k5config = NULL; khm_handle csp_prcache = NULL; khm_size cb; khm_size n_cur_prompts; khm_int32 n_prompts; khm_int32 i; khm_int64 iexpiry; FILETIME expiry; assert(kt->nc); if (KHM_FAILED(kcdb_identity_get_config(kt->identity, 0, &csp_idconfig)) || KHM_FAILED(khc_open_space(csp_idconfig, CSNAME_KRB5CRED, 0, &csp_k5config)) || KHM_FAILED(khc_open_space(csp_k5config, CSNAME_PROMPTCACHE, 0, &csp_prcache)) || KHM_FAILED(khc_read_int32(csp_prcache, L"PromptCount", &n_prompts)) || n_prompts == 0) goto _cleanup; if (KHM_SUCCEEDED(khc_read_int64(csp_prcache, L"ExpiresOn", &iexpiry))) { FILETIME current; /* has the cache expired? */ expiry = IntToFt(iexpiry); GetSystemTimeAsFileTime(¤t); if (CompareFileTime(&expiry, ¤t) < 0) /* already expired */ goto _cleanup; } else { /* if there is no value for ExpiresOn, we assume the prompts have already expired. */ goto _cleanup; } /* we found a prompt cache. We take this to imply that the principal is valid. */ kt->is_valid_principal = TRUE; /* check if there are any prompts currently showing. If there are we check if they are the same as the ones we are going to show. In which case we just reuse the exisitng prompts */ if (KHM_FAILED(khui_cw_get_prompt_count(kt->nc, &n_cur_prompts)) || n_prompts != (khm_int32) n_cur_prompts) goto _show_new_prompts; for(i = 0; i < n_prompts; i++) { wchar_t wsname[8]; wchar_t wprompt[KHUI_MAXCCH_PROMPT]; khm_handle csp_p = NULL; khm_int32 p_type; khm_int32 p_flags; khui_new_creds_prompt * p; if (KHM_FAILED(khui_cw_get_prompt(kt->nc, i, &p))) break; StringCbPrintf(wsname, sizeof(wsname), L"%d", i); if (KHM_FAILED(khc_open_space(csp_prcache, wsname, 0, &csp_p))) break; cb = sizeof(wprompt); if (KHM_FAILED(khc_read_string(csp_p, L"Prompt", wprompt, &cb))) { khc_close_space(csp_p); break; } if (KHM_FAILED(khc_read_int32(csp_p, L"Type", &p_type))) p_type = 0; if (KHM_FAILED(khc_read_int32(csp_p, L"Flags", &p_flags))) p_flags = 0; if ( /* if we received a prompt string, then it should be the same as the one that is displayed */ (wprompt[0] && (p->prompt == NULL || wcscmp(wprompt, p->prompt))) || /* if we didn't receive one, then there shouldn't be one displayed. This case really shouldn't happen in reality, but we check anyway. */ (!wprompt[0] && p->prompt != NULL) || /* the type should match */ (p_type != p->type) || /* if this prompt should be hidden, then it must also be so */ (p_flags != p->flags) ) { khc_close_space(csp_p); break; } khc_close_space(csp_p); } if (i == n_prompts) { /* We are already showing the right set of prompts. */ rv = TRUE; goto _cleanup; } _show_new_prompts: khui_cw_clear_prompts(kt->nc); { wchar_t wbanner[KHUI_MAXCCH_BANNER]; wchar_t wpname[KHUI_MAXCCH_PNAME]; cb = sizeof(wbanner); if (KHM_FAILED(khc_read_string(csp_prcache, L"Banner", wbanner, &cb))) wbanner[0] = 0; cb = sizeof(wpname); if (KHM_FAILED(khc_read_string(csp_prcache, L"Name", wpname, &cb))) wpname[0] = 0; if (wpname[0] == L'\0') LoadString(hResModule, IDS_PNAME_PW, wpname, ARRAYLENGTH(wpname)); khui_cw_begin_custom_prompts(kt->nc, n_prompts, (wbanner[0]? wbanner: NULL), (wpname[0]? wpname: NULL)); } for(i = 0; i < n_prompts; i++) { wchar_t wsname[8]; wchar_t wprompt[KHUI_MAXCCH_PROMPT]; khm_handle csp_p = NULL; khm_int32 p_type; khm_int32 p_flags; StringCbPrintf(wsname, sizeof(wsname), L"%d", i); if (KHM_FAILED(khc_open_space(csp_prcache, wsname, 0, &csp_p))) break; cb = sizeof(wprompt); if (KHM_FAILED(khc_read_string(csp_p, L"Prompt", wprompt, &cb))) { khc_close_space(csp_p); break; } if (KHM_FAILED(khc_read_int32(csp_p, L"Type", &p_type))) p_type = 0; if (KHM_FAILED(khc_read_int32(csp_p, L"Flags", &p_flags))) p_flags = 0; khui_cw_add_prompt(kt->nc, p_type, wprompt, NULL, p_flags); khc_close_space(csp_p); } if (i < n_prompts) { khui_cw_clear_prompts(kt->nc); } else { rv = TRUE; } _cleanup: if (csp_prcache) khc_close_space(csp_prcache); if (csp_k5config) khc_close_space(csp_k5config); if (csp_idconfig) khc_close_space(csp_idconfig); return rv; }
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]; nc = (khui_new_creds *) vparam; if (!nc->ctx.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; k4_dlg_data * d = NULL; long code = 0; wchar_t idname[KCDB_IDENT_MAXCCH_NAME]; khm_size cb; nc = (khui_new_creds *) vparam; if (KHM_FAILED(khui_cw_find_type(nc, credtype_id_krb4, &nct))) break; if (nc->subtype == KMSG_CRED_NEW_CREDS || nc->subtype == KMSG_CRED_RENEW_CREDS) { khm_int32 method; if (nc->subtype == KMSG_CRED_NEW_CREDS) { d = (k4_dlg_data *) nct->aux; if (!d || nc->n_identities == 0 || nc->identities[0] == NULL || nc->result != KHUI_NC_RESULT_PROCESS) { khui_cw_set_response(nc, credtype_id_krb4, KHUI_NC_RESPONSE_SUCCESS | KHUI_NC_RESPONSE_EXIT); 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); break; } method = d->method; ident = nc->identities[0]; cb = sizeof(idname); kcdb_identity_get_name(ident, idname, &cb); _begin_task(0); _report_mr2(KHERR_NONE, MSG_K4_NEW_CREDS, _cstr(ident), _int32(method)); _resolve(); _describe(); } else if (nc->subtype == KMSG_CRED_RENEW_CREDS) { if ((nc->ctx.scope == KHUI_SCOPE_IDENT && nc->ctx.identity != NULL) || (nc->ctx.scope == KHUI_SCOPE_CREDTYPE && nc->ctx.cred_type == credtype_id_krb4 && nc->ctx.identity != NULL) || (nc->ctx.scope == KHUI_SCOPE_CRED && nc->ctx.cred_type == credtype_id_krb4 && nc->ctx.identity != NULL && nc->ctx.cred != NULL)) { ident = nc->ctx.identity; 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); 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_mr2(KHERR_NONE, MSG_K4_RENEW_CREDS, _cstr(ident), _int32(method)); _resolve(); _describe(); } else { assert(FALSE); break; } 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_mr0(KHERR_INFO, MSG_K4_TRY_K524); tgt = khm_krb4_find_tgt(NULL, ident); 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); _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 (nc->subtype == KMSG_CRED_NEW_CREDS) { assert(d != NULL); k4_write_identity_data(d); } else if (nc->subtype == KMSG_CRED_RENEW_CREDS && (nc->ctx.scope == KHUI_SCOPE_CREDTYPE || nc->ctx.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, nc->ctx.identity, KCDB_CREDTYPE_INVALID, NULL); khui_action_trigger(KHUI_ACTION_RENEW_CRED, &ctx); khui_context_release(&ctx); } } _end_task(); break; } else if (method == K4_METHOD_K524) { khui_cw_set_response(nc, credtype_id_krb4, KHUI_NC_RESPONSE_FAILED | KHUI_NC_RESPONSE_EXIT); if (nc->subtype == KMSG_CRED_RENEW_CREDS && (nc->ctx.scope == KHUI_SCOPE_CREDTYPE || nc->ctx.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, nc->ctx.identity, KCDB_CREDTYPE_INVALID, NULL); khui_action_trigger(KHUI_ACTION_RENEW_CRED, &ctx); khui_context_release(&ctx); } _end_task(); 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(nc->subtype == KMSG_CRED_NEW_CREDS); _report_mr0(KHERR_INFO, MSG_K4_TRY_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); _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 (nc->subtype == KMSG_CRED_NEW_CREDS) { assert(d != NULL); k4_write_identity_data(d); } } } _end_task(); } } 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; }
khm_int32 kmmint_read_module_info(kmm_module_i * m) { /* the only fields we can count on at this point are m->name and m->path */ DWORD t; size_t cb; WORD lang; khm_int32 rv = KHM_ERROR_SUCCESS; struct lang_code *languages; int n_languages; int i; wchar_t resname[256]; /* the resource names are a lot shorter */ wchar_t * r; VS_FIXEDFILEINFO *vff; UINT c; assert(m->name); assert(m->path); t = TRUE; cb = GetFileVersionInfoSize(m->path, &t); /* if successful, cb gets the size in bytes of the version info structure and sets t to zero */ if (t) { return KHM_ERROR_NOT_FOUND; } else if (cb == 0) { _report_mr1(KHERR_WARNING, MSG_RMI_NOT_FOUND, _dupstr(m->path)); return KHM_ERROR_INVALID_PARAM; } if (m->version_info) { PFREE(m->version_info); m->version_info = NULL; } m->version_info = PMALLOC(cb); #ifdef DEBUG assert(m->version_info); #endif if(!GetFileVersionInfo(m->path, t, (DWORD) cb, m->version_info)) { rv = KHM_ERROR_NOT_FOUND; _report_mr1(KHERR_WARNING, MSG_RMI_NOT_FOUND, _dupstr(m->path)); _location(L"GetFileVersionInfo"); goto _cleanup; } if(!VerQueryValue(m->version_info, L"\\VarFileInfo\\Translation", (LPVOID*) &languages, &c)) { rv = KHM_ERROR_INVALID_PARAM; _report_mr1(KHERR_WARNING, MSG_RMI_NO_TRANS, _dupstr(m->path)); _location(L"VerQueryValue"); goto _cleanup; } n_languages = (int) (c / sizeof(*languages)); /* Try searching for the user's default language first */ lang = GetUserDefaultLangID(); for (i = 0; i < n_languages; i++) { if(languages[i].language == lang) break; } /* If not, try the system default */ if (i >= n_languages) { lang = GetSystemDefaultLangID(); for (i=0; i<n_languages; i++) if (languages[i].language == lang) break; } /* Then try EN_US */ if (i >= n_languages) { lang = MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US); for (i=0; i<n_languages; i++) if (languages[i].language == lang) break; } /* Language neutral? */ if (i >= n_languages) { lang = MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL); for (i=0; i<n_languages; i++) if (languages[i].language == lang) break; } /* Just use the first one? */ if (i >= n_languages) { i = 0; } if (i >= n_languages) { rv = KHM_ERROR_INVALID_PARAM; _report_mr0(KHERR_WARNING, MSG_RMI_NO_LOCAL); goto _cleanup; } /* check module name */ StringCbPrintf(resname, sizeof(resname), L"\\StringFileInfo\\%04x%04x\\" TEXT(NIMV_MODULE), languages[i].language, languages[i].codepage); if (!VerQueryValue(m->version_info, resname, (LPVOID *) &r, &c)) { rv = KHM_ERROR_INVALID_PARAM; _report_mr1(KHERR_WARNING, MSG_RMI_RES_MISSING, _cstr(TEXT(NIMV_MODULE))); goto _cleanup; } if (c > KMM_MAXCB_NAME || FAILED(StringCbLength(r, KMM_MAXCB_NAME, &cb))) { rv = KHM_ERROR_INVALID_PARAM; _report_mr1(KHERR_WARNING, MSG_RMI_RES_TOO_LONG, _cstr(TEXT(NIMV_MODULE))); goto _cleanup; } if (wcscmp(r, m->name)) { rv = KHM_ERROR_INVALID_PARAM; _report_mr2(KHERR_WARNING, MSG_RMI_MOD_MISMATCH, _dupstr(r), _dupstr(m->name)); goto _cleanup; } /* check API version */ StringCbPrintf(resname, sizeof(resname), L"\\StringFileInfo\\%04x%04x\\" TEXT(NIMV_APIVER), languages[i].language, languages[i].codepage); if (!VerQueryValue(m->version_info, resname, (LPVOID *) &r, &c)) { rv = KHM_ERROR_INVALID_PARAM; _report_mr1(KHERR_WARNING, MSG_RMI_RES_MISSING, _cstr(TEXT(NIMV_APIVER))); goto _cleanup; } if (c > KMM_MAXCB_NAME || FAILED(StringCbLength(r, KMM_MAXCB_NAME, &cb))) { rv = KHM_ERROR_INVALID_PARAM; _report_mr1(KHERR_WARNING, MSG_RMI_RES_TOO_LONG, _cstr(TEXT(NIMV_APIVER))); goto _cleanup; } t = wcstol(r, NULL, 10); rv = kmmint_check_api_version(t); if (KHM_FAILED(rv)) { _report_mr2(KHERR_WARNING, MSG_RMI_API_MISMATCH, _int32(t), _int32(KH_VERSION_API)); goto _cleanup; } /* Looks good. Now load the description, copyright, support URI and file versions */ if (m->description) { PFREE(m->description); m->description = NULL; } StringCbPrintf(resname, sizeof(resname), L"\\StringFileInfo\\%04x%04x\\FileDescription", languages[i].language, languages[i].codepage); if (!VerQueryValue(m->version_info, resname, (LPVOID *) &r, &c)) { rv = KHM_ERROR_INVALID_PARAM; _report_mr1(KHERR_WARNING, MSG_RMI_RES_MISSING, _cstr(L"FileDescription")); goto _cleanup; } if (c > KMM_MAXCB_DESC || FAILED(StringCbLength(r, KMM_MAXCB_DESC, &cb))) { rv = KHM_ERROR_INVALID_PARAM; _report_mr1(KHERR_WARNING, MSG_RMI_RES_TOO_LONG, _cstr(L"FileDescription")); goto _cleanup; } cb += sizeof(wchar_t); m->description = PMALLOC(cb); #ifdef DEBUG assert(m->description); #endif StringCbCopy(m->description, cb, r); /* on to the support URI */ if (m->support) { PFREE(m->support); m->support = NULL; } StringCbPrintf(resname, sizeof(resname), L"\\StringFileInfo\\%04x%04x\\" TEXT(NIMV_SUPPORT), languages[i].language, languages[i].codepage); if (!VerQueryValue(m->version_info, resname, (LPVOID *) &r, &c)) { rv = KHM_ERROR_INVALID_PARAM; _report_mr1(KHERR_WARNING, MSG_RMI_RES_MISSING, _cstr(TEXT(NIMV_SUPPORT))); goto _cleanup; } if (c > KMM_MAXCB_SUPPORT || FAILED(StringCbLength(r, KMM_MAXCB_SUPPORT, &cb))) { rv = KHM_ERROR_INVALID_PARAM; _report_mr1(KHERR_WARNING, MSG_RMI_RES_TOO_LONG, _cstr(TEXT(NIMV_SUPPORT))); goto _cleanup; } cb += sizeof(wchar_t); m->support = PMALLOC(cb); #ifdef DEBUG assert(m->support); #endif StringCbCopy(m->support, cb, r); /* the vendor/copyright */ if (m->vendor) { PFREE(m->vendor); m->vendor = NULL; } StringCbPrintf(resname, sizeof(resname), L"\\StringFileInfo\\%04x%04x\\LegalCopyright", languages[i].language, languages[i].codepage); if (!VerQueryValue(m->version_info, resname, (LPVOID *) &r, &c)) { rv = KHM_ERROR_INVALID_PARAM; _report_mr1(KHERR_WARNING, MSG_RMI_RES_MISSING, _cstr(L"LegalCopyright")); goto _cleanup; } if (c > KMM_MAXCB_SUPPORT || FAILED(StringCbLength(r, KMM_MAXCB_SUPPORT, &cb))) { rv = KHM_ERROR_INVALID_PARAM; _report_mr1(KHERR_WARNING, MSG_RMI_RES_TOO_LONG, _cstr(L"LegalCopyright")); goto _cleanup; } cb += sizeof(wchar_t); m->vendor = PMALLOC(cb); #ifdef DEBUG assert(m->vendor); #endif StringCbCopy(m->vendor, cb, r); if (!VerQueryValue(m->version_info, L"\\", (LPVOID *) &vff, &c) || c != sizeof(*vff)) { rv = KHM_ERROR_INVALID_PARAM; _report_mr1(KHERR_WARNING, MSG_RMI_RES_MISSING, _cstr(L"Fixed Version Info")); goto _cleanup; } m->file_version.major = HIWORD(vff->dwFileVersionMS); m->file_version.minor = LOWORD(vff->dwFileVersionMS); m->file_version.patch = HIWORD(vff->dwFileVersionLS); m->file_version.aux = LOWORD(vff->dwFileVersionLS); m->prod_version.major = HIWORD(vff->dwProductVersionMS); m->prod_version.minor = LOWORD(vff->dwProductVersionMS); m->prod_version.patch = HIWORD(vff->dwProductVersionLS); m->prod_version.aux = LOWORD(vff->dwProductVersionLS); rv = KHM_ERROR_SUCCESS; _cleanup: if (KHM_FAILED(rv)) { if (m->version_info) { PFREE(m->version_info); m->version_info = NULL; } } return rv; }
INT_PTR CALLBACK khm_cfg_plugins_proc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { plugin_dlg_data * d; switch(uMsg) { case WM_INITDIALOG: { kmm_plugin p; kmm_plugin pn; kmm_module m; khm_size i; LVCOLUMN lvc; RECT r; HWND hw; wchar_t buf[256]; HIMAGELIST h_ilist; HICON h_icon; d = PMALLOC(sizeof(*d)); #ifdef DEBUG assert(d); #endif ZeroMemory(d, sizeof(*d)); #pragma warning(push) #pragma warning(disable: 4244) SetWindowLongPtr(hwnd, DWLP_USER, (LONG_PTR) d); #pragma warning(pop) p = NULL; i = 0; do { if (KHM_FAILED(kmm_get_next_plugin(p, &pn))) break; if (p) kmm_release_plugin(p); p = pn; #ifdef DEBUG assert(d->info[i] == NULL); #endif d->info[i] = PMALLOC(sizeof(*(d->info[i]))); #ifdef DEBUG assert(d->info[i]); #endif ZeroMemory(&d->info[i]->plugin, sizeof(d->info[i]->plugin)); if (KHM_FAILED(kmm_get_plugin_info_i(p, &d->info[i]->plugin))) { PFREE(d->info[i]); d->info[i] = NULL; break; } ZeroMemory(&d->info[i]->module, sizeof(d->info[i]->module)); if (KHM_SUCCEEDED(kmm_load_module(d->info[i]->plugin.reg.module, KMM_LM_FLAG_NOLOAD, &m))) { kmm_get_module_info_i(m, &d->info[i]->module); kmm_release_module(m); } i ++; if (i == MAX_PLUGINS) break; } while(p); if (p) kmm_release_plugin(p); d->n_info = i; /* now populate the list view */ hw = GetDlgItem(hwnd, IDC_CFG_PLUGINS); #ifdef DEBUG assert(hw); #endif h_ilist = ImageList_Create(GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), ILC_COLOR8, 4, 4); h_icon = LoadImage(khm_hInstance, MAKEINTRESOURCE(IDI_CFG_PLUGIN), IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_DEFAULTCOLOR); #ifdef DEBUG assert(h_icon); #endif ImageList_AddIcon(h_ilist, h_icon); DestroyIcon(h_icon); h_icon = LoadImage(khm_hInstance, MAKEINTRESOURCE(IDI_CFG_PLUGIN_DIS), IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_DEFAULTCOLOR); #ifdef DEBUG assert(h_icon); #endif ImageList_AddIcon(h_ilist, h_icon); DestroyIcon(h_icon); h_icon = LoadImage(khm_hInstance, MAKEINTRESOURCE(IDI_CFG_PLUGIN_ERR), IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_DEFAULTCOLOR); #ifdef DEBUG assert(h_icon); #endif ImageList_AddIcon(h_ilist, h_icon); DestroyIcon(h_icon); ListView_SetImageList(hw, h_ilist, LVSIL_STATE); ZeroMemory(&lvc, sizeof(lvc)); lvc.mask = LVCF_TEXT | LVCF_WIDTH; GetWindowRect(hw, &r); lvc.cx = ((r.right - r.left) * 95) / 100; lvc.pszText = buf; LoadString(khm_hInstance, IDS_CFG_PI_COL_PLUGINS, buf, ARRAYLENGTH(buf)); ListView_InsertColumn(hw, 0, &lvc); for(i=0; i<d->n_info; i++) { LVITEM lvi; ZeroMemory(&lvi, sizeof(lvi)); lvi.mask = LVIF_PARAM | LVIF_TEXT | LVIF_STATE; lvi.lParam = (LPARAM) d->info[i]; lvi.pszText = d->info[i]->plugin.reg.name; if (d->info[i]->plugin.flags & KMM_PLUGIN_FLAG_DISABLED) { lvi.state = INDEXTOSTATEIMAGEMASK(IDX_PLUGIN_DISABLED); } else if (d->info[i]->plugin.state < 0) { lvi.state = INDEXTOSTATEIMAGEMASK(IDX_PLUGIN_ERROR); } else { lvi.state = INDEXTOSTATEIMAGEMASK(IDX_PLUGIN_NORMAL); } ListView_InsertItem(hw, &lvi); } d->plugin_ico = (HICON) LoadImage(khm_hInstance, MAKEINTRESOURCE(IDI_CFG_PLUGIN), IMAGE_ICON, GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON), LR_DEFAULTCOLOR); } return FALSE; case WM_NOTIFY: { LPNMHDR lpnm; HWND hw; d = (plugin_dlg_data *) (LONG_PTR) GetWindowLongPtr(hwnd, DWLP_USER); if (d == NULL) return FALSE; if (wParam == IDC_CFG_PLUGINS && (lpnm = (LPNMHDR) lParam) && lpnm->code == LVN_ITEMCHANGED) { LVITEM lvi; hw = GetDlgItem(hwnd, IDC_CFG_PLUGINS); #ifdef DEBUG assert(hw); #endif if (ListView_GetSelectedCount(hw) != 1) { SetDlgItemText(hwnd, IDC_CFG_DESC, L""); SetDlgItemText(hwnd, IDC_CFG_STATE, L""); SetDlgItemText(hwnd, IDC_CFG_MODULE, L""); SetDlgItemText(hwnd, IDC_CFG_VENDOR, L""); SetDlgItemText(hwnd, IDC_CFG_VERSION, L""); EnableWindow(GetDlgItem(hwnd, IDC_CFG_ENABLE), FALSE); EnableWindow(GetDlgItem(hwnd, IDC_CFG_DISABLE), FALSE); EnableWindow(GetDlgItem(hwnd, IDC_CFG_UNREGISTER), FALSE); SendDlgItemMessage(hwnd, IDC_CFG_DEPS, LB_RESETCONTENT, 0, 0); SendDlgItemMessage(hwnd, IDC_CFG_ICON, STM_SETICON, (WPARAM) d->plugin_ico, 0); d->selected = NULL; } else { int idx; plugin_data * info; idx = ListView_GetNextItem(hw, -1, LVNI_SELECTED); #ifdef DEBUG assert(idx != -1); #endif ZeroMemory(&lvi, sizeof(lvi)); lvi.iItem = idx; lvi.iSubItem = 0; lvi.mask = LVIF_PARAM; ListView_GetItem(hw, &lvi); #ifdef DEBUG assert(lvi.lParam != 0); #endif info = (plugin_data *) lvi.lParam; update_dialog_fields(hwnd, d, info); } } } return TRUE; case WM_COMMAND: { d = (plugin_dlg_data *) (LONG_PTR) GetWindowLongPtr(hwnd, DWLP_USER); if (d == NULL) return FALSE; switch (wParam) { case MAKEWPARAM(IDC_CFG_ENABLE, BN_CLICKED): if (d->selected != NULL) { khui_alert * alert = NULL; wchar_t buf[KHUI_MAXCCH_MESSAGE]; wchar_t fmt[KHUI_MAXCCH_MESSAGE]; kmm_plugin p; khui_alert_create_empty(&alert); LoadString(khm_hInstance, IDS_CFG_P_ENBCNFT, fmt, ARRAYLENGTH(fmt)); StringCbPrintf(buf, sizeof(buf), fmt, d->selected->plugin.reg.name); khui_alert_set_title(alert, buf); LoadString(khm_hInstance, IDS_CFG_P_ENBCNFM, fmt, ARRAYLENGTH(fmt)); StringCbPrintf(buf, sizeof(buf), fmt, d->selected->plugin.reg.name); khui_alert_set_message(alert, buf); khui_alert_set_severity(alert, KHERR_INFO); khui_alert_show_modal(alert); kmm_enable_plugin(d->selected->plugin.h_plugin, TRUE); khui_alert_release(alert); p = d->selected->plugin.h_plugin; kmm_hold_plugin(p); kmm_release_plugin_info_i(&d->selected->plugin); kmm_get_plugin_info_i(p, &d->selected->plugin); kmm_release_plugin(p); update_dialog_fields(hwnd, d, d->selected); } break; case MAKEWPARAM(IDC_CFG_DISABLE, BN_CLICKED): if (d->selected != NULL) { khui_alert * alert = NULL; wchar_t buf[KHUI_MAXCCH_MESSAGE]; wchar_t fmt[KHUI_MAXCCH_MESSAGE]; wchar_t depends[KHUI_MAXCCH_MESSAGE]; khm_size i; kmm_plugin p; khui_alert_create_empty(&alert); #ifdef DEBUG assert(alert); #endif if (alert == NULL) break; LoadString(khm_hInstance, IDS_CFG_P_DELCNFT, fmt, ARRAYLENGTH(fmt)); StringCbPrintf(buf, sizeof(buf), fmt, d->selected->plugin.reg.name); khui_alert_set_title(alert, buf); LoadString(khm_hInstance, IDS_CFG_P_DELCNFM, fmt, ARRAYLENGTH(fmt)); StringCbPrintf(buf, sizeof(buf), fmt, d->selected->plugin.reg.name); khui_alert_set_message(alert, buf); depends[0] = L'\0'; for (i=0; i<d->n_info; i++) { wchar_t * t; t = d->info[i]->plugin.reg.dependencies; while(t) { if (!wcscmp(t, d->selected->plugin.reg.name)) { if (depends[0]) StringCbCat(depends, sizeof(depends), L", "); StringCbCat(depends, sizeof(depends), d->info[i]->plugin.reg.name); break; } t = multi_string_next(t); } } if (depends[0]) { LoadString(khm_hInstance, IDS_CFG_P_DELCNFS, fmt, ARRAYLENGTH(fmt)); StringCbPrintf(buf, sizeof(buf), fmt, depends); khui_alert_set_suggestion(alert, buf); } else { LoadString(khm_hInstance, IDS_CFG_P_DELNDEP, buf, ARRAYLENGTH(buf)); khui_alert_set_suggestion(alert, buf); } khui_alert_add_command(alert, KHUI_PACTION_YES); khui_alert_add_command(alert, KHUI_PACTION_NO); khui_alert_set_severity(alert, KHERR_WARNING); if (KHM_SUCCEEDED(khui_alert_show_modal(alert)) && alert->response == KHUI_PACTION_YES) { kmm_enable_plugin(d->selected->plugin.h_plugin, FALSE); } khui_alert_release(alert); p = d->selected->plugin.h_plugin; kmm_hold_plugin(p); kmm_release_plugin_info_i(&d->selected->plugin); kmm_get_plugin_info_i(p, &d->selected->plugin); kmm_release_plugin(p); update_dialog_fields(hwnd, d, d->selected); } break; case MAKEWPARAM(IDC_CFG_UNREGISTER, BN_CLICKED): { khui_alert * alert = NULL; wchar_t buf[KHUI_MAXCCH_MESSAGE]; wchar_t fmt[KHUI_MAXCCH_MESSAGE]; wchar_t plist[KHUI_MAXCCH_MESSAGE]; khm_size i; if (d->selected == NULL) { #ifdef DEBUG assert(FALSE); #endif break; } khui_alert_create_empty(&alert); LoadString(khm_hInstance, IDS_CFG_P_UNRCNFT, fmt, ARRAYLENGTH(fmt)); StringCbPrintf(buf, sizeof(buf), fmt, d->selected->plugin.reg.name); khui_alert_set_title(alert, buf); LoadString(khm_hInstance, IDS_CFG_P_UNRCNFM, fmt, ARRAYLENGTH(fmt)); StringCbPrintf(buf, sizeof(buf), fmt, d->selected->plugin.reg.name); khui_alert_set_message(alert, buf); plist[0] = L'\0'; for (i=0; i < d->n_info; i++) { if (!wcscmp(d->info[i]->module.reg.name, d->selected->module.reg.name)) { if (plist[0]) StringCbCat(plist, sizeof(plist), L", "); StringCbCat(plist, sizeof(plist), d->info[i]->plugin.reg.name); } } #ifdef DEBUG /* there should have been at least one plugin */ assert(plist[0]); #endif LoadString(khm_hInstance, IDS_CFG_P_UNRCNFS, fmt, ARRAYLENGTH(fmt)); StringCbPrintf(buf, sizeof(buf), fmt, plist); khui_alert_set_suggestion(alert, buf); khui_alert_add_command(alert, KHUI_PACTION_YES); khui_alert_add_command(alert, KHUI_PACTION_NO); khui_alert_set_severity(alert, KHERR_WARNING); if (KHM_SUCCEEDED(khui_alert_show_modal(alert)) && alert->response == KHUI_PACTION_YES) { kmm_unregister_module(d->selected->module.reg.name, 0); update_dialog_fields(hwnd, d, d->selected); } } break; case MAKEWPARAM(IDC_CFG_REGISTER, BN_CLICKED): { } break; } } return TRUE; case WM_DESTROY: { khm_size i; d = (plugin_dlg_data *) (LONG_PTR) GetWindowLongPtr(hwnd, DWLP_USER); #ifdef DEBUG assert(d); #endif if (d == NULL) return TRUE; for (i=0; i<d->n_info; i++) { #ifdef DEBUG assert(d->info[i]); #endif kmm_release_plugin_info_i(&d->info[i]->plugin); kmm_release_module_info_i(&d->info[i]->module); PFREE(d->info[i]); } PFREE(d); SetWindowLongPtr(hwnd, DWLP_USER, 0); khm_set_dialog_result(hwnd, 0); } return TRUE; } return FALSE; }
static void read_params_ident(ident_data * d) { khm_handle csp_ident; khm_handle csp_cw; khm_int32 t; if (KHM_FAILED(kcdb_identity_get_config(d->ident, KHM_PERM_READ, &csp_ident))) { csp_ident = NULL; } if (KHM_SUCCEEDED(khc_open_space(NULL, L"CredWindow", KHM_PERM_READ, &csp_cw))) { if (csp_ident) { khc_shadow_space(csp_ident, csp_cw); khc_close_space(csp_cw); } else { csp_ident = csp_cw; } csp_cw = NULL; } else { #ifdef DEBUG assert(FALSE); #endif d->saved.monitor = TRUE; d->saved.auto_renew = TRUE; d->saved.sticky = FALSE; d->work = d->saved; if (csp_ident) khc_close_space(csp_ident); return; } if (KHM_FAILED(khc_read_int32(csp_ident, L"Monitor", &t))) { #ifdef DEBUG assert(FALSE); #endif d->saved.monitor = TRUE; } else { d->saved.monitor = !!t; } if (KHM_FAILED(khc_read_int32(csp_ident, L"AllowAutoRenew", &t))) { #ifdef DEBUG assert(FALSE); #endif d->saved.auto_renew = TRUE; } else { d->saved.auto_renew = !!t; } if (KHM_FAILED(khc_read_int32(csp_ident, L"Sticky", &t))) { d->saved.sticky = FALSE; } else { d->saved.sticky = !!t; } khc_close_space(csp_ident); d->work = d->saved; d->applied = FALSE; }
/*! \internal \brief Manages a plugin message thread. Each plugin gets its own plugin thread which is used to dispatch messages to the plugin. This acts as the thread function for the plugin thread.*/ DWORD WINAPI kmmint_plugin_broker(LPVOID lpParameter) { DWORD rv = 0; kmm_plugin_i * p = (kmm_plugin_i *) lpParameter; PDESCTHREAD(p->p.name, L"KMM"); _begin_task(0); _report_mr1(KHERR_NONE, MSG_PB_START, _cstr(p->p.name)); _describe(); TlsSetValue(tls_kmm, (LPVOID) p); kmm_hold_plugin(kmm_handle_from_plugin(p)); p->tid_thread = GetCurrentThreadId(); if (IsBadCodePtr(p->p.msg_proc)) { _report_mr0(KHERR_WARNING, MSG_PB_INVALID_CODE_PTR); rv = KHM_ERROR_INVALID_PARAM; } else { rv = (*p->p.msg_proc)(KMSG_SYSTEM, KMSG_SYSTEM_INIT, 0, (void *) &(p->p)); _report_mr1(KHERR_INFO, MSG_PB_INIT_RV, _int32(rv)); } /* if it fails to initialize, we exit the plugin */ if(KHM_FAILED(rv)) { kherr_report(KHERR_ERROR, (wchar_t *) MSG_PB_INIT_FAIL_S, (wchar_t *) KHERR_FACILITY, NULL, (wchar_t *) MSG_PB_INIT_FAIL, (wchar_t *) MSG_PB_INIT_FAIL_G, KHERR_FACILITY_ID, KHERR_SUGGEST_NONE, _cstr(p->p.name), _cstr(p->p.description), _cstr(p->module->path), _cstr(p->module->support), KHERR_RF_MSG_SHORT_DESC | KHERR_RF_MSG_LONG_DESC | KHERR_RF_MSG_SUGGEST #ifdef _WIN32 ,KHERR_HMODULE #endif ); _resolve(); /* exit the plugin first. Otherwise it may not uninitialize correctly */ (*p->p.msg_proc)(KMSG_SYSTEM, KMSG_SYSTEM_EXIT, 0, (void *) &(p->p)); kmmint_remove_from_plugin_queue(p); rv = 1; _end_task(); p->state = KMM_PLUGIN_STATE_FAIL_INIT; goto _exit; } /* subscribe to default message classes by plugin type */ if(p->p.type == KHM_PITYPE_CRED) { kmq_subscribe(KMSG_SYSTEM, p->p.msg_proc); kmq_subscribe(KMSG_KCDB, p->p.msg_proc); kmq_subscribe(KMSG_CRED, p->p.msg_proc); } else if(p->p.type == KHM_PITYPE_IDENT) { khm_handle h = NULL; kmq_subscribe(KMSG_SYSTEM, p->p.msg_proc); kmq_subscribe(KMSG_KCDB, p->p.msg_proc); kmq_create_subscription(p->p.msg_proc, &h); kcdb_identity_set_provider(h); /* kcdb deletes the subscription when it's done with it */ } else if(p->p.type == KHM_PITYPE_CONFIG) { /*TODO: subscribe to configuration provider messages here */ } p->state = KMM_PLUGIN_STATE_RUNNING; _report_mr0(KHERR_INFO, MSG_PB_INIT_DONE); _end_task(); /* if there were any plugins that were waiting for this one to start, we should start them too */ EnterCriticalSection(&cs_kmm); do { kmm_plugin_i * pd; int i; for(i=0; i < p->n_dependants; i++) { pd = p->dependants[i]; pd->n_unresolved--; if(pd->n_unresolved == 0) { kmmint_add_to_plugin_queue(pd); kmm_hold_plugin(kmm_handle_from_plugin(pd)); kmq_post_message(KMSG_KMM, KMSG_KMM_I_REG, KMM_REG_INIT_PLUGIN, (void *) pd); } } } while(FALSE); LeaveCriticalSection(&cs_kmm); kmmint_remove_from_plugin_queue(p); /* main message loop */ while(KHM_SUCCEEDED(kmq_dispatch(INFINITE))); /* unsubscribe from default message classes by plugin type */ if(p->p.type == KHM_PITYPE_CRED) { kmq_unsubscribe(KMSG_SYSTEM, p->p.msg_proc); kmq_unsubscribe(KMSG_KCDB, p->p.msg_proc); kmq_unsubscribe(KMSG_CRED, p->p.msg_proc); } else if (p->p.type == KHM_PITYPE_IDENT) { kmq_unsubscribe(KMSG_KCDB, p->p.msg_proc); kmq_unsubscribe(KMSG_SYSTEM, p->p.msg_proc); kcdb_identity_set_provider(NULL); } else if(p->p.type == KHM_PITYPE_CONFIG) { /*TODO: unsubscribe from configuration provider messages here */ } p->p.msg_proc(KMSG_SYSTEM, KMSG_SYSTEM_EXIT, 0, (void *) &(p->p)); _exit: if (p->state >= 0) p->state = KMM_PLUGIN_STATE_EXITED; /* the following call will automatically release the plugin */ kmq_post_message(KMSG_KMM, KMSG_KMM_I_REG, KMM_REG_EXIT_PLUGIN, (void *) p); TlsSetValue(tls_kmm, (LPVOID) 0); ExitThread(rv); /* not reached */ return rv; }
static void add_subpanels(HWND hwnd, khui_config_node ctx_node, khui_config_node ref_node) { HWND hw_tab; HWND hw_target; khui_config_node sub; khui_config_node_reg reg; khui_config_init_data idata; int idx; hw_tab = GetDlgItem(hwnd, IDC_CFG_TAB); hw_target = GetDlgItem(hwnd, IDC_CFG_TARGET); #ifdef DEBUG assert(hw_tab); assert(hw_target); #endif if (KHM_FAILED(khui_cfg_get_first_subpanel(ref_node, &sub))) { #ifdef DEBUG assert(FALSE); #endif return; } idx = 0; while(sub) { HWND hwnd_panel; TCITEM tci; int iid; khui_cfg_get_reg(sub, ®); if ((ctx_node == ref_node && (reg.flags & KHUI_CNFLAG_PLURAL)) || (ctx_node != ref_node && !(reg.flags & KHUI_CNFLAG_PLURAL))) goto _next_node; idata.ctx_node = ctx_node; idata.this_node = sub; idata.ref_node = ref_node; hwnd_panel = CreateDialogParam(reg.h_module, reg.dlg_template, hwnd, reg.dlg_proc, (LPARAM) &idata); #ifdef DEBUG assert(hwnd_panel); #endif ShowWindow(hwnd_panel, SW_HIDE); ZeroMemory(&tci, sizeof(tci)); tci.mask = TCIF_PARAM | TCIF_TEXT; tci.lParam = (LPARAM) sub; tci.pszText = (LPWSTR) reg.short_desc; iid = TabCtrl_InsertItem(hw_tab, 0, &tci); idx++; if (reg.flags & KHUI_CNFLAG_PLURAL) { khui_cfg_set_param_inst(sub, ctx_node, iid); khui_cfg_set_hwnd_inst(sub, ctx_node, hwnd_panel); } else { khui_cfg_set_param(sub, iid); khui_cfg_set_hwnd(sub, hwnd_panel); } _next_node: khui_cfg_get_next_release(&sub); } TabCtrl_SetCurSel(hw_tab, 0); }
/* Handler for system messages. The only two we handle are KMSG_SYSTEM_INIT and KMSG_SYSTEM_EXIT. */ khm_int32 KHMAPI handle_kmsg_system(khm_int32 msg_type, khm_int32 msg_subtype, khm_ui_4 uparam, void * vparam) { khm_int32 rv = KHM_ERROR_SUCCESS; switch (msg_subtype) { /* This is the first message that will be received by a plugin. We use it to perform initialization operations such as registering any credential types, data types and attributes. */ case KMSG_SYSTEM_INIT: { kcdb_credtype ct; wchar_t short_desc[KCDB_MAXCCH_SHORT_DESC]; wchar_t long_desc[KCDB_MAXCCH_LONG_DESC]; khui_config_node cnode; khui_config_node_reg creg; kcdb_attrib attr; khm_handle csp_plugin = NULL; khm_handle csp_plugins = NULL; #ifdef BUILD_KRBCOMPAT /* If we don't have a Kerberos backend, then we can't * function. */ if (!DelayLoadHeimdal()) { _reportf("Can't initialize a Kerberos backend. LastError=%d", GetLastError()); return KHM_ERROR_NOT_FOUND; } #endif #if KH_VERSION_API < 12 do { khm_version libver; khm_ui_4 apiver; khm_get_lib_version(&libver, &apiver); if (apiver < 7) break; hm_netidmgr = LoadLibrary(NIMDLLNAME); if (hm_netidmgr == NULL) break; #if KH_VERSION_API < 7 pkhui_action_lock = (void (KHMAPI *)(void)) GetProcAddress(hm_netidmgr, API_khui_action_lock); pkhui_action_unlock = (void (KHMAPI *)(void)) GetProcAddress(hm_netidmgr, API_khui_action_unlock); pkhui_refresh_actions = (void (KHMAPI *)(void)) GetProcAddress(hm_netidmgr, API_khui_refresh_actions); pkhui_request_UI_callback = (khm_int32 (KHMAPI *)(khm_ui_callback, void *)) GetProcAddress(hm_netidmgr, API_khui_request_UI_callback); #endif pkhui_cw_get_primary_id = (khm_int32 (KHMAPI *)(khui_new_creds *, khm_handle *)) GetProcAddress(hm_netidmgr, API_khui_cw_get_primary_id); pkhui_cw_get_result = (khm_int32 (KHMAPI *)(khui_new_creds *)) GetProcAddress(hm_netidmgr, API_khui_cw_get_result); pkhui_cw_get_subtype = (khui_nc_subtype (KHMAPI *)(khui_new_creds *)) GetProcAddress(hm_netidmgr, API_khui_cw_get_subtype); pkhui_cw_get_ctx = (khui_action_context * (KHMAPI *)(khui_new_creds *)) GetProcAddress(hm_netidmgr, API_khui_cw_get_ctx); pkcdb_get_resource = (khm_int32 (KHMAPI *)(khm_handle, kcdb_resource_id, khm_int32, khm_int32 *, void *, void *, khm_size *)) GetProcAddress(hm_netidmgr, API_kcdb_get_resource); } while (FALSE); if (pkhui_cw_get_primary_id == NULL) pkhui_cw_get_primary_id = int_khui_cw_get_primary_id; if (pkhui_cw_get_result == NULL) pkhui_cw_get_result = int_khui_cw_get_result; if (pkhui_cw_get_subtype == NULL) pkhui_cw_get_subtype = int_khui_cw_get_subtype; if (pkhui_cw_get_ctx == NULL) pkhui_cw_get_ctx = int_khui_cw_get_ctx; if (pkcdb_get_resource == NULL) pkcdb_get_resource = int_kcdb_get_resource; #endif /* Add the icon now. On NIM v2.x, doing so after tokens were reported may result in a deadlock as we try to switch to the UI thread and the UI thread is blocked on a resource request to this plug-in. */ kca_icon_set_state(NULL); /* First and foremost, we need to register a credential type. */ ZeroMemory(&ct, sizeof(ct)); ct.id = KCDB_CREDTYPE_AUTO; ct.name = MYCREDTYPE_NAMEW; ct.short_desc = short_desc; ct.long_desc = long_desc; short_desc[0] = L'\0'; LoadString(hResModule, IDS_CT_SHORT_DESC, short_desc, ARRAYLENGTH(short_desc)); long_desc[0] = L'\0'; LoadString(hResModule, IDS_CT_LONG_DESC, long_desc, ARRAYLENGTH(long_desc)); ct.icon = NULL; /* We skip the icon for now, but you can assign a handle to an icon here. The icon will be used to represent the credentials type.*/ kmq_create_subscription(plugin_msg_proc, &ct.sub); ct.is_equal = cred_is_equal; rv = kcdb_credtype_register(&ct, &credtype_id); /* We create a global credential set that we use in the plug-in thread. This alleviates the need to create one everytime we need one. Keep in mind that this should only be used in the plug-in thread and should not be touched from the UI thread or any other thread. */ kcdb_credset_create(&g_credset); /* TODO: Perform additional initialization operations. */ /* Register our attributes */ ZeroMemory(&attr, sizeof(attr)); attr.name = ATTRNAME_KCA_AUTHREALM; attr.id = KCDB_ATTR_INVALID; attr.alt_id = KCDB_ATTR_INVALID; attr.flags = 0; attr.type = KCDB_TYPE_STRING; attr.short_desc = short_desc; attr.long_desc = long_desc; attr.compute_cb = NULL; attr.compute_min_cbsize = 0; attr.compute_max_cbsize = 0; LoadString(hResModule, IDS_ATTR_REALM_SHORT_DESC, short_desc, ARRAYLENGTH(short_desc)); LoadString(hResModule, IDS_ATTR_REALM_LONG_DESC, long_desc, ARRAYLENGTH(long_desc)); rv = kcdb_attrib_register(&attr, &attr_id_auth_realm); if (KHM_FAILED(rv)) break; attr.name = ATTRNAME_SUBJECT_EMAIL; LoadString(hResModule, IDS_ATTR_SUBJECT_EMAIL_SHORT_DESC, short_desc, ARRAYLENGTH(short_desc)); LoadString(hResModule, IDS_ATTR_SUBJECT_EMAIL_LONG_DESC, long_desc, ARRAYLENGTH(long_desc)); rv = kcdb_attrib_register(&attr, &attr_id_subj_email); if (KHM_FAILED(rv)) break; attr.name = ATTRNAME_SUBJECT_DISPLAY; LoadString(hResModule, IDS_ATTR_SUBJECT_SHORT_DESC, short_desc, ARRAYLENGTH(short_desc)); LoadString(hResModule, IDS_ATTR_SUBJECT_LONG_DESC, long_desc, ARRAYLENGTH(long_desc)); rv = kcdb_attrib_register(&attr, &attr_id_subj_display); if (KHM_FAILED(rv)) break; attr.name = ATTRNAME_ISSUER_DISPLAY; LoadString(hResModule, IDS_ATTR_ISSUER_SHORT_DESC, short_desc, ARRAYLENGTH(short_desc)); LoadString(hResModule, IDS_ATTR_ISSUER_LONG_DESC, long_desc, ARRAYLENGTH(long_desc)); rv = kcdb_attrib_register(&attr, &attr_id_issuer_display); if (KHM_FAILED(rv)) break; attr.name = ATTRNAME_ISSUER_NAME; attr.flags = KCDB_ATTR_FLAG_HIDDEN; attr.type = KCDB_TYPE_DATA; attr.short_desc = NULL; attr.long_desc = NULL; rv = kcdb_attrib_register(&attr, &attr_id_issuer_name); if (KHM_FAILED(rv)) break; attr.name = ATTRNAME_SERIAL; rv = kcdb_attrib_register(&attr, &attr_id_serial_number); if (KHM_FAILED(rv)) break; /* List the credentials that are already here */ kca_list_creds(); /* Now we register our configuration panels. */ #ifdef GENERAL_CONFIG_PANEL /* This configuration panel is the one that controls general options. We leave the identity specific and identity defaults for other configuration panels. */ ZeroMemory(&creg, sizeof(creg)); short_desc[0] = L'\0'; LoadString(hResModule, IDS_CFG_SHORT_DESC, short_desc, ARRAYLENGTH(short_desc)); long_desc[0] = L'\0'; LoadString(hResModule, IDS_CFG_LONG_DESC, long_desc, ARRAYLENGTH(long_desc)); creg.name = CONFIGNODE_MAIN; creg.short_desc = short_desc; creg.long_desc = long_desc; creg.h_module = hResModule; creg.dlg_template = MAKEINTRESOURCE(IDD_CONFIG); creg.dlg_proc = config_dlgproc; creg.flags = 0; khui_cfg_register(NULL, &creg); #endif /* Now we do the identity specific and identity default configuration panels. "KhmIdentities" is a predefined configuration node under which all the identity spcific configuration is managed. */ if (KHM_FAILED(khui_cfg_open(NULL, L"KhmIdentities", &cnode))) { /* this should always work */ assert(FALSE); rv = KHM_ERROR_NOT_FOUND; break; } /* First the tab panel for defaults for all identities */ ZeroMemory(&creg, sizeof(creg)); short_desc[0] = L'\0'; LoadString(hResModule, IDS_CFG_IDS_SHORT_DESC, short_desc, ARRAYLENGTH(short_desc)); long_desc[0] = L'\0'; LoadString(hResModule, IDS_CFG_IDS_LONG_DESC, long_desc, ARRAYLENGTH(long_desc)); creg.name = CONFIGNODE_ALL_ID; creg.short_desc = short_desc; creg.long_desc = long_desc; creg.h_module = hResModule; creg.dlg_template = MAKEINTRESOURCE(IDD_CONFIG_IDS); creg.dlg_proc = config_ids_dlgproc; creg.flags = KHUI_CNFLAG_SUBPANEL; khui_cfg_register(cnode, &creg); /* Now the panel for per identity configuration */ ZeroMemory(&creg, sizeof(creg)); short_desc[0] = L'\0'; LoadString(hResModule, IDS_CFG_ID_SHORT_DESC, short_desc, ARRAYLENGTH(short_desc)); long_desc[0] = L'\0'; LoadString(hResModule, IDS_CFG_ID_LONG_DESC, long_desc, ARRAYLENGTH(long_desc)); creg.name = CONFIGNODE_PER_ID; creg.short_desc = short_desc; creg.long_desc = long_desc; creg.h_module = hResModule; creg.dlg_template = MAKEINTRESOURCE(IDD_CONFIG_ID); creg.dlg_proc = config_id_dlgproc; creg.flags = KHUI_CNFLAG_SUBPANEL | KHUI_CNFLAG_INSTANCE; khui_cfg_register(cnode, &creg); khui_cfg_release(cnode); /* load the schema */ if (KHM_SUCCEEDED(kmm_get_plugins_config(0, &csp_plugins))) { khc_load_schema(csp_plugins, plugin_schema); khc_close_space(csp_plugins); } /* open the plug-in and parameter configuration spaces */ if (KHM_SUCCEEDED(kmm_get_plugin_config(MYPLUGIN_NAMEW, KHM_FLAG_CREATE, &csp_plugin))) { khc_open_space(csp_plugin, L"Parameters", KHM_FLAG_CREATE, &csp_params); khc_close_space(csp_plugin); } /* try to install the kpkcs11 plugin now */ install_kpkcs11_plugin(); /* register the "KCA Help" menu item, so that we can add the plug-in menu item to the Help menu. */ { khm_handle h_sub = NULL; #if KH_VERSION_API < 7 if (pkhui_action_lock == NULL || pkhui_action_unlock == NULL || pkhui_refresh_actions == NULL || pkhui_request_UI_callback == NULL) goto no_custom_help; #endif kmq_create_subscription(plugin_msg_proc, &h_sub); LoadString(hResModule, IDS_ACTION_KCA_HELP, short_desc, ARRAYLENGTH(short_desc)); LoadString(hResModule, IDS_ACTION_KCA_HELP_TT, long_desc, ARRAYLENGTH(long_desc)); action_id_kca_help = khui_action_create(NULL, short_desc, long_desc, NULL, KHUI_ACTIONTYPE_TRIGGER, h_sub); if (action_id_kca_help != 0) { khm_size s; khm_size i; khui_menu_def * help_menu; khm_boolean refresh = FALSE; khui_action_lock(); help_menu = khui_find_menu(KHUI_MENU_HELP); if (help_menu) { s = khui_menu_get_size(help_menu); for (i=0; i < s; i++) { khui_action_ref * aref; aref = khui_menu_get_action(help_menu, i); if (aref && !(aref->flags & KHUI_ACTIONREF_PACTION) && aref->action == KHUI_ACTION_HELP_INDEX) { khui_menu_insert_action(help_menu, i + 1, action_id_kca_help, 0); refresh = TRUE; break; } } } khui_action_unlock(); if (refresh) khui_refresh_actions(); } #if KH_VERSION_API < 7 no_custom_help: ; #endif } } break; /* This is the last message that will be received by the plugin. */ case KMSG_SYSTEM_EXIT: { khui_config_node cnode; khui_config_node cn_idents; khm_int32 attr_id; kca_remove_icon(); /* It should not be assumed that initialization of the plugin went well at this point since we receive a KMSG_SYSTEM_EXIT even if the initialization failed. */ /* Try to remove the KCA plug-in action from Help menu if it was successfully registered. Also, delete the action. */ if (action_id_kca_help != 0) { khui_menu_def * help_menu; khm_boolean menu_changed = FALSE; khui_action_lock(); help_menu = khui_find_menu(KHUI_MENU_HELP); if (help_menu) { khm_size s; khm_size i; s = khui_menu_get_size(help_menu); for (i=0; i < s; i++) { khui_action_ref * aref = khui_menu_get_action(help_menu, i); if (aref && !(aref->flags & KHUI_ACTIONREF_PACTION) && aref->action == action_id_kca_help) { khui_menu_remove_action(help_menu, i); menu_changed = TRUE; break; } } } khui_action_delete(action_id_kca_help); khui_action_unlock(); if (menu_changed) khui_refresh_actions(); action_id_kca_help = 0; } if (credtype_id != KCDB_CREDTYPE_INVALID) { kcdb_credtype_unregister(credtype_id); credtype_id = KCDB_CREDTYPE_INVALID; } if (g_credset) { kcdb_credset_delete(g_credset); g_credset = NULL; } /* Now unregister any configuration nodes we registered. */ if (KHM_SUCCEEDED(khui_cfg_open(NULL, CONFIGNODE_MAIN, &cnode))) { khui_cfg_remove(cnode); khui_cfg_release(cnode); } if (KHM_SUCCEEDED(khui_cfg_open(NULL, L"KhmIdentities", &cn_idents))) { if (KHM_SUCCEEDED(khui_cfg_open(cn_idents, CONFIGNODE_ALL_ID, &cnode))) { khui_cfg_remove(cnode); khui_cfg_release(cnode); } if (KHM_SUCCEEDED(khui_cfg_open(cn_idents, CONFIGNODE_PER_ID, &cnode))) { khui_cfg_remove(cnode); khui_cfg_release(cnode); } khui_cfg_release(cn_idents); } if (KHM_SUCCEEDED(kcdb_attrib_get_id(ATTRNAME_KCA_AUTHREALM, &attr_id))) kcdb_attrib_unregister(attr_id); if (KHM_SUCCEEDED(kcdb_attrib_get_id(ATTRNAME_SUBJECT_EMAIL, &attr_id))) kcdb_attrib_unregister(attr_id); if (KHM_SUCCEEDED(kcdb_attrib_get_id(ATTRNAME_SUBJECT_DISPLAY, &attr_id))) kcdb_attrib_unregister(attr_id); if (KHM_SUCCEEDED(kcdb_attrib_get_id(ATTRNAME_ISSUER_DISPLAY, &attr_id))) kcdb_attrib_unregister(attr_id); if (KHM_SUCCEEDED(kcdb_attrib_get_id(ATTRNAME_ISSUER_NAME, &attr_id))) kcdb_attrib_unregister(attr_id); if (KHM_SUCCEEDED(kcdb_attrib_get_id(ATTRNAME_SERIAL, &attr_id))) kcdb_attrib_unregister(attr_id); if (csp_params) { khc_close_space(csp_params); csp_params = NULL; } #if KH_VERSION_API < 12 if (hm_netidmgr) FreeLibrary(hm_netidmgr); pkhui_cw_get_primary_id = NULL; #endif #if KH_VERSION_API < 7 pkhui_action_lock = NULL; pkhui_action_unlock = NULL; pkhui_refresh_actions = NULL; pkhui_request_UI_callback = NULL; #endif /* TODO: Perform additional uninitialization operations. */ } break; } return rv; }