/* * Copyright (c) 2004 Massachusetts Institute of Technology * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, copy, * modify, merge, publish, distribute, sublicense, and/or sell copies * of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ /* $Id$ */ #include #include CRITICAL_SECTION cs_credset; kcdb_credset * kcdb_credsets = NULL; kcdb_credset * kcdb_root_credset = NULL; void kcdb_credset_init(void) { khm_handle rc; InitializeCriticalSection(&cs_credset); kcdb_credsets = NULL; kcdb_credset_create(&rc); kcdb_root_credset = (kcdb_credset *) rc; kcdb_root_credset->flags |= KCDB_CREDSET_FLAG_ROOT; } void kcdb_credset_exit(void) { /*TODO: free the credsets */ DeleteCriticalSection(&cs_credset); } /* called on an unreleased credset, or with credset::cs held */ void kcdb_credset_buf_new(kcdb_credset * cs) { cs->clist = malloc(KCDB_CREDSET_INITIAL_SIZE * sizeof(kcdb_credset_credref)); ZeroMemory(cs->clist, KCDB_CREDSET_INITIAL_SIZE * sizeof(kcdb_credset_credref)); cs->nc_clist = KCDB_CREDSET_INITIAL_SIZE; cs->nclist = 0; } /* called on an unreleased credset, or with credset::cs held */ void kcdb_credset_buf_delete(kcdb_credset * cs) { free(cs->clist); cs->nc_clist = 0; cs->nclist = 0; } void kcdb_credset_buf_assert_size(kcdb_credset * cs, khm_int32 nclist) { if(cs->nc_clist < nclist) { kcdb_credset_credref * new_clist; /* nclist had better be greater than KCDB_CREDSET_INITIAL_SIZE */ nclist = KCDB_CREDSET_INITIAL_SIZE + (((nclist - (KCDB_CREDSET_INITIAL_SIZE + 1)) / KCDB_CREDSET_GROWTH_FACTOR) + 1) * KCDB_CREDSET_GROWTH_FACTOR; new_clist = calloc(nclist, sizeof(kcdb_credset_credref)); memcpy(new_clist, cs->clist, cs->nclist * sizeof(kcdb_credset_credref)); free(cs->clist); cs->clist = new_clist; } } KHMEXP khm_int32 KHMAPI kcdb_credset_create(khm_handle * result) { kcdb_credset * cs; cs = malloc(sizeof(kcdb_credset)); ZeroMemory(cs, sizeof(kcdb_credset)); cs->magic = KCDB_CREDSET_MAGIC; InitializeCriticalSection(&(cs->cs)); LINIT(cs); kcdb_credset_buf_new(cs); cs->version = 0; cs->seal_count = 0; EnterCriticalSection(&cs_credset); LPUSH(&kcdb_credsets, cs); LeaveCriticalSection(&cs_credset); *result = (khm_handle) cs; return KHM_ERROR_SUCCESS; } 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_PARM; } cs = (kcdb_credset *) vcredset; EnterCriticalSection(&cs_credset); LDELETE(&kcdb_credsets, cs); LeaveCriticalSection(&cs_credset); EnterCriticalSection(&(cs->cs)); cs->magic = 0; for(i=0;inclist;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)); free(cs); return KHM_ERROR_SUCCESS; } /*! \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; ics)); EnterCriticalSection(&(rcs->cs)); /* enumerate through the root and given credential sets and select the ones we want */ if(rcs->nclist > 0) r_sel = malloc(sizeof(kcdb_cred *) * rcs->nclist); if(cs->nclist > 0) c_sel = malloc(sizeof(kcdb_cred *) * cs->nclist); nr_sel = 0; nc_sel = 0; for(i=0; inclist; i++) { if(rcs->clist[i].cred && (!identity || rcs->clist[i].cred->identity == identity) && (type==KCDB_CREDTYPE_ALL || rcs->clist[i].cred->type == type)) { r_sel[nr_sel++] = rcs->clist[i].cred; } } for(i=0; inclist; i++) { if(cs->clist[i].cred && (!identity || cs->clist[i].cred->identity == identity) && (type==KCDB_CREDTYPE_ALL || cs->clist[i].cred->type == type)) { c_sel[nc_sel++] = cs->clist[i].cred; } } rcs->version++; code = kcdb_credset_collect_core( rcs, r_sel, nr_sel, cs, c_sel, nc_sel, delta); LeaveCriticalSection(&(rcs->cs)); LeaveCriticalSection(&(cs->cs)); if(r_sel) free(r_sel); if(c_sel) free(c_sel); return code; } KHMEXP khm_int32 KHMAPI kcdb_credset_collect_filtered( khm_handle cs_dest, khm_handle cs_src, kcdb_cred_filter_func filter, void * rock, khm_int32 * delta) { kcdb_credset * cs; kcdb_credset * rcs; khm_int32 code = KHM_ERROR_SUCCESS; kcdb_cred ** r_sel = NULL; kcdb_cred ** c_sel = NULL; int nr_sel, nc_sel; int i; khm_int32 cs_f = 0; khm_int32 rcs_f = 0; if((cs_src && !kcdb_credset_is_credset(cs_src)) || (cs_dest && !kcdb_credset_is_credset(cs_dest)) || (cs_src == cs_dest)) /* works because credsets use shared handles */ return KHM_ERROR_INVALID_PARM; if(cs_src) cs = (kcdb_credset *) cs_src; else { cs = kcdb_root_credset; cs_f = KCDB_CREDCOLL_FILTER_ROOT; } if(cs_dest) rcs = (kcdb_credset *) cs_dest; else { rcs = kcdb_root_credset; rcs_f = KCDB_CREDCOLL_FILTER_ROOT; } if (kcdb_credset_is_sealed(rcs)) return KHM_ERROR_INVALID_OPERATION; EnterCriticalSection(&(cs->cs)); EnterCriticalSection(&(rcs->cs)); #ifdef DEBUG assert(!(rcs->flags & KCDB_CREDSET_FLAG_ENUM)); assert(!(cs->flags & KCDB_CREDSET_FLAG_ENUM)); #endif if(rcs->nclist) r_sel = malloc(sizeof(kcdb_cred *) * rcs->nclist); if(cs->nclist) c_sel = malloc(sizeof(kcdb_cred *) * cs->nclist); nr_sel = 0; nc_sel = 0; rcs->flags |= KCDB_CREDSET_FLAG_ENUM; for(i=0; inclist; i++) { if(rcs->clist[i].cred && (*filter)((khm_handle)rcs->clist[i].cred, KCDB_CREDCOLL_FILTER_DEST | rcs_f, rock)) { r_sel[nr_sel++] = rcs->clist[i].cred; } } rcs->flags &= ~KCDB_CREDSET_FLAG_ENUM; cs->flags |= KCDB_CREDSET_FLAG_ENUM; for(i=0; inclist; i++) { if(cs->clist[i].cred && filter((khm_handle)rcs->clist[i].cred, KCDB_CREDCOLL_FILTER_SRC | cs_f, rock)) { c_sel[nc_sel++] = cs->clist[i].cred; } } cs->flags &= ~KCDB_CREDSET_FLAG_ENUM; rcs->version++; code = kcdb_credset_collect_core( rcs, r_sel, nr_sel, cs, c_sel, nc_sel, delta); LeaveCriticalSection(&(rcs->cs)); LeaveCriticalSection(&(cs->cs)); if(r_sel) free(r_sel); if(c_sel) free(c_sel); return code; } 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_PARM; 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;inclist;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_extract( khm_handle destcredset, khm_handle sourcecredset, khm_handle identity, khm_int32 type) { 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_PARM; if(sourcecredset) { if(!kcdb_credset_is_credset(sourcecredset)) return KHM_ERROR_INVALID_PARM; } else { sourcecredset = kcdb_root_credset; } if (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(); for(i=0; i < (int) srcSize; i++) { kcdb_cred * c; c = src->clist[i].cred; if(kcdb_cred_is_active_cred((khm_handle) c) && (!identity || c->identity == identity) && (type==KCDB_TYPE_INVALID || c->type == type)) { 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(); } } } kcdb_cred_unlock_read(); _exit: LeaveCriticalSection(&(dest->cs)); LeaveCriticalSection(&(src->cs)); return code; } 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_PARM; if(sourcecredset) { if(!kcdb_credset_is_credset(sourcecredset)) return KHM_ERROR_INVALID_PARM; } 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; } KHMEXP khm_int32 KHMAPI kcdb_credset_apply(khm_handle vcredset, kcdb_cred_apply_func f, void * rock) { kcdb_credset * cs; khm_int32 rv = KHM_ERROR_SUCCESS; int i; if(vcredset != NULL && !kcdb_credset_is_credset(vcredset)) return KHM_ERROR_INVALID_PARM; if(vcredset == NULL) { cs = kcdb_root_credset; } else { cs = (kcdb_credset *) vcredset; } EnterCriticalSection(&cs->cs); #ifdef DEBUG assert(!(cs->flags & KCDB_CREDSET_FLAG_ENUM)); #endif cs->flags |= KCDB_CREDSET_FLAG_ENUM; for(i=0; inclist; i++) { if(!kcdb_cred_is_active_cred(cs->clist[i].cred)) continue; if(KHM_FAILED(f((khm_handle) cs->clist[i].cred, rock))) break; } cs->flags &= ~KCDB_CREDSET_FLAG_ENUM; LeaveCriticalSection(&cs->cs); if(inclist) rv = KHM_ERROR_EXIT; return rv; } 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_PARM; 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_find_filtered( khm_handle credset, khm_int32 idx_start, kcdb_cred_filter_func f, void * rock, khm_handle * cred, khm_int32 * idx) { kcdb_credset * cs; khm_int32 rv = KHM_ERROR_SUCCESS; int i; if((credset && !kcdb_credset_is_credset(credset)) || (!f || !cred)) return KHM_ERROR_INVALID_PARM; if(credset) cs = (kcdb_credset *) credset; else cs = kcdb_root_credset; EnterCriticalSection(&cs->cs); if(idx_start < 0) i = 0; else i = idx_start + 1; #ifdef DEBUG assert(!(cs->flags & KCDB_CREDSET_FLAG_ENUM)); #endif cs->flags |= KCDB_CREDSET_FLAG_ENUM; for(; i < cs->nclist; i++) { if(kcdb_cred_is_active_cred(cs->clist[i].cred) && (*f)((khm_handle) cs->clist[i].cred, 0, rock) != 0) break; } cs->flags &= ~KCDB_CREDSET_FLAG_ENUM; if(i < cs->nclist) { *cred = (khm_handle) cs->clist[i].cred; kcdb_cred_hold(*cred); if(idx) *idx = i; } else { rv = KHM_ERROR_NOT_FOUND; } LeaveCriticalSection(&cs->cs); return rv; } 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_PARM; if (!kcdb_cred_is_active_cred(vcred_src)) return KHM_ERROR_INVALID_PARM; 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_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_PARM; 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_PARM; 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; } khm_int32 kcdb_credset_update_cred_ref( khm_handle credset, khm_handle cred) { kcdb_credset * cs; khm_int32 code = KHM_ERROR_SUCCESS; int i; if(!kcdb_credset_is_credset(credset)) return KHM_ERROR_INVALID_PARM; cs = (kcdb_credset *) credset; EnterCriticalSection(&(cs->cs)); for(i=0; inclist; i++) { if(cs->clist[i].cred == cred) break; } if(inclist) { cs->clist[i].version = cs->version; } else { code = KHM_ERROR_NOT_FOUND; } LeaveCriticalSection(&(cs->cs)); return code; } KHMEXP khm_int32 KHMAPI kcdb_credset_del_cred_ref( khm_handle credset, khm_handle cred) { kcdb_credset * cs; khm_int32 code = KHM_ERROR_SUCCESS; int i; if(!kcdb_credset_is_credset(credset)) return KHM_ERROR_INVALID_PARM; cs = (kcdb_credset *) credset; if (kcdb_credset_is_sealed(cs)) return KHM_ERROR_INVALID_OPERATION; EnterCriticalSection(&(cs->cs)); for(i=0; inclist; i++) { if(cs->clist[i].cred == cred) break; } if(inclist) { code = kcdb_credset_del_cred(credset, i); } else { code = KHM_ERROR_NOT_FOUND; } LeaveCriticalSection(&(cs->cs)); return code; } KHMEXP khm_int32 KHMAPI kcdb_credset_add_cred( khm_handle credset, khm_handle cred, khm_int32 idx) { int new_idx; kcdb_credset * cs; khm_int32 code = KHM_ERROR_SUCCESS; if(!kcdb_credset_is_credset(credset)) return KHM_ERROR_INVALID_PARM; cs = (kcdb_credset *) credset; if (kcdb_credset_is_sealed(cs)) return KHM_ERROR_INVALID_OPERATION; EnterCriticalSection(&(cs->cs)); kcdb_credset_buf_assert_size(cs, cs->nclist + 1); if(idx < 0 || idx > cs->nclist) new_idx = cs->nclist; else if(idx < cs->nclist){ #ifdef DEBUG assert(!(cs->flags & KCDB_CREDSET_FLAG_ENUM)); #endif memmove(&(cs->clist[idx+1]), &(cs->clist[idx]), (cs->nclist - idx)*sizeof(cs->clist[0])); new_idx = idx; } else new_idx = idx; kcdb_cred_hold(cred); cs->clist[new_idx].cred = (kcdb_cred *) cred; cs->clist[new_idx].version = cs->version; cs->nclist++; LeaveCriticalSection(&(cs->cs)); return code; } KHMEXP khm_int32 KHMAPI kcdb_credset_get_size( khm_handle credset, khm_size * size) { kcdb_credset * cs; *size = 0; /* we don't rely on this working, since we can't purge a sealed credset, although we can measure its size. */ kcdb_credset_purge(credset); if (credset == NULL) cs = kcdb_root_credset; else cs = (kcdb_credset *) credset; EnterCriticalSection(&(cs->cs)); /* while it may seem a bit redundant to get a lock, it ensures that that the size that we return is consistent with the current state of the credential set */ *size = cs->nclist; LeaveCriticalSection(&(cs->cs)); return KHM_ERROR_SUCCESS; } 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_PARM; 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; } KHMEXP khm_int32 KHMAPI kcdb_credset_seal(khm_handle credset) { kcdb_credset * cs; if (!kcdb_credset_is_credset(credset)) return KHM_ERROR_INVALID_PARM; cs = (kcdb_credset *) credset; EnterCriticalSection(&cs->cs); cs->seal_count++; LeaveCriticalSection(&cs->cs); return KHM_ERROR_SUCCESS; } KHMEXP khm_int32 KHMAPI kcdb_credset_unseal(khm_handle credset) { kcdb_credset * cs; khm_int32 rv; if (!kcdb_credset_is_credset(credset)) return KHM_ERROR_INVALID_PARM; cs = (kcdb_credset *) credset; EnterCriticalSection(&cs->cs); if (cs->seal_count > 0) { cs->seal_count--; rv = KHM_ERROR_SUCCESS; } else { rv = KHM_ERROR_INVALID_OPERATION; } LeaveCriticalSection(&cs->cs); return rv; } /* wrapper for qsort and also parameter gobbling FSM. */ int __cdecl kcdb_creds_comp_wrapper(const void * a, const void * b) { static void * rock = NULL; static kcdb_cred_comp_func comp = NULL; if(!b) { rock = (void *) a; return 0; } if(!a) { comp = (kcdb_cred_comp_func) b; return 0; } return comp((khm_handle) ((kcdb_credset_credref *)a)->cred, (khm_handle) ((kcdb_credset_credref *)b)->cred, rock); } KHMEXP khm_int32 KHMAPI kcdb_credset_sort( khm_handle credset, kcdb_cred_comp_func comp, void * rock) { khm_int32 code = KHM_ERROR_SUCCESS; kcdb_credset * cs; if(!kcdb_credset_is_credset(credset)) return KHM_ERROR_INVALID_PARM; cs = (kcdb_credset *) credset; if (kcdb_credset_is_sealed(cs)) return KHM_ERROR_INVALID_OPERATION; EnterCriticalSection(&(cs->cs)); #ifdef DEBUG assert(!(cs->flags & KCDB_CREDSET_FLAG_ENUM)); #endif kcdb_creds_comp_wrapper(rock, NULL); kcdb_creds_comp_wrapper(NULL, (void *) comp); qsort(cs->clist, cs->nclist, sizeof(kcdb_credset_credref), kcdb_creds_comp_wrapper); LeaveCriticalSection(&(cs->cs)); return code; } KHMEXP khm_int32 KHMAPI kcdb_cred_comp_generic( khm_handle cred1, khm_handle cred2, void * rock) { kcdb_cred_comp_order * o = (kcdb_cred_comp_order *) rock; int i; khm_int32 r = 0; khm_int32 f1, f2; khm_int32 pt; for(i=0; inFields; i++) { if (o->fields[i].order & KCDB_CRED_COMP_INITIAL_FIRST) { kcdb_cred_get_flags(cred1, &f1); kcdb_cred_get_flags(cred2, &f2); if (((f1 ^ f2) & KCDB_CRED_FLAG_INITIAL) == 0) { kcdb_cred_get_type(cred1, &f1); kcdb_cred_get_type(cred2, &f2); kcdb_identity_get_type(&pt); if (f1 == f2) r = 0; else if (f1 == pt) r = -1; else if (f2 == pt) r = 1; else r = 0; } else if (f1 & KCDB_CRED_FLAG_INITIAL) r = -1; else r = 1; } else { r = 0; } if (r == 0) r = kcdb_creds_comp_attr(cred1,cred2,o->fields[i].attrib); if(r != 0) { if(o->fields[i].order & KCDB_CRED_COMP_DECREASING) r = -r; break; } } return r; }