/* * Simple (but not efficient) function to convert list of attribute,value * into an ADD_REQUEST type entry. * (e.g. ppszAttrList = { "objectclass","person", * "objectclass", "masterdiver", * "cn","my common name", * NULL}; */ static DWORD AttrListToEntry( PVDIR_SCHEMA_CTX pSchemaCtx, PSTR pszDN, PSTR* ppszAttrList, PVDIR_ENTRY pEntry) { DWORD dwError = 0; VDIR_ATTRIBUTE* pAttr = NULL; PSTR* ppszNext = NULL; assert(pSchemaCtx && pszDN && ppszAttrList && pEntry); pEntry->allocType = ENTRY_STORAGE_FORMAT_NORMAL; // establish entry schema context association pEntry->pSchemaCtx = VmDirSchemaCtxClone(pSchemaCtx); assert(pEntry->pSchemaCtx); dwError = VmDirAllocateStringA( pszDN, &pEntry->dn.lberbv.bv_val); BAIL_ON_VMDIR_ERROR(dwError); pEntry->dn.bOwnBvVal = TRUE; pEntry->dn.lberbv.bv_len = VmDirStringLenA(pEntry->dn.lberbv.bv_val); dwError = VmDirNormalizeDN( &(pEntry->dn), pSchemaCtx ); BAIL_ON_VMDIR_ERROR(dwError); for (ppszNext = ppszAttrList; *ppszNext && *(ppszNext+1); ppszNext += 2) { assert (!pAttr); if ( (*(ppszNext+1))[0] != '\0') // skip attribute with empty value { dwError = VmDirAttributeAllocate( *ppszNext, 1, pSchemaCtx, &pAttr); BAIL_ON_VMDIR_ERROR(dwError); dwError = VmDirAllocateStringA( *(ppszNext+1), &pAttr->vals[0].lberbv.bv_val); BAIL_ON_VMDIR_ERROR(dwError); pAttr->vals[0].bOwnBvVal = TRUE; pAttr->vals[0].lberbv.bv_len = VmDirStringLenA(pAttr->vals[0].lberbv.bv_val); dwError = VmDirEntryAddAttribute( pEntry, pAttr); BAIL_ON_VMDIR_ERROR(dwError); pAttr = NULL; // pEntry takes over pAttr } } cleanup: return dwError; error: if (pAttr) { VmDirFreeAttribute(pAttr); } VmDirFreeEntryContent(pEntry); memset(pEntry, 0, sizeof(*pEntry)); goto cleanup; }
//Clone a operation struct that share the same //transaction context with pOp DWORD VmDirCloneStackOperation( PVDIR_OPERATION pOp, PVDIR_OPERATION pOutOp, VDIR_OPERATION_TYPE opType, ber_tag_t requestCode, PVDIR_SCHEMA_CTX pSchemaCtx ) { DWORD dwError = 0; PVDIR_SCHEMA_CTX pLocalSchemaCtx = NULL; BAIL_ON_VMDIR_INVALID_POINTER( pOp, dwError ); BAIL_ON_VMDIR_INVALID_POINTER( pOutOp, dwError ); pOutOp->opType = opType; pOutOp->reqCode = requestCode; if ( pOutOp->reqCode == LDAP_REQ_ADD ) { dwError = VmDirAllocateMemory( sizeof(*(pOutOp->request.addReq.pEntry)), (PVOID)&(pOutOp->request.addReq.pEntry) ); BAIL_ON_VMDIR_ERROR( dwError ); } if ( pSchemaCtx ) { pLocalSchemaCtx = VmDirSchemaCtxClone( pSchemaCtx ); if ( !pLocalSchemaCtx ) { dwError = ERROR_NO_SCHEMA; BAIL_ON_VMDIR_ERROR(dwError); } } else { dwError = VmDirSchemaCtxAcquire(&pLocalSchemaCtx); BAIL_ON_VMDIR_ERROR(dwError); } dwError = VmDirAllocateAndCopyMemory(pOp->pBECtx, sizeof(*pOutOp->pBECtx ), (PVOID) &(pOutOp->pBECtx)); BAIL_ON_VMDIR_ERROR(dwError); if ( pOutOp->opType == VDIR_OPERATION_TYPE_INTERNAL ) { // needs dummy conn->VDIR_ACCESS_INFO for ACL check dwError = VmDirAllocateMemory( sizeof( *pOutOp->conn), (PVOID) &(pOutOp->conn) ); BAIL_ON_VMDIR_ERROR(dwError); } pOutOp->pSchemaCtx = pLocalSchemaCtx; pLocalSchemaCtx = NULL; cleanup: return dwError; error: if ( pLocalSchemaCtx ) { VmDirSchemaCtxRelease( pLocalSchemaCtx ); } VmDirFreeOperationContent(pOutOp); goto cleanup; }
/* DecodeEntry: Decodes an Entry that was stored using EncodeEntry. Create the Entry structure from entry->encodedEntry * string. * */ DWORD VmDirDecodeEntry( PVDIR_SCHEMA_CTX pSchemaCtx, PVDIR_ENTRY pEntry ) { DWORD dwError = 0; int len = 0; int i = 0; int j = 0; int nAttrs = 0; int nVals = 0; VDIR_ATTRIBUTE * pBeginAttr = NULL; VDIR_ATTRIBUTE * pEndAttr = NULL; VDIR_ATTRIBUTE * attr = NULL; unsigned char * strPtr = NULL; VDIR_BERVALUE * bvPtr = NULL; BOOLEAN bKeepAttr = TRUE; if (pEntry == NULL || pSchemaCtx == NULL) { dwError = ERROR_INVALID_PARAMETER; BAIL_ON_VMDIR_ERROR(dwError); } pEntry->pSchemaCtx = VmDirSchemaCtxClone(pSchemaCtx); strPtr = pEntry->encodedEntry; nAttrs = VmDirDecodeShort(&strPtr); nVals = VmDirDecodeShort(&strPtr); dwError = VmDirInitializeEntry( pEntry, ENTRY_STORAGE_FORMAT_PACK, nAttrs, nVals); BAIL_ON_VMDIR_ERROR( dwError ); bvPtr = (VDIR_BERVALUE *)pEntry->bvs; for (i = 0, attr = pEntry->attrs; i < nAttrs; attr = &(pEntry->attrs[++i])) { unsigned short usIdMap = VmDirDecodeShort(&strPtr); bKeepAttr = TRUE; // set pATDesc attr->pATDesc = VmDirSchemaAttrIdToDesc(pEntry->pSchemaCtx, usIdMap); if (attr->pATDesc == NULL) { if ( pEntry->eId == SUB_SCEHMA_SUB_ENTRY_ID && VmDirSchemaCtxIsBootStrap(pSchemaCtx) == TRUE // bootstrap ctx ) { // bootstrap schema case, ignore attributes not defined in // schema/defines.h VDIR_SCHEMA_BOOTSTRP_ATTR_INITIALIZER table // while decoding schema entry during InitializeSchema call. bKeepAttr = FALSE; } else { dwError = VMDIR_ERROR_INVALID_ATTRIBUTETYPES; BAIL_ON_VMDIR_ERROR(dwError); } } if ( bKeepAttr ) { // type.bv_val always uses in-place storage attr->type.lberbv.bv_val = attr->pATDesc->pszName; attr->type.lberbv.bv_len = VmDirStringLenA(attr->type.lberbv.bv_val); } // Keep consuming strPtr even if bKeepAttr is FALSE // Get number of attribute values j = VmDirDecodeShort(&strPtr); attr->numVals = j; attr->vals = bvPtr; // Set vals array while (j) { len = VmDirDecodeShort(&strPtr); bvPtr->lberbv.bv_len = len; bvPtr->lberbv.bv_val = (char *)strPtr; strPtr += len + 1; // Skipping \0 bvPtr++; j--; } // Set the last BerValue in vals array. bvPtr->lberbv.bv_val = NULL; bvPtr->lberbv.bv_len = 0; bvPtr++; if ( bKeepAttr ) { if (VmDirStringCompareA( attr->type.lberbv.bv_val, ATTR_DN, FALSE) == 0) { pEntry->dn = attr->vals[0]; } if ( pBeginAttr == NULL ) { pBeginAttr = attr; pEndAttr = attr; } else { pEndAttr->next = attr; pEndAttr = attr; } } } if ( pBeginAttr == NULL ) { dwError = VMDIR_ERROR_INVALID_ENTRY; BAIL_ON_VMDIR_ERROR(dwError); } // reposition pEntry->attrs to the first kept attr pEntry->attrs = pBeginAttr; pEndAttr->next = NULL; dwError = VmDirNormalizeDN( &(pEntry->dn), pSchemaCtx ); BAIL_ON_VMDIR_ERROR(dwError); cleanup: return dwError; error: VMDIR_LOG_ERROR ( VMDIR_LOG_MASK_ALL, "DecodeEntry failed (%u) DN:(%s)", dwError, pEntry ? VDIR_SAFE_STRING(pEntry->dn.lberbv.bv_val) : "unknown" ); goto cleanup; }