void k5_read_file_cc_data(k5_ccc_data * d) { khm_int32 t; wchar_t * fclist = NULL; wchar_t * fc; khm_size cb; #ifdef DEBUG assert(csp_params); #endif d->inc_api = TRUE; t = TRUE; khc_read_int32(csp_params, L"MsLsaList", &t); d->inc_mslsa = t; if (khc_read_multi_string(csp_params, L"FileCCList", NULL, &cb) != KHM_ERROR_TOO_LONG || cb <= sizeof(wchar_t) * 2) { k5_flush_file_ccs(d); } else { fclist = PMALLOC(cb); #ifdef DEBUG assert(fclist); #endif khc_read_multi_string(csp_params, L"FileCCList", fclist, &cb); for(fc = fclist; fc && *fc; fc = multi_string_next(fc)) { k5_add_file_cc(d, fc); } PFREE(fclist); } }
/* called with cs_identpro held */ static void identpro_check_and_set_default_provider(void) { wchar_t * p_order = NULL; khm_size cb; khm_handle csp_kcdb = NULL; khm_int32 rv; kcdb_identpro_i * p = NULL; wchar_t * e; if (KHM_SUCCEEDED(khc_open_space(NULL, L"KCDB", KHM_PERM_READ, &csp_kcdb))) { rv = khc_read_multi_string(csp_kcdb, L"IdentityProviderOrder", NULL, &cb); if (rv == KHM_ERROR_TOO_LONG && cb > sizeof(wchar_t) * 2) { p_order = PMALLOC(cb); rv = khc_read_multi_string(csp_kcdb, L"IdentityProviderOrder", p_order, &cb); if (KHM_FAILED(rv)) { PFREE(p_order); p_order = NULL; } } khc_close_space(csp_kcdb); csp_kcdb = NULL; } for (e = p_order; e && e[0]; e = multi_string_next(e)) { p = identpro_find_by_name(e); if (p) break; } if (p != NULL) { if (DEFAULT_PROVIDER != p) { QDEL(&id_providers, p); QPUSH(&id_providers, p); #ifdef DEBUG assert(DEFAULT_PROVIDER == p); #endif kcdbint_identpro_post_message(KCDB_OP_NEW_DEFAULT, DEFAULT_PROVIDER); } } if (p) identpro_release(p); if (p_order) PFREE(p_order); }
void k5_write_file_cc_data(k5_ccc_data * d) { wchar_t * ms; khm_size cb; khm_size cbt; khm_int32 t; khm_size i; #ifdef DEBUG assert(csp_params); #endif if (KHM_FAILED(khc_read_int32(csp_params, L"MsLsaList", &t)) || !!t != !!d->inc_mslsa) { khc_write_int32(csp_params, L"MsLsaList", !!d->inc_mslsa); } if (d->n_file_ccs > 0) { cb = d->n_file_ccs * MAX_PATH * sizeof(wchar_t); ms = PMALLOC(cb); #ifdef DEBUG assert(ms); #endif multi_string_init(ms, cb); for(i=0; i<d->n_file_ccs; i++) { cbt = cb; multi_string_append(ms, &cbt, d->file_ccs[i].path); } khc_write_multi_string(csp_params, L"FileCCList", ms); PFREE(ms); } else { if (khc_read_multi_string(csp_params, L"FileCCList", NULL, &cb) != KHM_ERROR_TOO_LONG || cb != sizeof(wchar_t) * 2) khc_write_multi_string(csp_params, L"FileCCList", L"\0\0"); } }
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; }
/*! \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 }
khm_int32 KHMAPI khm_krb5_find_ccache_for_identity(khm_handle ident, krb5_context *pctx, void * buffer, khm_size * pcbbuf) { krb5_context ctx = 0; krb5_ccache cache = 0; krb5_error_code code; apiCB * cc_ctx = 0; struct _infoNC ** pNCi = NULL; int i; khm_int32 t; wchar_t * ms = NULL; khm_size cb; krb5_timestamp expiration = 0; krb5_timestamp best_match_expiration = 0; char best_match_ccname[256] = ""; khm_handle csp_params = NULL; khm_handle csp_plugins = NULL; if (!buffer || !pcbbuf) return KHM_ERROR_GENERAL; ctx = *pctx; if (!pcc_initialize || !pcc_get_NC_info || !pcc_free_NC_info || !pcc_shutdown) goto _skip_cc_iter; code = pcc_initialize(&cc_ctx, CC_API_VER_2, NULL, NULL); if (code) goto _exit; code = pcc_get_NC_info(cc_ctx, &pNCi); if (code) goto _exit; for(i=0; pNCi[i]; i++) { if (pNCi[i]->vers != CC_CRED_V5) continue; code = (*pkrb5_cc_resolve)(ctx, pNCi[i]->name, &cache); if (code) continue; /* need a function to check the cache for the identity * and determine if it has valid tickets. If it has * the right identity and valid tickets, store the * expiration time and the cache name. If it has the * right identity but no valid tickets, store the ccache * name and an expiration time of zero. if it does not * have the right identity don't save the name. * * Keep searching to find the best cache available. */ if (KHM_SUCCEEDED(khm_get_identity_expiration_time(ctx, cache, ident, &expiration))) { if ( expiration > best_match_expiration ) { best_match_expiration = expiration; StringCbCopyA(best_match_ccname, sizeof(best_match_ccname), "API:"); StringCbCatA(best_match_ccname, sizeof(best_match_ccname), pNCi[i]->name); expiration = 0; } } if(ctx != NULL && cache != NULL) (*pkrb5_cc_close)(ctx, cache); cache = 0; } _skip_cc_iter: if (KHM_SUCCEEDED(kmm_get_plugins_config(0, &csp_plugins))) { khc_open_space(csp_plugins, L"Krb5Cred\\Parameters", 0, &csp_params); khc_close_space(csp_plugins); csp_plugins = NULL; } #ifdef DEBUG if (csp_params == NULL) { assert(FALSE); } #endif if (csp_params && KHM_SUCCEEDED(khc_read_int32(csp_params, L"MsLsaList", &t)) && t) { code = (*pkrb5_cc_resolve)(ctx, "MSLSA:", &cache); if (code == 0 && cache) { if (KHM_SUCCEEDED(khm_get_identity_expiration_time(ctx, cache, ident, &expiration))) { if ( expiration > best_match_expiration ) { best_match_expiration = expiration; StringCbCopyA(best_match_ccname, sizeof(best_match_ccname), "MSLSA:"); expiration = 0; } } } if (ctx != NULL && cache != NULL) (*pkrb5_cc_close)(ctx, cache); cache = 0; } if (csp_params && khc_read_multi_string(csp_params, L"FileCCList", NULL, &cb) == KHM_ERROR_TOO_LONG && cb > sizeof(wchar_t) * 2) { wchar_t * t; char ccname[MAX_PATH + 6]; ms = PMALLOC(cb); #ifdef DEBUG assert(ms); #endif khc_read_multi_string(csp_params, L"FileCCList", ms, &cb); for(t = ms; t && *t; t = multi_string_next(t)) { StringCchPrintfA(ccname, ARRAYLENGTH(ccname), "FILE:%S", t); code = (*pkrb5_cc_resolve)(ctx, ccname, &cache); if (code) continue; if (KHM_SUCCEEDED(khm_get_identity_expiration_time(ctx, cache, ident, &expiration))) { if ( expiration > best_match_expiration ) { best_match_expiration = expiration; StringCbCopyA(best_match_ccname, sizeof(best_match_ccname), ccname); expiration = 0; } } if (ctx != NULL && cache != NULL) (*pkrb5_cc_close)(ctx, cache); cache = 0; } PFREE(ms); } _exit: if (csp_params) khc_close_space(csp_params); if (pNCi) (*pcc_free_NC_info)(cc_ctx, &pNCi); if (cc_ctx) (*pcc_shutdown)(&cc_ctx); if (best_match_ccname[0]) { if (*pcbbuf = AnsiStrToUnicode((wchar_t *)buffer, *pcbbuf, best_match_ccname)) { *pcbbuf = (*pcbbuf + 1) * sizeof(wchar_t); return KHM_ERROR_SUCCESS; } } return KHM_ERROR_GENERAL; }