KHMEXP khm_int32 KHMAPI kcdb_credset_flush(khm_handle vcredset) { int i; kcdb_credset * cs; if(!kcdb_credset_is_credset(vcredset)) return KHM_ERROR_INVALID_PARAM; cs = (kcdb_credset *) vcredset; if (kcdb_credset_is_sealed(cs)) return KHM_ERROR_INVALID_OPERATION; EnterCriticalSection(&(cs->cs)); #ifdef DEBUG assert(!(cs->flags & KCDB_CREDSET_FLAG_ENUM)); #endif for(i=0;i<cs->nclist;i++) { if(cs->clist[i].cred) { kcdb_cred_release((khm_handle) cs->clist[i].cred); } } cs->nclist = 0; LeaveCriticalSection(&(cs->cs)); return KHM_ERROR_SUCCESS; }
KHMEXP khm_int32 KHMAPI kcdb_credset_get_cred(khm_handle vcredset, khm_int32 idx, khm_handle * cred) { kcdb_credset * cs; khm_int32 code = KHM_ERROR_SUCCESS; if(!kcdb_credset_is_credset(vcredset)) return KHM_ERROR_INVALID_PARAM; cs = (kcdb_credset *) vcredset; *cred = NULL; EnterCriticalSection(&(cs->cs)); if(idx < 0 || idx >= cs->nclist) code = KHM_ERROR_OUT_OF_BOUNDS; else if(!cs->clist[idx].cred || !kcdb_cred_is_active_cred((khm_handle) cs->clist[idx].cred)) { code = KHM_ERROR_DELETED; if(cs->clist[idx].cred) { kcdb_cred_release((khm_handle) cs->clist[idx].cred); cs->clist[idx].cred = NULL; } } else { kcdb_cred_hold((khm_handle) cs->clist[idx].cred); *cred = cs->clist[idx].cred; } LeaveCriticalSection(&(cs->cs)); return code; }
KHMEXP khm_int32 KHMAPI kcdb_credset_delete(khm_handle vcredset) { kcdb_credset * cs; int i; if(!kcdb_credset_is_credset(vcredset)) { return KHM_ERROR_INVALID_PARAM; } cs = (kcdb_credset *) vcredset; EnterCriticalSection(&cs_credset); LDELETE(&kcdb_credsets, cs); LeaveCriticalSection(&cs_credset); EnterCriticalSection(&(cs->cs)); cs->magic = 0; for(i=0;i<cs->nclist;i++) { if(cs->clist[i].cred) { kcdb_cred_release((khm_handle) cs->clist[i].cred); } } kcdb_credset_buf_delete(cs); LeaveCriticalSection(&(cs->cs)); DeleteCriticalSection(&(cs->cs)); PFREE(cs); return KHM_ERROR_SUCCESS; }
KHMEXP khm_int32 KHMAPI kcdb_buf_release(khm_handle record) { if(kcdb_cred_is_active_cred(record)) return kcdb_cred_release(record); else if(kcdb_is_active_identity(record)) return kcdb_identity_release(record); else return KHM_ERROR_INVALID_PARAM; }
KHMEXP khm_int32 KHMAPI kcdb_credset_del_cred(khm_handle vcredset, khm_int32 idx) { kcdb_credset * cs; khm_int32 code = KHM_ERROR_SUCCESS; if(!kcdb_credset_is_credset(vcredset)) return KHM_ERROR_INVALID_PARAM; cs = (kcdb_credset *) vcredset; if (kcdb_credset_is_sealed(cs)) return KHM_ERROR_INVALID_OPERATION; EnterCriticalSection(&(cs->cs)); if(idx < 0 || idx >= cs->nclist) { code = KHM_ERROR_INVALID_PARAM; goto _exit; } if(cs->clist[idx].cred) kcdb_cred_release((khm_handle) cs->clist[idx].cred); if (!(cs->flags & KCDB_CREDSET_FLAG_ENUM)) { if(idx + 1 < cs->nclist) memmove(&(cs->clist[idx]), &(cs->clist[idx+1]), sizeof(kcdb_credset_credref) * (cs->nclist - (idx + 1))); cs->nclist--; } else { cs->clist[idx].cred = NULL; } _exit: LeaveCriticalSection(&(cs->cs)); return code; }
KHMEXP khm_int32 KHMAPI kcdb_credset_find_cred(khm_handle vcredset, khm_handle vcred_src, khm_handle *cred_dest) { kcdb_credset * cs; khm_handle cred = NULL; int idx; if (!kcdb_credset_is_credset(vcredset)) return KHM_ERROR_INVALID_PARAM; if (!kcdb_cred_is_active_cred(vcred_src)) return KHM_ERROR_INVALID_PARAM; cs = (kcdb_credset *) vcredset; EnterCriticalSection(&cs->cs); for (idx = 0; idx < cs->nclist; idx++) { if (cs->clist[idx].cred && kcdb_creds_is_equal(vcred_src, cs->clist[idx].cred)) { cred = cs->clist[idx].cred; break; } } if (cred) kcdb_cred_hold(cred); LeaveCriticalSection(&cs->cs); if (cred) { if (cred_dest) *cred_dest = cred; else kcdb_cred_release(cred); return KHM_ERROR_SUCCESS; } else { return KHM_ERROR_NOT_FOUND; } }
KHMEXP khm_int32 KHMAPI kcdb_credset_purge(khm_handle credset) { khm_int32 code = KHM_ERROR_SUCCESS; kcdb_credset * cs; int i,j; if(!kcdb_credset_is_credset(credset)) return KHM_ERROR_INVALID_PARAM; cs = (kcdb_credset *) credset; if (kcdb_credset_is_sealed(cs)) return KHM_ERROR_INVALID_OPERATION; EnterCriticalSection(&(cs->cs)); /* we can't purge a credset while an enumeration operation is in progress. */ if (cs->flags & KCDB_CREDSET_FLAG_ENUM) { code = KHM_ERROR_INVALID_OPERATION; goto _exit; } for(i=0,j=0; i < cs->nclist; i++) { if(cs->clist[i].cred) { if(!kcdb_cred_is_active_cred((khm_handle) cs->clist[i].cred)) { kcdb_cred_release((khm_handle) cs->clist[i].cred); } else if(i != j) { cs->clist[j++] = cs->clist[i]; } else j++; } } cs->nclist = j; _exit: LeaveCriticalSection(&(cs->cs)); return code; }
khm_int32 krb4_msg_newcred(khm_int32 msg_type, khm_int32 msg_subtype, khm_ui_4 uparam, void * vparam) { switch(msg_subtype) { case KMSG_CRED_NEW_CREDS: { khui_new_creds * nc; khui_new_creds_by_type * nct; khm_size cbsize; wchar_t wbuf[256]; nc = (khui_new_creds *) vparam; nct = PMALLOC(sizeof(*nct)); #ifdef DEBUG assert(nct); #endif ZeroMemory(nct, sizeof(*nct)); nct->type = credtype_id_krb4; nct->ordinal = 3; LoadString(hResModule, IDS_NC_K4_SHORT, wbuf, ARRAYLENGTH(wbuf)); StringCbLength(wbuf, sizeof(wbuf), &cbsize); cbsize += sizeof(wchar_t); nct->name = PMALLOC(cbsize); StringCbCopy(nct->name, cbsize, wbuf); nct->type_deps[nct->n_type_deps++] = credtype_id_krb5; nct->h_module = hResModule; nct->dlg_proc = k4_nc_dlg_proc; nct->dlg_template = MAKEINTRESOURCE(IDD_NC_KRB4); khui_cw_add_type(nc, nct); } break; case KMSG_CRED_RENEW_CREDS: { khui_new_creds * nc; khui_new_creds_by_type * nct; khm_size cbsize; wchar_t wbuf[256]; khui_action_context * pctx = NULL; nc = (khui_new_creds *) vparam; pctx = khui_cw_get_ctx(nc); if (!pctx->identity) break; nct = PMALLOC(sizeof(*nct)); #ifdef DEBUG assert(nct); #endif ZeroMemory(nct, sizeof(*nct)); nct->type = credtype_id_krb4; nct->ordinal = 3; LoadString(hResModule, IDS_NC_K4_SHORT, wbuf, ARRAYLENGTH(wbuf)); StringCbLength(wbuf, sizeof(wbuf), &cbsize); cbsize += sizeof(wchar_t); nct->name = PMALLOC(cbsize); StringCbCopy(nct->name, cbsize, wbuf); nct->type_deps[nct->n_type_deps++] = credtype_id_krb5; khui_cw_add_type(nc, nct); } break; case KMSG_CRED_DIALOG_SETUP: break; case KMSG_CRED_PROCESS: { khui_new_creds * nc; khui_new_creds_by_type * nct = NULL; khm_handle ident = NULL; khui_action_context * pctx = NULL; k4_dlg_data * d = NULL; long code = 0; wchar_t idname[KCDB_IDENT_MAXCCH_NAME]; khm_size cb; khm_int32 subtype; nc = (khui_new_creds *) vparam; if (KHM_FAILED(khui_cw_find_type(nc, credtype_id_krb4, &nct))) break; subtype = khui_cw_get_subtype(nc); if (subtype == KMSG_CRED_NEW_CREDS || subtype == KMSG_CRED_RENEW_CREDS) { khm_int32 method; if (subtype == KMSG_CRED_NEW_CREDS) { d = (k4_dlg_data *) nct->aux; if (KHM_FAILED(khui_cw_get_primary_id(nc, &ident))) break; if (!d || khui_cw_get_result(nc) != KHUI_NC_RESULT_PROCESS) { khui_cw_set_response(nc, credtype_id_krb4, KHUI_NC_RESPONSE_SUCCESS | KHUI_NC_RESPONSE_EXIT); kcdb_identity_release(ident); break; } if (!d->k4_enabled) { k4_write_identity_data(d); khui_cw_set_response(nc, credtype_id_krb4, KHUI_NC_RESPONSE_SUCCESS | KHUI_NC_RESPONSE_EXIT); kcdb_identity_release(ident); break; } method = d->method; cb = sizeof(idname); kcdb_identity_get_name(ident, idname, &cb); _begin_task(0); _report_sr0(KHERR_NONE, IDS_MSG_K4NEW); _resolve(); _describe(); } else if (subtype == KMSG_CRED_RENEW_CREDS) { pctx = khui_cw_get_ctx(nc); if ((pctx->scope == KHUI_SCOPE_IDENT && pctx->identity != NULL) || (pctx->scope == KHUI_SCOPE_CREDTYPE && pctx->cred_type == credtype_id_krb4 && pctx->identity != NULL) || (pctx->scope == KHUI_SCOPE_CRED && pctx->cred_type == credtype_id_krb4 && pctx->identity != NULL && pctx->cred != NULL)) { ident = pctx->identity; kcdb_identity_hold(ident); if (!k4_should_identity_get_k4(ident)) { _reportf(L"Kerberos 4 is not enabled for this identity. Skipping"); khui_cw_set_response(nc, credtype_id_krb4, KHUI_NC_RESPONSE_FAILED | KHUI_NC_RESPONSE_EXIT); kcdb_identity_release(ident); break; } } else { _reportf(L"Kerberos 4 is not within renewal scope. Skipping"); khui_cw_set_response(nc, credtype_id_krb4, KHUI_NC_RESPONSE_FAILED | KHUI_NC_RESPONSE_EXIT); break; } method = K4_METHOD_K524; /* only k524 is supported for renewals */ _begin_task(0); cb = sizeof(idname); kcdb_identity_get_name(ident, idname, &cb); _report_sr0(KHERR_NONE, IDS_MSG_K4RENEW); _resolve(); _describe(); } else { assert(FALSE); break; } _progress(0,1); if ((method == K4_METHOD_AUTO || method == K4_METHOD_K524) && khui_cw_type_succeeded(nc, credtype_id_krb5)) { khm_handle tgt; FILETIME ft_prev; FILETIME ft_new; khm_size cb; _report_cs0(KHERR_INFO, L"Trying K524..."); tgt = khm_krb4_find_tgt(NULL, ident); _progress(1,3); if (tgt) { cb = sizeof(ft_prev); if (KHM_FAILED(kcdb_cred_get_attr(tgt, KCDB_ATTR_EXPIRE, NULL, &ft_prev, &cb))) ZeroMemory(&ft_prev, sizeof(ft_prev)); kcdb_cred_release(tgt); } code = khm_convert524(ident); _progress(2,3); _reportf(L"khm_convert524 returns code %d", code); if (code == 0) { khui_cw_set_response(nc, credtype_id_krb4, KHUI_NC_RESPONSE_SUCCESS | KHUI_NC_RESPONSE_EXIT); if (subtype == KMSG_CRED_NEW_CREDS) { assert(d != NULL); k4_write_identity_data(d); } else if (subtype == KMSG_CRED_RENEW_CREDS && (pctx->scope == KHUI_SCOPE_CREDTYPE || pctx->scope == KHUI_SCOPE_CRED)) { khm_krb4_list_tickets(); tgt = khm_krb4_find_tgt(NULL, ident); if (tgt) { cb = sizeof(ft_new); ZeroMemory(&ft_new, sizeof(ft_new)); kcdb_cred_get_attr(tgt, KCDB_ATTR_EXPIRE, NULL, &ft_new, &cb); kcdb_cred_release(tgt); } if (!tgt || CompareFileTime(&ft_new, &ft_prev) <= 0) { /* The new TGT wasn't much of an improvement over what we already had. We should go out and try to renew the identity now. */ khui_action_context ctx; _reportf(L"Renewal of Krb4 creds failed to get a longer TGT. Triggering identity renewal"); khui_context_create(&ctx, KHUI_SCOPE_IDENT, pctx->identity, KCDB_CREDTYPE_INVALID, NULL); khui_action_trigger(KHUI_ACTION_RENEW_CRED, &ctx); khui_context_release(&ctx); } } _progress(1,1); _end_task(); if (ident) kcdb_identity_release(ident); break; } else if (method == K4_METHOD_K524) { khui_cw_set_response(nc, credtype_id_krb4, KHUI_NC_RESPONSE_FAILED | KHUI_NC_RESPONSE_EXIT); if (subtype == KMSG_CRED_RENEW_CREDS && (pctx->scope == KHUI_SCOPE_CREDTYPE || pctx->scope == KHUI_SCOPE_CRED)) { /* We were trying to get a new Krb4 TGT for this identity. Sometimes this fails because of restrictions placed on K524d regarding the lifetime of the issued K4 TGT. In this case, we trigger a renewal of the identity in the hope that the new K5 TGT will allow us to successfully get a new K4 TGT next time over using the new K5 TGT. */ khui_action_context ctx; _reportf(L"Renewal of Krb4 creds failed using k524. Triggerring identity renewal."); khui_context_create(&ctx, KHUI_SCOPE_IDENT, pctx->identity, KCDB_CREDTYPE_INVALID, NULL); khui_action_trigger(KHUI_ACTION_RENEW_CRED, &ctx); khui_context_release(&ctx); } _progress(1,1); _end_task(); if (ident) kcdb_identity_release(ident); break; } } /* only supported for new credentials */ if (method == K4_METHOD_AUTO || method == K4_METHOD_PASSWORD) { khm_size n_prompts = 0; khm_size idx; khm_size cb; wchar_t wpwd[KHUI_MAXCCH_PROMPT_VALUE]; char pwd[KHUI_MAXCCH_PROMPT_VALUE]; wchar_t widname[KCDB_IDENT_MAXCCH_NAME]; char idname[KCDB_IDENT_MAXCCH_NAME]; char * aname = NULL; char * inst = NULL; char * realm = NULL; assert(subtype == KMSG_CRED_NEW_CREDS); _report_cs0(KHERR_INFO, L"Trying password ..."); code = TRUE; /* just has to be non-zero */ khui_cw_get_prompt_count(nc, &n_prompts); if (n_prompts == 0) goto _skip_pwd; for (idx = 0; idx < n_prompts; idx++) { khui_new_creds_prompt * p; if (KHM_FAILED(khui_cw_get_prompt(nc, idx, &p))) continue; if (p->type == KHUI_NCPROMPT_TYPE_PASSWORD) break; } if (idx >= n_prompts) { _reportf(L"Password prompt not found"); goto _skip_pwd; } khui_cw_sync_prompt_values(nc); cb = sizeof(wpwd); if (KHM_FAILED(khui_cw_get_prompt_value(nc, idx, wpwd, &cb))) { _reportf(L"Failed to obtain password value"); goto _skip_pwd; } UnicodeStrToAnsi(pwd, sizeof(pwd), wpwd); cb = sizeof(widname); kcdb_identity_get_name(ident, widname, &cb); UnicodeStrToAnsi(idname, sizeof(idname), widname); { char * atsign; atsign = strchr(idname, '@'); if (atsign == NULL) { _reportf(L"Identity name does not contain an '@'"); goto _skip_pwd; } *atsign++ = 0; realm = atsign; } { char * slash; slash = strchr(idname, '/'); if (slash != NULL) { *slash++ = 0; inst = slash; } else { inst = ""; } } aname = idname; code = khm_krb4_kinit(aname, inst, realm, (long) d->lifetime, pwd); _progress(2,3); _reportf(L"khm_krb4_kinit returns code %d", code); _skip_pwd: if (code) { khui_cw_set_response(nc, credtype_id_krb4, KHUI_NC_RESPONSE_EXIT | KHUI_NC_RESPONSE_FAILED); } else { khui_cw_set_response(nc, credtype_id_krb4, KHUI_NC_RESPONSE_EXIT | KHUI_NC_RESPONSE_SUCCESS); if (subtype == KMSG_CRED_NEW_CREDS) { assert(d != NULL); k4_write_identity_data(d); } } } _progress(1,1); _end_task(); } if (ident) kcdb_identity_release(ident); } break; case KMSG_CRED_END: { khui_new_creds * nc; khui_new_creds_by_type * nct = NULL; nc = (khui_new_creds *) vparam; if (KHM_FAILED(khui_cw_find_type(nc, credtype_id_krb4, &nct))) break; khui_cw_del_type(nc, credtype_id_krb4); if (nct->name) PFREE(nct->name); if (nct->credtext) PFREE(nct->credtext); PFREE(nct); } break; } return KHM_ERROR_SUCCESS; }
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; }
/*! \internal Collect credentials from cs2 to cs1 which have already been selected into cl1 and cl2. - Credentials in cl2 that are not in cl1 will get added to cs1 - Credentials in cl1 that are not in cl2 will get removed from cs1 - Credentials in cl1 and cl2 will be updated in cs1 cl1 and cl2 will be modified. */ khm_int32 kcdb_credset_collect_core(kcdb_credset * cs1, kcdb_cred ** cl1, khm_int32 ncl1, kcdb_credset * cs2, kcdb_cred ** cl2, khm_int32 ncl2, khm_int32 * delta) { int i, j; int ldelta = 0; khm_int32 rv; /* find matching creds and update them */ for(i=0; i<ncl1; i++) if(cl1[i]) { for(j=0; j<ncl2; j++) if(cl2[j] && kcdb_creds_is_equal((khm_handle) cl1[i], (khm_handle) cl2[j])) { /* they are equivalent. make them equal */ /* depending on whether any changes were made, update ldelta with the proper bit flag */ rv = kcdb_cred_update(cl1[i], cl2[j]); if (rv == KHM_ERROR_SUCCESS) { kcdb_credset_update_cred_ref((khm_handle) cs1, (khm_handle) cl1[i]); ldelta |= KCDB_DELTA_MODIFY; } cl2[j] = NULL; cl1[i] = NULL; break; } } /* all the creds that are left in cl1 need to be removed */ for(i=0; i<ncl1; i++) if(cl1[i]) { kcdb_credset_del_cred_ref((khm_handle) cs1, (khm_handle) cl1[i]); cl1[i] = NULL; ldelta |= KCDB_DELTA_DEL; } /* all the creds in cl2 need to be added to cs1 */ for(j=0; j<ncl2; j++) if(cl2[j]) { /* duplicate the credential and add it if we are adding it to the root credential store. */ if(cs1 == kcdb_root_credset) { khm_handle h; if(KHM_SUCCEEDED(kcdb_cred_dup((khm_handle) cl2[j], &h))) { kcdb_credset_add_cred((khm_handle) cs1, h, -1); kcdb_cred_release(h); } } else kcdb_credset_add_cred((khm_handle) cs1, cl2[j], -1); cl2[j] = NULL; ldelta |= KCDB_DELTA_ADD; } if(delta) *delta = ldelta; if((cs1 == kcdb_root_credset) && ldelta) { /* something changed in the root credential set */ kmq_post_message(KMSG_CRED,KMSG_CRED_ROOTDELTA,ldelta,NULL); } return KHM_ERROR_SUCCESS; }
/*! \internal Collect credentials from cs_src to cs_dest which have already been selected into cl_dest and cl_src. - Credentials in cl_src that are not in cl_dest will get added to cs_dest - Credentials in cl_dest that are not in cl_src will get removed from cs_dest - Credentials in cl_dest and cl_src will be updated in cs_dest cl_dest and cl_src will be modified. */ khm_int32 kcdb_credset_collect_core(kcdb_credset * cs_dest, kcdb_cred ** cl_dest, khm_int32 ncl_dest, kcdb_credset * cs_src, kcdb_cred ** cl_src, khm_int32 ncl_src, khm_int32 * delta) { int i, j; int ldelta = 0; khm_int32 rv; khm_boolean dest_is_root; khm_handle last_identity = NULL; dest_is_root = (cs_dest == kcdb_root_credset); /* find matching credentials and update them */ for (i=0; i < ncl_dest; i++) { if (cl_dest[i]) { for (j=0; j < ncl_src; j++) { if (cl_src[j] && kcdb_creds_is_equal((khm_handle) cl_dest[i], (khm_handle) cl_src[j])) { /* depending on whether any changes were made, update ldelta with the proper bit flag */ rv = kcdb_cred_update(cl_dest[i], cl_src[j]); if (rv == KHM_ERROR_SUCCESS) { kcdb_credset_update_cred_ref((khm_handle) cs_dest, (khm_handle) cl_dest[i]); ldelta |= KCDB_DELTA_MODIFY; if (dest_is_root) check_and_set_refresh_bit_for_identity(cl_dest[i], &last_identity); } cl_src[j] = NULL; cl_dest[i] = NULL; break; } } } } /* all the creds that are left in cl_dest need to be removed */ for (i=0; i < ncl_dest; i++) { if (cl_dest[i]) { if (dest_is_root) check_and_set_refresh_bit_for_identity(cl_dest[i], &last_identity); kcdb_credset_del_cred_ref((khm_handle) cs_dest, (khm_handle) cl_dest[i]); ldelta |= KCDB_DELTA_DEL; cl_dest[i] = NULL; } } /* all the creds in cl_src need to be added to cs_dest */ for (j=0; j < ncl_src; j++) { if (cl_src[j]) { /* duplicate the credential and add it if we are adding it to or from the root credential store. */ if (cs_dest == kcdb_root_credset || cs_src == kcdb_root_credset) { khm_handle h; if (KHM_SUCCEEDED(kcdb_cred_dup((khm_handle) cl_src[j], &h))) { kcdb_credset_add_cred((khm_handle) cs_dest, h, -1); kcdb_cred_release(h); } } else { kcdb_credset_add_cred((khm_handle) cs_dest, cl_src[j], -1); } if (dest_is_root) check_and_set_refresh_bit_for_identity(cl_src[j], &last_identity); cl_src[j] = NULL; ldelta |= KCDB_DELTA_ADD; } } if (last_identity) { kcdb_identity_release(last_identity); last_identity = NULL; } if (delta) *delta = ldelta; if (dest_is_root && ldelta) { /* something changed in the root credential set */ kmq_post_message(KMSG_CRED,KMSG_CRED_ROOTDELTA,ldelta,NULL); } return KHM_ERROR_SUCCESS; }