/* * Copyright (c) 2005 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 /* cs_creds protects the *collection* of credentials, while l_creds protects the *contents* of individual credentials. */ CRITICAL_SECTION cs_creds; kcdb_cred * kcdb_creds = NULL; /* a read lock must be obtained when querying any existing credential. a write lock must be obtained when modifying any existing credential. */ RWLOCK l_creds; /* serial number */ khm_ui_8 kcdb_cred_id = 0; void kcdb_cred_init(void) { InitializeCriticalSection(&cs_creds); InitializeRwLock(&l_creds); kcdb_cred_id = 0; } void kcdb_cred_exit(void) { /*TODO: Free the credentials */ DeleteCriticalSection(&cs_creds); DeleteRwLock(&l_creds); } /*! \internal can be called by kcdb_cred_dup with a write lock on l_creds and in other places with a read lock on l_creds. New credentials must be creatable while holding either lock. */ KHMEXP khm_int32 KHMAPI kcdb_cred_create(wchar_t * name, khm_handle identity, khm_int32 cred_type, khm_handle * result) { kcdb_cred * cred; size_t cb_name; if(!name || !result || FAILED(StringCbLength(name, KCDB_CRED_MAXCB_NAME, &cb_name)) || KHM_FAILED(kcdb_credtype_get_info(cred_type, NULL)) || KHM_FAILED(kcdb_identity_hold(identity))) { return KHM_ERROR_INVALID_PARAM; } cb_name += sizeof(wchar_t); cred = PMALLOC(sizeof(kcdb_cred)); ZeroMemory(cred, sizeof(kcdb_cred)); cred->magic = KCDB_CRED_MAGIC; cred->identity = identity; cred->name = PMALLOC(cb_name); StringCbCopy(cred->name, cb_name, name); cred->type = cred_type; cred->refcount = 1; /* initially held */ LINIT(cred); kcdb_buf_new(&cred->buf, KCDB_ATTR_MAX_ID + 1); /* Not obtaining a write lock on l_cred on purpose. Well, because no one should be referencing this credential until this function returns. */ EnterCriticalSection(&cs_creds); cred->id = kcdb_cred_id++; LPUSH(&kcdb_creds, cred); LeaveCriticalSection(&cs_creds); *result = cred; return KHM_ERROR_SUCCESS; } KHMEXP khm_int32 KHMAPI kcdb_cred_update(khm_handle vdest, khm_handle vsrc) { khm_int32 rv = KHM_ERROR_EQUIVALENT; kcdb_cred * src; kcdb_cred * dest; kcdb_type * t; kcdb_attrib * a; void * srcbuf; void * destbuf; khm_size cbsrcbuf; khm_size cbdestbuf; int i; kcdb_cred_lock_write(); if(!kcdb_cred_is_active_cred(vsrc) || !kcdb_cred_is_active_cred(vdest)) goto _exit; src = (kcdb_cred *) vsrc; dest = (kcdb_cred *) vdest; for(i=0;iflags & KCDB_ATTR_FLAG_COMPUTED) || KHM_FAILED(kcdb_type_get_info(a->type, &t))) { kcdb_attrib_release_info(a); continue; } srcbuf = kcdb_cred_buf_get(src,i); cbsrcbuf = kcdb_cred_buf_size(src, i); if(kcdb_cred_val_exist(dest, i)) { destbuf = kcdb_cred_buf_get(dest, i); cbdestbuf = kcdb_cred_buf_size(dest, i); if(!t->comp(srcbuf, cbsrcbuf, destbuf, cbdestbuf)) goto _skip_copy; } kcdb_buf_set_value(&dest->buf, i, i, srcbuf, cbsrcbuf); rv = KHM_ERROR_SUCCESS; _skip_copy: kcdb_attrib_release_info(a); kcdb_type_release_info(t); } else { if (KHM_FAILED(kcdb_attrib_get_info(i, &a))) continue; if (!(a->flags & KCDB_ATTR_FLAG_COMPUTED) && (a->flags & KCDB_ATTR_FLAG_TRANSIENT) && kcdb_cred_val_exist(dest, i)) { kcdb_buf_set_value(&dest->buf, i, i, NULL, 0); rv = KHM_ERROR_SUCCESS; } kcdb_attrib_release_info(a); } } if (dest->flags != src->flags) { khm_int32 old_flags; old_flags = dest->flags; dest->flags = (src->flags & ~KCDB_CRED_FLAGMASK_ADDITIVE) | ((src->flags | dest->flags) & KCDB_CRED_FLAGMASK_ADDITIVE); if (dest->flags != old_flags) rv = KHM_ERROR_SUCCESS; } _exit: kcdb_cred_unlock_write(); return rv; } KHMEXP khm_int32 KHMAPI kcdb_cred_dup( khm_handle vcred, khm_handle * pnewcred) { khm_int32 code = KHM_ERROR_SUCCESS; kcdb_cred * cred; kcdb_cred * newcred; khm_handle vnewcred; if(!pnewcred) return KHM_ERROR_INVALID_PARAM; *pnewcred = NULL; kcdb_cred_lock_write(); if(!kcdb_cred_is_active_cred(vcred)) { code = KHM_ERROR_INVALID_PARAM; goto _exit; } cred = (kcdb_cred *) vcred; if(KHM_FAILED(kcdb_cred_create(cred->name, cred->identity, cred->type, &vnewcred))) { code = KHM_ERROR_UNKNOWN; goto _exit; } newcred = (kcdb_cred *) vnewcred; newcred->flags = cred->flags; kcdb_buf_dup(&newcred->buf, &cred->buf); /* newcred is already held from the call to kcdb_cred_create */ *pnewcred = (khm_handle) newcred; _exit: kcdb_cred_unlock_write(); return code; } KHMEXP khm_int32 KHMAPI kcdb_cred_get_serial( khm_handle vcred, khm_ui_8 * pserial) { kcdb_cred * c; if(!pserial) return KHM_ERROR_INVALID_PARAM; kcdb_cred_lock_read(); if(!kcdb_cred_is_active_cred(vcred)) { kcdb_cred_unlock_read(); return KHM_ERROR_INVALID_PARAM; } c = (kcdb_cred *) vcred; *pserial = c->id; kcdb_cred_unlock_read(); return KHM_ERROR_SUCCESS; } KHMEXP khm_int32 KHMAPI kcdb_cred_set_identity( khm_handle vcred, khm_handle id) { kcdb_cred * c; if(!kcdb_is_identity(id)) return KHM_ERROR_INVALID_PARAM; kcdb_cred_lock_write(); if(!kcdb_cred_is_active_cred(vcred)) { kcdb_cred_unlock_write(); return KHM_ERROR_INVALID_PARAM; } c = (kcdb_cred *) vcred; if(c->identity) { kcdb_identity_release((khm_handle) c->identity); } kcdb_identity_hold(id); c->identity = (kcdb_identity *) id; kcdb_cred_unlock_write(); return KHM_ERROR_SUCCESS; } KHMEXP khm_int32 KHMAPI kcdb_cred_get_type( khm_handle vcred, khm_int32 * type) { kcdb_cred * c; if(!type) return KHM_ERROR_INVALID_PARAM; kcdb_cred_lock_read(); if(!kcdb_cred_is_active_cred(vcred)) { kcdb_cred_unlock_read(); return KHM_ERROR_INVALID_PARAM; } c = (kcdb_cred *) vcred; *type = c->type; kcdb_cred_unlock_read(); return KHM_ERROR_SUCCESS; } KHMEXP khm_int32 KHMAPI kcdb_cred_set_attrib( khm_handle cred, wchar_t * name, void * buffer, khm_size cbbuf) { khm_int32 attr_id = -1; if(KHM_FAILED(kcdb_attrib_get_id(name, &attr_id))) return KHM_ERROR_INVALID_PARAM; return kcdb_cred_set_attr( cred, attr_id, buffer, cbbuf); } KHMEXP khm_int32 KHMAPI kcdb_cred_set_attr( khm_handle vcred, khm_int32 attr_id, void * buffer, khm_size cbbuf) { kcdb_cred * cred; kcdb_type * type = NULL; kcdb_attrib * attrib = NULL; khm_size cbdest; khm_int32 code = KHM_ERROR_SUCCESS; if(attr_id < 0 || attr_id > KCDB_ATTR_MAX_ID) return KHM_ERROR_INVALID_PARAM; kcdb_cred_lock_write(); if(!kcdb_cred_is_active_cred(vcred)) { kcdb_cred_unlock_write(); return KHM_ERROR_INVALID_PARAM; } cred = (kcdb_cred *) vcred; if(KHM_FAILED(kcdb_attrib_get_info(attr_id, &attrib))) { kcdb_cred_unlock_write(); return KHM_ERROR_INVALID_PARAM; } if(attrib->flags & KCDB_ATTR_FLAG_COMPUTED) { kcdb_cred_unlock_write(); kcdb_attrib_release_info(attrib); return KHM_ERROR_INVALID_OPERATION; } if (buffer == 0) { /* we are removing the value */ kcdb_buf_alloc(&cred->buf, attr_id, attr_id, 0); code = KHM_ERROR_SUCCESS; goto _exit; } if(KHM_FAILED(kcdb_type_get_info(attrib->type, &type))) { kcdb_cred_unlock_write(); kcdb_attrib_release_info(attrib); return KHM_ERROR_INVALID_PARAM; } if(!(type->isValid(buffer,cbbuf))) { code = KHM_ERROR_TYPE_MISMATCH; goto _exit; } if((type->dup(buffer, cbbuf, NULL, &cbdest)) != KHM_ERROR_TOO_LONG) { code = KHM_ERROR_INVALID_PARAM; goto _exit; } kcdb_buf_alloc(&cred->buf, attr_id, attr_id, cbdest); if(!kcdb_cred_buf_exist(cred, attr_id)) { code = KHM_ERROR_NO_RESOURCES; goto _exit; } if(KHM_FAILED(code = type->dup(buffer, cbbuf, kcdb_cred_buf_get(cred,attr_id), &cbdest))) { kcdb_buf_alloc(&cred->buf, attr_id, attr_id, 0); goto _exit; } kcdb_buf_set_value_flag(&cred->buf, attr_id); _exit: kcdb_cred_unlock_write(); if(attrib) kcdb_attrib_release_info(attrib); if(type) kcdb_type_release_info(type); return code; } KHMEXP khm_int32 KHMAPI kcdb_cred_get_attrib( khm_handle cred, wchar_t * name, khm_int32 * attr_type, void * buffer, khm_size * cbbuf) { khm_int32 attr_id = -1; if(KHM_FAILED(kcdb_attrib_get_id(name, &attr_id))) return KHM_ERROR_NOT_FOUND; return kcdb_cred_get_attr( cred, attr_id, attr_type, buffer, cbbuf); } KHMEXP khm_int32 KHMAPI kcdb_cred_get_attrib_string( khm_handle cred, wchar_t * name, wchar_t * buffer, khm_size * cbbuf, khm_int32 flags) { khm_int32 attr_id = -1; if(KHM_FAILED(kcdb_attrib_get_id(name, &attr_id))) return KHM_ERROR_NOT_FOUND; return kcdb_cred_get_attr_string( cred, attr_id, buffer, cbbuf, flags); } KHMEXP khm_int32 KHMAPI kcdb_cred_get_attr(khm_handle vcred, khm_int32 attr_id, khm_int32 * attr_type, void * buffer, khm_size * pcbbuf) { khm_int32 code = KHM_ERROR_SUCCESS; kcdb_cred * cred = NULL; kcdb_attrib * attrib = NULL; kcdb_type * type = NULL; if(attr_id < 0 || attr_id > KCDB_ATTR_MAX_ID) return KHM_ERROR_INVALID_PARAM; if(KHM_FAILED(kcdb_attrib_get_info(attr_id, &attrib))) { return KHM_ERROR_INVALID_PARAM; } if(KHM_FAILED(kcdb_type_get_info(attrib->type, &type))) { kcdb_attrib_release_info(attrib); return KHM_ERROR_UNKNOWN; } if(attr_type) *attr_type = attrib->type; kcdb_cred_lock_read(); if(!kcdb_cred_is_active_cred(vcred)) { code = KHM_ERROR_INVALID_PARAM; goto _exit; } cred = (kcdb_cred *) vcred; if(!buffer && !pcbbuf) { /* in this case the caller is only trying to determine if the field contains data. We assume that computed fields are always non-null. */ code = (kcdb_cred_val_exist(cred, attr_id) || (attrib->flags & KCDB_ATTR_FLAG_COMPUTED))?KHM_ERROR_SUCCESS:KHM_ERROR_NOT_FOUND; goto _exit; } if(attrib->flags & KCDB_ATTR_FLAG_COMPUTED) { code = attrib->compute_cb( vcred, attr_id, buffer, pcbbuf); } else if (kcdb_cred_val_exist(cred, attr_id)) { code = type->dup( kcdb_cred_buf_get(cred, attr_id), kcdb_cred_buf_size(cred, attr_id), buffer, pcbbuf); } else { code = KHM_ERROR_NOT_FOUND; } _exit: kcdb_cred_unlock_read(); if(type) kcdb_type_release_info(type); if(attrib) kcdb_attrib_release_info(attrib); return code; } KHMEXP khm_int32 KHMAPI kcdb_cred_get_attr_string( khm_handle vcred, khm_int32 attr_id, wchar_t * buffer, khm_size * pcbbuf, khm_int32 flags) { khm_int32 code = KHM_ERROR_SUCCESS; kcdb_cred * cred = NULL; kcdb_attrib * attrib = NULL; kcdb_type * type = NULL; if(attr_id < 0 || attr_id > KCDB_ATTR_MAX_ID) return KHM_ERROR_INVALID_PARAM; if(KHM_FAILED(kcdb_attrib_get_info(attr_id, &attrib))) { code = KHM_ERROR_INVALID_PARAM; goto _exit_nolock; } if(KHM_FAILED(kcdb_type_get_info(attrib->type, &type))) { code = KHM_ERROR_UNKNOWN; goto _exit_nolock; } kcdb_cred_lock_read(); if(!kcdb_cred_is_active_cred(vcred)) { code = KHM_ERROR_INVALID_PARAM; goto _exit; } cred = (kcdb_cred *) vcred; if(!buffer && !pcbbuf) { /* in this case the caller is only trying to determine if the field contains data. We assume that computed fields are always non-null. */ code = (kcdb_cred_val_exist(cred, attr_id) || (attrib->flags & KCDB_ATTR_FLAG_COMPUTED))?KHM_ERROR_SUCCESS:KHM_ERROR_NOT_FOUND; goto _exit; } if(attrib->flags & KCDB_ATTR_FLAG_COMPUTED) { void * buf; khm_size cbbuf; code = attrib->compute_cb(vcred, attr_id, NULL, &cbbuf); if(code == KHM_ERROR_TOO_LONG) { wchar_t vbuf[KCDB_MAXCCH_NAME]; if (cbbuf < sizeof(vbuf)) buf = vbuf; else buf = PMALLOC(cbbuf); code = attrib->compute_cb(vcred, attr_id, buf, &cbbuf); if(KHM_SUCCEEDED(code)) { code = type->toString(buf, cbbuf, buffer, pcbbuf, flags); } if (buf != vbuf) PFREE(buf); } } else { if(kcdb_cred_buf_exist(cred, attr_id)) { code = type->toString( kcdb_cred_buf_get(cred, attr_id), kcdb_cred_buf_size(cred, attr_id), buffer, pcbbuf, flags); } else code = KHM_ERROR_NOT_FOUND; } _exit: kcdb_cred_unlock_read(); _exit_nolock: if(type) kcdb_type_release_info(type); if(attrib) kcdb_attrib_release_info(attrib); return code; } KHMEXP khm_int32 KHMAPI kcdb_cred_get_name( khm_handle vcred, wchar_t * buffer, khm_size * cbbuf) { khm_int32 code = KHM_ERROR_SUCCESS; kcdb_cred * cred = NULL; size_t cbsize; if(!cbbuf) return KHM_ERROR_INVALID_PARAM; kcdb_cred_lock_read(); if(!kcdb_cred_is_active_cred(vcred)) { code = KHM_ERROR_INVALID_PARAM; goto _exit; } cred = (kcdb_cred *) vcred; if(FAILED(StringCbLength(cred->name, KCDB_CRED_MAXCB_NAME, &cbsize))) { code = KHM_ERROR_UNKNOWN; goto _exit; } cbsize += sizeof(wchar_t); if(!buffer || *cbbuf < cbsize) { *cbbuf = cbsize; code = KHM_ERROR_TOO_LONG; goto _exit; } StringCbCopy(buffer, *cbbuf, cred->name); *cbbuf = cbsize; _exit: kcdb_cred_unlock_read(); return code; } KHMEXP khm_int32 KHMAPI kcdb_cred_get_identity( khm_handle vcred, khm_handle * identity) { khm_int32 code = KHM_ERROR_SUCCESS; kcdb_cred * cred; if(!identity) return KHM_ERROR_INVALID_PARAM; kcdb_cred_lock_read(); if(!kcdb_cred_is_active_cred(vcred)) { code = KHM_ERROR_INVALID_PARAM; goto _exit; } cred = (kcdb_cred *) vcred; kcdb_identity_hold((khm_handle) cred->identity); *identity = cred->identity; _exit: kcdb_cred_unlock_read(); return code; } KHMEXP khm_int32 KHMAPI kcdb_cred_hold(khm_handle vcred) { khm_int32 code = KHM_ERROR_SUCCESS; kcdb_cred * cred; kcdb_cred_lock_write(); if(!kcdb_cred_is_cred(vcred)) { code = KHM_ERROR_INVALID_PARAM; goto _exit; } cred = (kcdb_cred *) vcred; cred->refcount++; _exit: kcdb_cred_unlock_write(); return code; } KHMEXP khm_int32 KHMAPI kcdb_cred_release(khm_handle vcred) { khm_int32 code = KHM_ERROR_SUCCESS; kcdb_cred * cred; kcdb_cred_lock_write(); if(!kcdb_cred_is_cred(vcred)) { code = KHM_ERROR_INVALID_PARAM; goto _exit; } cred = (kcdb_cred *) vcred; cred->refcount--; _exit: kcdb_cred_unlock_write(); kcdb_cred_check_and_delete(vcred); return code; } void kcdb_cred_check_and_delete(khm_handle vcred) { kcdb_cred * cred; kcdb_cred_lock_read(); if(!kcdb_cred_is_cred(vcred)) { goto _exit; } cred = (kcdb_cred *) vcred; if(cred->refcount) goto _exit; kcdb_cred_unlock_read(); kcdb_cred_lock_write(); if(!kcdb_cred_is_cred(vcred)) { /* did we lose the race? */ goto _exit2; } cred->magic = 0; /* no longer a cred */ kcdb_identity_release(cred->identity); EnterCriticalSection(&cs_creds); LDELETE(&kcdb_creds, cred); LeaveCriticalSection(&cs_creds); kcdb_buf_delete(&cred->buf); PFREE(cred->name); PFREE(cred); /*TODO: notifications */ _exit2: kcdb_cred_unlock_write(); return; _exit: kcdb_cred_unlock_read(); } KHMEXP khm_int32 KHMAPI kcdb_cred_delete(khm_handle vcred) { khm_int32 code = KHM_ERROR_SUCCESS; kcdb_cred * cred; kcdb_cred_lock_write(); if(!kcdb_cred_is_active_cred(vcred)) { code = KHM_ERROR_INVALID_PARAM; goto _exit; } cred = (kcdb_cred *) vcred; cred->flags |= KCDB_CRED_FLAG_DELETED; _exit: kcdb_cred_unlock_write(); kcdb_cred_check_and_delete(vcred); return code; } KHMEXP khm_int32 KHMAPI kcdb_creds_comp_attrib(khm_handle cred1, khm_handle cred2, wchar_t * name) { khm_int32 attr_id; if(KHM_FAILED(kcdb_attrib_get_id(name, &attr_id))) return 0; return kcdb_creds_comp_attr(cred1, cred2, attr_id); } KHMEXP khm_int32 KHMAPI kcdb_creds_comp_attr(khm_handle vcred1, khm_handle vcred2, khm_int32 attr_id) { khm_int32 code = 0; kcdb_cred * cred1; kcdb_cred * cred2; kcdb_attrib * attrib = NULL; kcdb_type * type = NULL; if(attr_id < 0 || attr_id > KCDB_ATTR_MAX_ID) return 0; cred1 = (kcdb_cred *) vcred1; cred2 = (kcdb_cred *) vcred2; kcdb_cred_lock_read(); if( !kcdb_cred_is_active_cred(vcred1) || !kcdb_cred_is_active_cred(vcred2)) goto _exit; cred1 = (kcdb_cred *) vcred1; cred2 = (kcdb_cred *) vcred2; if(KHM_FAILED(kcdb_attrib_get_info(attr_id, &attrib))) goto _exit; if(!(attrib->flags & KCDB_ATTR_FLAG_COMPUTED)) { int nc = 0; if(!kcdb_cred_val_exist(cred1, attr_id)) { code = -1; nc = 1; } if(!kcdb_cred_val_exist(cred2, attr_id)) { code += 1; nc = 1; } if(nc) goto _exit; } if(KHM_FAILED(kcdb_type_get_info(attrib->type, &type))) goto _exit; if(attrib->flags & KCDB_ATTR_FLAG_COMPUTED) { khm_octet vbuf[KCDB_MAXCB_NAME * 2]; void * buf1 = NULL; void * buf2 = NULL; khm_size cb1; khm_size cb2; code = 0; if(attrib->compute_cb(vcred1, attr_id, NULL, &cb1) != KHM_ERROR_TOO_LONG) goto _exit_1; if(attrib->compute_cb(vcred2, attr_id, NULL, &cb2) != KHM_ERROR_TOO_LONG) goto _exit_1; if(cb1) { if (cb1 < sizeof(vbuf)) buf1 = vbuf; else buf1 = PMALLOC(cb1); if(KHM_FAILED(attrib->compute_cb(vcred1, attr_id, buf1, &cb1))) goto _exit_1; } if(cb2) { if (cb1 + cb2 < sizeof(vbuf)) buf2 = vbuf + cb1; else buf2 = PMALLOC(cb2); if(KHM_FAILED(attrib->compute_cb(vcred2, attr_id, buf2, &cb2))) goto _exit_1; } code = type->comp(buf1, cb1, buf2, cb2); _exit_1: if(buf1 && (buf1 < (void *)vbuf || buf1 >= (void*)(vbuf + sizeof(vbuf)))) PFREE(buf1); if(buf2 && (buf2 < (void *)vbuf || buf2 >= (void *)(vbuf + sizeof(vbuf)))) PFREE(buf2); } else { code = type->comp( kcdb_cred_buf_get(cred1, attr_id), kcdb_cred_buf_size(cred1, attr_id), kcdb_cred_buf_get(cred2, attr_id), kcdb_cred_buf_size(cred2, attr_id)); } _exit: kcdb_cred_unlock_read(); if(attrib) kcdb_attrib_release_info(attrib); if(type) kcdb_type_release_info(type); return code; } KHMEXP khm_int32 KHMAPI kcdb_creds_is_equal(khm_handle vcred1, khm_handle vcred2) { khm_int32 code = 0; kcdb_cred * cred1; kcdb_cred * cred2; kcdb_cred_lock_read(); if(!kcdb_cred_is_active_cred(vcred1) || !kcdb_cred_is_active_cred(vcred2)) goto _exit; if(vcred1 == vcred2) { code = TRUE; goto _exit; } cred1 = vcred1; cred2 = vcred2; if(cred1->identity == cred2->identity && cred1->type == cred2->type && !wcscmp(cred1->name, cred2->name)) { kcdb_credtype * type; code = TRUE; if (KHM_SUCCEEDED(kcdb_credtype_get_info(cred1->type, &type))) { if (type->is_equal && (*type->is_equal)(vcred1, vcred2, NULL)) code = 0; kcdb_credtype_release_info(type); } } _exit: kcdb_cred_unlock_read(); return code; } KHMEXP khm_int32 KHMAPI kcdb_cred_get_flags(khm_handle vcred, khm_int32 * pflags) { khm_int32 f; khm_int32 rv = KHM_ERROR_SUCCESS; kcdb_cred * cred; int release_lock = TRUE; if (pflags == NULL) return KHM_ERROR_INVALID_PARAM; kcdb_cred_lock_read(); if (!kcdb_cred_is_active_cred(vcred)) { *pflags = 0; rv = KHM_ERROR_INVALID_PARAM; goto _exit; } cred = vcred; f = cred->flags; /* Update flags if necessary */ if (!(f & KCDB_CRED_FLAG_EXPIRED) && kcdb_cred_buf_exist(cred, KCDB_ATTR_EXPIRE)) { FILETIME ftc; GetSystemTimeAsFileTime(&ftc); if (CompareFileTime(&ftc, ((FILETIME *) kcdb_cred_buf_get(cred, KCDB_ATTR_EXPIRE))) >= 0) f |= KCDB_CRED_FLAG_EXPIRED; } #if 0 /* Commented out: if the credential has expired, then checking the renewable time is not useful */ if (!(f & KCDB_CRED_FLAG_INVALID)) { if (f & KCDB_CRED_FLAG_RENEWABLE) { if (kcdb_cred_buf_exist(cred, KCDB_ATTR_RENEW_EXPIRE)) { FILETIME ftc; GetSystemTimeAsFileTime(&ftc); if (CompareFileTime(&ftc, ((FILETIME *) kcdb_cred_buf_get(cred, KCDB_ATTR_RENEW_EXPIRE))) >= 0) f |= KCDB_CRED_FLAG_INVALID; } } else { if (f & KCDB_CRED_FLAG_EXPIRED) f |= KCDB_CRED_FLAG_INVALID; } } /* Commented out: this is a read operation. We shouldn't attempt to lock for writing */ if (f != cred->flags) { kcdb_cred_unlock_read(); kcdb_cred_lock_write(); /* Did we lose a race? */ if (kcdb_cred_is_active_cred(vcred)) cred->flags = f; else { rv = KHM_ERROR_INVALID_PARAM; f = 0; } kcdb_cred_unlock_write(); release_lock = FALSE; } #endif *pflags = f; _exit: if (release_lock) kcdb_cred_unlock_read(); return rv; } KHMEXP khm_int32 KHMAPI kcdb_cred_set_flags( khm_handle vcred, khm_int32 flags, khm_int32 mask) { khm_int32 rv = KHM_ERROR_SUCCESS; kcdb_cred * cred; kcdb_cred_lock_write(); if(!kcdb_cred_is_active_cred(vcred)) { rv = KHM_ERROR_INVALID_PARAM; goto _exit; } cred = vcred; flags &= ~(KCDB_CRED_FLAG_DELETED); mask &= ~(KCDB_CRED_FLAG_DELETED); cred->flags = (cred->flags & (~mask)) | (flags & mask); _exit: kcdb_cred_unlock_write(); return rv; }