/* * For given DN (pszDN content will be modified), * 1. allocate ppszRDNs to hold PSTR to RDN * 2. change pszDN ',' to '\0' and have ppszRDNs[i] point to it * 3. set *piNumRDNs * * Caller should free *pppszRDNs but NOT **pppszRDNs, which point into pszDN. */ static DWORD VdirSchemaInPlaceDN2RDNs( PSTR pszDN, PSTR** pppszRDNs, int* piNumRDNs ) { DWORD dwError = 0; PSTR* ppszRDNs = NULL; int iCnt = 0; PSTR pChar = NULL; assert(pppszRDNs && piNumRDNs); for (iCnt = 0, pChar = pszDN; pChar; iCnt++) { pChar = VmDirStringChrA(pChar+1, ','); } dwError = VmDirAllocateMemory( sizeof(PSTR) * (iCnt+1), (PVOID)&ppszRDNs); BAIL_ON_VMDIR_ERROR(dwError); *piNumRDNs = iCnt; for (iCnt = 0, pChar = pszDN, ppszRDNs[0] = pszDN; pChar; iCnt++) { pChar = VmDirStringChrA(pChar+1, ','); if (pChar) { *pChar = '\0'; ppszRDNs[iCnt+1] = pChar+1; } } *pppszRDNs = ppszRDNs; cleanup: return dwError; error: VMDIR_SAFE_FREE_MEMORY(ppszRDNs); *pppszRDNs = NULL; *piNumRDNs = 0; goto cleanup; }
/* * Read schema definition from file * We only care for * attributetypes * objectclasses * ditcontentrules * attributeindices */ DWORD VmDirReadSchemaFile( PCSTR pszSchemaFilePath, PVMDIR_STRING_LIST* ppAtStrList, PVMDIR_STRING_LIST* ppOcStrList, PVMDIR_STRING_LIST* ppCrStrList, PVMDIR_STRING_LIST* ppIdxStrList ) { DWORD dwError = 0; CHAR pbuf[1024] = {0}; FILE* fp = NULL; PVMDIR_STRING_LIST pAtStrList = NULL; PVMDIR_STRING_LIST pOcStrList = NULL; PVMDIR_STRING_LIST pCrStrList = NULL; PVMDIR_STRING_LIST pIdxStrList = NULL; if (!pszSchemaFilePath || !ppAtStrList || !ppOcStrList || !ppCrStrList || !ppIdxStrList) { BAIL_WITH_VMDIR_ERROR(dwError, VMDIR_ERROR_INVALID_PARAMETER); } dwError = VmDirStringListInitialize(&pAtStrList, 2048); BAIL_ON_VMDIR_ERROR(dwError); dwError = VmDirStringListInitialize(&pOcStrList, 512); BAIL_ON_VMDIR_ERROR(dwError); dwError = VmDirStringListInitialize(&pCrStrList, 512); BAIL_ON_VMDIR_ERROR(dwError); dwError = VmDirStringListInitialize(&pIdxStrList, 16); BAIL_ON_VMDIR_ERROR(dwError); #ifndef _WIN32 fp = fopen(pszSchemaFilePath, "r"); #else if (fopen_s(&fp, pszSchemaFilePath, "r") != 0) { fp = NULL; } #endif if (NULL == fp) { dwError = errno; VMDIR_LOG_ERROR(VMDIR_LOG_MASK_ALL, "Open schema file (%s) failed. Error (%d)", pszSchemaFilePath, dwError); BAIL_ON_VMDIR_ERROR(dwError); } while (fgets(pbuf, sizeof(pbuf), fp) != NULL) { PSTR pszTag = NULL; if ((pbuf[0] == '\n') || (pbuf[0] == '#') || (pbuf[0] != ' ' && (pszTag = VmDirStringChrA(pbuf, ':')) == NULL)) { continue; } if (IS_ATTRIBUTETYPES_TAG(pbuf)) { dwError = _VmDirReadOneDefFromFile(fp, pAtStrList); BAIL_ON_VMDIR_ERROR(dwError); } else if (IS_OBJECTCLASSES_TAG(pbuf)) { dwError = _VmDirReadOneDefFromFile(fp, pOcStrList); BAIL_ON_VMDIR_ERROR(dwError); } else if (IS_CONTENTRULES_TAG(pbuf)) { dwError = _VmDirReadOneDefFromFile(fp, pCrStrList); BAIL_ON_VMDIR_ERROR(dwError); } else if (IS_ATTRIBUTEINDICES_TAG(pbuf)) { dwError = _VmDirReadOneDefFromFile(fp, pIdxStrList); BAIL_ON_VMDIR_ERROR(dwError); } else { continue; } } *ppAtStrList = pAtStrList; *ppOcStrList = pOcStrList; *ppCrStrList = pCrStrList; *ppIdxStrList = pIdxStrList; cleanup: if (fp) { fclose(fp); } return dwError; error: VmDirStringListFree(pAtStrList); VmDirStringListFree(pOcStrList); VmDirStringListFree(pCrStrList); VmDirStringListFree(pIdxStrList); goto cleanup; }
/* * This is NOT RFC 4514 compliance. * * 1. separate into RDNs * 2. for each RDN, normalize value based on its syntax * (does not handle multi-value RDN case) * remove all leading/trailing spaces * 3. reconstruct DN based on RDNs */ DWORD VmDirNormalizeDN( PVDIR_BERVALUE pBerv, PVDIR_SCHEMA_CTX pSchemaCtx ) { DWORD dwError = 0; PSTR pszTmpDN = NULL; PSTR* ppszRDNs = NULL; PSTR* ppszNormRDNs = NULL; int iNumRDNs = 0; int iCnt = 0; size_t iNormDNSize = 0; PVDIR_SCHEMA_CTX pCtx = pSchemaCtx; if (!pBerv || !pBerv->lberbv.bv_val) { dwError = ERROR_INVALID_PARAMETER; BAIL_ON_VMDIR_ERROR(dwError); } // Already normalized. => Nothing to be done. if ( pBerv->bvnorm_val != NULL ) { dwError = 0; goto cleanup; } // Nothing to be normalized for the ROOT DN if (pBerv->lberbv.bv_len == 0) { pBerv->bvnorm_val = pBerv->lberbv.bv_val; pBerv->bvnorm_len = 0; dwError = 0; goto cleanup; } if (pCtx == NULL) { dwError = VmDirSchemaCtxAcquire(&pCtx); BAIL_ON_VMDIR_ERROR(dwError); } // make a local copy dwError = VmDirAllocateStringA( pBerv->lberbv.bv_val, &pszTmpDN); BAIL_ON_VMDIR_ERROR(dwError); dwError = VdirSchemaInPlaceDN2RDNs( pszTmpDN, &ppszRDNs, &iNumRDNs); BAIL_ON_VMDIR_ERROR(dwError); dwError = VmDirAllocateMemory( sizeof(PSTR) * (iNumRDNs + 1), (PVOID)&ppszNormRDNs); BAIL_ON_VMDIR_ERROR(dwError); for (iCnt=0; ppszRDNs[iCnt] && iCnt < iNumRDNs; iCnt++) { size_t iNameLen = 0 ; VDIR_BERVALUE berval = VDIR_BERVALUE_INIT; PVDIR_SCHEMA_AT_DESC pATDesc = NULL; char* pChar = VmDirStringChrA(ppszRDNs[iCnt], '='); if (!pChar) { dwError = ERROR_INVALID_DN; BAIL_ON_VMDIR_ERROR(dwError); } *pChar = '\0'; iNameLen = VmDirStringLenA(ppszRDNs[iCnt]); // attribute name - remove all leading/trailing spaces while (ppszRDNs[iCnt][iNameLen-1] == ' ') { ppszRDNs[iCnt][iNameLen-1] = '\0'; iNameLen--; assert(iNameLen > 0); // MIN 1 char for name } while (ppszRDNs[iCnt][0] == ' ') { ppszRDNs[iCnt]++; } pATDesc = VmDirSchemaAttrNameToDesc(pCtx, ppszRDNs[iCnt]); if (!pATDesc) { dwError = ERROR_INVALID_DN; BAIL_ON_VMDIR_ERROR(dwError); } berval.lberbv.bv_val = pChar+1; berval.lberbv.bv_len = VmDirStringLenA(berval.lberbv.bv_val); dwError = VmDirSchemaBervalNormalize(pCtx, pATDesc, &berval); BAIL_ON_VMDIR_ERROR(dwError); if (berval.bvnorm_len == 0) { dwError = ERROR_INVALID_DN; BAIL_ON_VMDIR_ERROR(dwError); } if (berval.lberbv.bv_val == berval.bvnorm_val) { dwError = VmDirAllocateStringA( berval.lberbv.bv_val, &ppszNormRDNs[iCnt]); BAIL_ON_VMDIR_ERROR(dwError); } else { // ppszNormRDNs takes over bvnorm_val ppszNormRDNs[iCnt] = berval.bvnorm_val; } iNormDNSize = iNormDNSize + berval.bvnorm_len + (pChar - ppszRDNs[iCnt]) + 2; } // Reconstruct normalized DN VMDIR_SAFE_FREE_MEMORY(pBerv->bvnorm_val); pBerv->bvnorm_len = 0; dwError = VmDirAllocateMemory( sizeof(char) * (iNormDNSize+1), (PVOID)&pBerv->bvnorm_val); BAIL_ON_VMDIR_ERROR(dwError); for (iCnt = 0; ppszNormRDNs[iCnt] && iCnt < iNumRDNs; iCnt++) { size_t iValueLen = VmDirStringLenA(ppszNormRDNs[iCnt]); int iValueOffset = 0; // attribute value - remove leading/trailing spaces while (ppszNormRDNs[iCnt][iValueOffset] == ' ') { iValueOffset++; assert(iValueOffset < iValueLen); } while (ppszNormRDNs[iCnt][iValueLen-1] == ' ') { ppszNormRDNs[iCnt][iValueLen-1] = '\0'; iValueLen--; assert(iValueLen > 0); } // attribute name to lower case { char* pToLower = NULL; for (pToLower = ppszRDNs[iCnt]; *pToLower != '\0'; pToLower++) { *pToLower = (char) tolower(*pToLower); } } VmDirStringCatA(pBerv->bvnorm_val, (iNormDNSize+1), ppszRDNs[iCnt]); VmDirStringCatA(pBerv->bvnorm_val, (iNormDNSize+1), "="); VmDirStringCatA(pBerv->bvnorm_val, (iNormDNSize+1), ppszNormRDNs[iCnt]+iValueOffset); if (iCnt + 1 < iNumRDNs) { VmDirStringCatA(pBerv->bvnorm_val, (iNormDNSize+1), ","); } } pBerv->bvnorm_len = VmDirStringLenA(pBerv->bvnorm_val); cleanup: if (pCtx && pCtx != pSchemaCtx) { VmDirSchemaCtxRelease(pCtx); } VMDIR_SAFE_FREE_MEMORY(pszTmpDN); VMDIR_SAFE_FREE_MEMORY(ppszRDNs); // ppszRDNs[i] is in place of pszTmpDN VmDirFreeStringArrayA(ppszNormRDNs); VMDIR_SAFE_FREE_MEMORY(ppszNormRDNs); return dwError; error: goto cleanup; }
static int WriteAttributes( VDIR_OPERATION * op, PVDIR_ENTRY pEntry, uint32_t iSearchReqSpecialChars, BerElement * ber, PSTR* ppszErrorMsg ) { int retVal = LDAP_SUCCESS; unsigned int i = 0; SearchReq * sr = &(op->request.searchReq); BOOLEAN mapFSPDN = FALSE; PVDIR_ATTRIBUTE pAttr = NULL; PVDIR_ATTRIBUTE pRetAttrs[3] = {pEntry->attrs, pEntry->pComputedAttrs, NULL}; DWORD dwCnt = 0; PSTR pszLocalErrorMsg = NULL; // loop through both normal and computed attributes for ( dwCnt = 0, pAttr = pRetAttrs[dwCnt]; pAttr != NULL; ++dwCnt, pAttr = pRetAttrs[dwCnt]) { for ( ; pAttr != NULL; pAttr = pAttr->next ) { BOOLEAN bSendAttribute = FALSE; if (op->syncReqCtrl != NULL) // Replication, { // Filter attributes based on the input utdVector, and attribute's meta-data retVal = IsAttrInReplScope( op, pAttr->type.lberbv.bv_val, pAttr->metaData, &bSendAttribute, &pszLocalErrorMsg ); BAIL_ON_VMDIR_ERROR( retVal ); } else { // WEI: the correct way to handle this is to have attribute level 'ACL' check // For instance, the 'userPassword' attribute ACL defines: // Deny 'READ' access to everyone including administrator/admins/SELF // Possibly only allow 'backup Operators' 'READ' access // Allow 'administrator/admins' WRITE (set password) // Allow 'SELF' WRITE (reset password) // For now, do not send 'userPassword' attribute for everyone when implicitly/explicitly requested // normal ldap client search request // check if we need to return this attribute if (VmDirStringCompareA(pAttr->type.lberbv.bv_val, ATTR_USER_PASSWORD, FALSE) == 0) { if ((iSearchReqSpecialChars & LDAP_SEARCH_REQUEST_CHAR_PASSWD) != 0) { // vmdir specific - return password only if special char '-' is requested bSendAttribute = TRUE; } } else if (VmDirStringCompareA(pAttr->type.lberbv.bv_val, ATTR_KRB_MASTER_KEY, FALSE) == 0) { //only return master key if all of following conditions are satisfied if (op->showMasterKeyCtrl && // server control must be present op->conn->bIsLdaps && // must be ldaps op->conn->AccessInfo.pszNormBindedDn && // can't be anonymous VmDirStringCompareA(op->reqDn.bvnorm_val, gVmdirServerGlobals.systemDomainDN.bvnorm_val, FALSE) == 0 && // must query system domain object op->request.searchReq.scope == LDAP_SCOPE_BASE && // scope must be base op->request.searchReq.attrs != NULL && // attribute must be krbMKey only VmDirStringCompareA(op->request.searchReq.attrs[0].lberbv.bv_val, ATTR_KRB_MASTER_KEY, FALSE) == 0 && op->request.searchReq.attrs[1].lberbv.bv_val == NULL) { retVal = VmDirSrvAccessCheckIsAdminRole( //must be administrator op, op->conn->AccessInfo.pszNormBindedDn, &op->conn->AccessInfo, &bSendAttribute); BAIL_ON_VMDIR_ERROR( retVal ); } } else if ( (VmDirStringCompareA(pAttr->type.lberbv.bv_val, ATTR_VMW_STS_PASSWORD, FALSE) == 0) || (VmDirStringCompareA(pAttr->type.lberbv.bv_val, ATTR_VMW_STS_TENANT_KEY, FALSE) == 0) ) { //only admin users can read ATTR_VMW_STS_PASSWORD, ATTR_VMW_STS_TENANT_KEY attribute { retVal = VmDirSrvAccessCheckIsAdminRole( //must be administrator op, op->conn->AccessInfo.pszNormBindedDn, &op->conn->AccessInfo, &bSendAttribute); BAIL_ON_VMDIR_ERROR( retVal ); } } else if (((iSearchReqSpecialChars & LDAP_SEARCH_REQUEST_CHAR_USER) != 0) && pAttr->pATDesc->usage == VDIR_ATTRIBUTETYPE_USER_APPLICATIONS) { bSendAttribute = TRUE; // return all user attributes - "*" } else if (((iSearchReqSpecialChars & LDAP_SEARCH_REQUEST_CHAR_OP) != 0) && (pAttr->pATDesc->usage == VDIR_ATTRIBUTETYPE_DIRECTORY_OPERATION || pAttr->pATDesc->usage == VDIR_ATTRIBUTETYPE_DSA_OPERATION || pAttr->pATDesc->usage == VDIR_ATTRIBUTETYPE_DISTRIBUTED_OPERATION)) { bSendAttribute = TRUE; // return all operational attributes - "+" } else { for (i = 0; sr->attrs && sr->attrs[i].lberbv.bv_val != NULL; i++) { if (VmDirStringCompareA( sr->attrs[i].lberbv.bv_val, pAttr->type.lberbv.bv_val, FALSE) == 0) { bSendAttribute = TRUE; break; } } } } if (bSendAttribute) { if (ber_printf( ber, "{O[", &(pAttr->type) ) == -1 ) { VMDIR_LOG_VERBOSE( VMDIR_LOG_MASK_ALL, "WriteAttributes: ber_printf (to print attribute name ...) failed" ); retVal = LDAP_OTHER; BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, (pszLocalErrorMsg), "Encoding attribute type failed."); } // Non-replication/normal search request, and the attribute is FSP enabled (SJ-TBD, for now ATTR_MEMBER) if (op->syncReqCtrl == NULL && VmDirStringCompareA(pAttr->type.lberbv.bv_val, ATTR_MEMBER, FALSE) == 0) { mapFSPDN = TRUE; } else { mapFSPDN = FALSE; } if ( VmDirStringCompareA( pAttr->type.lberbv_val, ATTR_OBJECT_CLASS, FALSE ) == 0 ) { if ( op->syncReqCtrl == NULL ) // Not replication { BerValue bvOCTop = {OC_TOP_LEN, OC_TOP}; // explicitly send TOP as we don't store it in Entry/DB if (ber_printf( ber, "O", &bvOCTop ) == -1 ) { VMDIR_LOG_VERBOSE( VMDIR_LOG_MASK_ALL, "WriteAttributes: ber_printf (to print an attribute value ...) failed." ); retVal = LDAP_OTHER; BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, (pszLocalErrorMsg), "Encoding an attribute value failed."); } } // ADSI wants structure objetclass at the end to display correctly. for ( i = pAttr->numVals ; i > 0; i-- ) { if (ber_printf( ber, "O", &(pAttr->vals[i-1]) ) == -1 ) { VMDIR_LOG_VERBOSE( VMDIR_LOG_MASK_ALL, "WriteAttributes: ber_printf (to print an attribute value ...) failed." ); retVal = LDAP_OTHER; BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, (pszLocalErrorMsg), "Encoding an attribute value failed."); } } } else { for ( i = 0; i< pAttr->numVals; i++ ) { // SJ-TBD: A better/bit-more-expensive way is to Normalize the value, do GetParentDN, check if the 1st // RDN is FSP container RDN ... if (mapFSPDN && VmDirStringStrA(pAttr->vals[i].lberbv.bv_val, FSP_CONTAINER_RDN_ATTR_VALUE) != NULL) { char * tmpPos = VmDirStringChrA(pAttr->vals[i].lberbv.bv_val, ','); assert( tmpPos != NULL); *tmpPos = '\0'; pAttr->vals[i].lberbv.bv_len = tmpPos - pAttr->vals[i].lberbv.bv_val; } if (ber_printf( ber, "O", &(pAttr->vals[i]) ) == -1 ) { VMDIR_LOG_VERBOSE( VMDIR_LOG_MASK_ALL, "WriteAttributes: ber_printf (to print an attribute value ...) failed." ); retVal = LDAP_OTHER; BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, (pszLocalErrorMsg), "Encoding an attribute value failed."); } } } if ( ber_printf( ber, "]N}" ) == -1 ) { VMDIR_LOG_VERBOSE( VMDIR_LOG_MASK_ALL, "WriteAttributes: ber_printf (to terminate an attribute's values ...) failed" ); retVal = LDAP_OTHER; BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, (pszLocalErrorMsg), "Encoding terminating an attribute type failed."); } } } } cleanup: if (ppszErrorMsg) { *ppszErrorMsg = pszLocalErrorMsg; } else { VMDIR_SAFE_FREE_MEMORY(pszLocalErrorMsg); } return( retVal ); error: VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "WriteAttributes failed (%u)(%s)", retVal, VDIR_SAFE_STRING(pszLocalErrorMsg) ); goto cleanup; }
/* * APIs for HA Topology Management ends here */ DWORD VmDirClientJoinAtomic( PCSTR pszServerName, PCSTR pszUserName, PCSTR pszPassword, PCSTR pszDomainName, PCSTR pszMachineName, PCSTR pszOrgUnit, DWORD dwFlags, PVMDIR_MACHINE_INFO_A *ppMachineInfo ) { DWORD dwError = 0; PVMDIR_MACHINE_INFO_A pMachineInfo = NULL; PVMDIR_MACHINE_INFO_W pRpcMachineInfo = NULL; PVMDIR_KRB_INFO pKrbInfo = NULL; PVMDIR_KRB_INFO pRpcKrbInfo = NULL; handle_t hBinding = NULL; PSTR pszSRPUPN = NULL; PSTR pszSRPUPNAlloc = NULL; PWSTR pwszMachineName = NULL; PWSTR pwszDomainName = NULL; PWSTR pwszOrgUnit = NULL; PWSTR pwszPassword = NULL; if (IsNullOrEmptyString(pszServerName) || IsNullOrEmptyString(pszUserName) || IsNullOrEmptyString(pszPassword) || IsNullOrEmptyString(pszDomainName) || IsNullOrEmptyString(pszMachineName) || !ppMachineInfo ) { dwError = ERROR_INVALID_PARAMETER; BAIL_ON_VMDIR_ERROR(dwError); } dwError = VmDirAllocateStringWFromA( pszDomainName, &pwszDomainName ); BAIL_ON_VMDIR_ERROR(dwError); dwError = VmDirAllocateStringWFromA( pszMachineName, &pwszMachineName ); BAIL_ON_VMDIR_ERROR(dwError); if (!IsNullOrEmptyString(pszOrgUnit)) { dwError = VmDirAllocateStringWFromA( pszOrgUnit, &pwszOrgUnit ); BAIL_ON_VMDIR_ERROR(dwError); } dwError = VmDirAllocateStringWFromA( pszPassword, &pwszPassword ); BAIL_ON_VMDIR_ERROR(dwError); if (!VmDirStringChrA(pszUserName, '@')) { dwError = VmDirAllocateStringPrintf( &pszSRPUPNAlloc, "%s@%s", pszUserName, pszDomainName ); BAIL_ON_VMDIR_ERROR(dwError); pszSRPUPN = pszSRPUPNAlloc; } else { pszSRPUPN = (PSTR)pszUserName; } dwError = VmDirCreateBindingHandleAuthA( pszServerName, NULL, pszSRPUPN, NULL, pszPassword, &hBinding); BAIL_ON_VMDIR_ERROR(dwError); VMDIR_RPC_TRY { if (dwFlags & VMDIR_CLIENT_JOIN_FLAGS_PREJOINED) { dwError = RpcVmDirGetComputerAccountInfo( hBinding, pwszDomainName, pwszPassword, pwszMachineName, &pRpcMachineInfo, &pRpcKrbInfo ); } else { dwError = RpcVmDirClientJoin( hBinding, pwszDomainName, pwszMachineName, pwszOrgUnit, &pRpcMachineInfo, &pRpcKrbInfo ); } } VMDIR_RPC_CATCH { VMDIR_RPC_GETERROR_CODE(dwError); } VMDIR_RPC_ENDTRY; BAIL_ON_VMDIR_ERROR(dwError); if (pRpcKrbInfo) { dwError = _VmDirCopyFromRpcKrbInfo( pRpcKrbInfo, &pKrbInfo ); BAIL_ON_VMDIR_ERROR(dwError); dwError = VmDirWriteToKeyTabFile(pKrbInfo); BAIL_ON_VMDIR_ERROR(dwError); } dwError = _VmDirCopyFromRpcMachineInfo( pRpcMachineInfo, &pMachineInfo ); BAIL_ON_VMDIR_ERROR(dwError); dwError = VmDirConfigSetDCAccountInfo( pszMachineName, pMachineInfo->pszComputerDN, pMachineInfo->pszPassword, strlen(pMachineInfo->pszPassword), pMachineInfo->pszMachineGUID ); BAIL_ON_VMDIR_ERROR(dwError); *ppMachineInfo = pMachineInfo; cleanup: if (hBinding) { VmDirFreeBindingHandle(&hBinding); } if (pRpcKrbInfo) { VmDirClientRpcFreeKrbInfo(pRpcKrbInfo); } if (pRpcMachineInfo) { VmDirClientRpcFreeMachineInfoW(pRpcMachineInfo); } VMDIR_SAFE_FREE_MEMORY(pszSRPUPNAlloc); VMDIR_SAFE_FREE_MEMORY(pwszMachineName); VMDIR_SAFE_FREE_MEMORY(pwszDomainName); VMDIR_SAFE_FREE_MEMORY(pwszOrgUnit); VMDIR_SAFE_FREE_MEMORY(pwszPassword); return dwError; error: VMDIR_LOG_ERROR(VMDIR_LOG_MASK_ALL, "%s error (%u)", __FUNCTION__, dwError); if (ppMachineInfo) { *ppMachineInfo = NULL; } if (pMachineInfo) { VmDirFreeMachineInfoA(pMachineInfo); } goto cleanup; }
static int IsAttrInReplScope( VDIR_OPERATION * op, char * attrType, char * attrMetaData, BOOLEAN * inScope, PSTR* ppszErrorMsg ) { int retVal = LDAP_SUCCESS; PLW_HASHTABLE_NODE pNode = NULL; char origInvocationId[VMDIR_GUID_STR_LEN]; USN origUsn = VmDirStringToLA( VmDirStringRChrA( attrMetaData, ':' ) + 1, NULL, 10 ); int rc = 0; PSTR pszLocalErrorMsg = NULL; *inScope = FALSE; // attrMetaData format is: <local USN>:<version no>:<originating server ID>:<originating time>:<originating USN> VmDirStringNCpyA( origInvocationId, VMDIR_GUID_STR_LEN, VmDirStringChrA( VmDirStringChrA( attrMetaData, ':' ) + 1, ':') + 1, VMDIR_GUID_STR_LEN - 1); origInvocationId[VMDIR_GUID_STR_LEN - 1] = '\0'; // Skip the attribute: // - if the originating server for the current state is same as the requesting server or if it is one of those // attributes that have "local" scope only. E.g. sending ATTR_LAST_LOCAL_USN_PROCESSED and // ATTR_UP_TO_DATE_VECTOR, causes continuous back-forth replication of Replication Agreements and Server // entries between various servers. assert( op->syncReqCtrl != NULL ); if ((attrType != NULL && (VmDirStringCompareA( attrType, ATTR_LAST_LOCAL_USN_PROCESSED, FALSE) == 0 || VmDirStringCompareA( attrType, ATTR_UP_TO_DATE_VECTOR, FALSE) == 0 || VmDirStringCompareA( attrType, VDIR_ATTRIBUTE_SEQUENCE_RID, FALSE) == 0))) { // Reset metaData value so that we don't send local only attribute back. attrMetaData[0] = '\0'; *inScope = FALSE; goto cleanup; } else if ( attrType != NULL && (VmDirStringCompareA( attrType, ATTR_USN_CHANGED, FALSE) == 0)) { ; // always send uSNChanged. (PR 1573117) } else if (VmDirStringCompareA( origInvocationId, op->syncReqCtrl->value.syncReqCtrlVal.reqInvocationId.lberbv.bv_val,TRUE ) == 0) { // Change is originated from the requesting server. // Reset metaData value so that we don't send metaData as well as this attribute back. attrMetaData[0] = '\0'; *inScope = FALSE; goto cleanup; } else { rc = LwRtlHashTableFindKey( op->syncDoneCtrl->value.syncDoneCtrlVal.htUtdVector, &pNode, origInvocationId ); rc = LwNtStatusToWin32Error(rc); if (rc != 0 && rc != ERROR_NOT_FOUND) { VMDIR_LOG_VERBOSE( VMDIR_LOG_MASK_ALL, "IsAttrInReplScope: LwRtlHashTableFindKey failed for origInvocationId: %s", origInvocationId ); retVal = LDAP_OPERATIONS_ERROR; BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, (pszLocalErrorMsg), "LwRtlHashTableFindKey failed."); } if (pNode == NULL) // Attribute is to be sent in the result entry. { UptoDateVectorEntry * utdVectorEntry = NULL; VDIR_BERVALUE bvServerId = VDIR_BERVALUE_INIT; if (VmDirAllocateMemory( sizeof( UptoDateVectorEntry ), (PVOID *)&utdVectorEntry) != 0) { retVal = LDAP_OPERATIONS_ERROR; BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, (pszLocalErrorMsg), "IsAttrInReplScope: BervalContentDup failed."); } bvServerId.lberbv.bv_val = origInvocationId; bvServerId.lberbv.bv_len = VmDirStringLenA( origInvocationId ); if (VmDirBervalContentDup( &bvServerId, &utdVectorEntry->invocationId ) != 0) { retVal = LDAP_OPERATIONS_ERROR; BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, (pszLocalErrorMsg), "IsAttrInReplScope: BervalContentDup failed."); } utdVectorEntry->currMaxOrigUsnProcessed = origUsn; LwRtlHashTableResizeAndInsert( op->syncDoneCtrl->value.syncDoneCtrlVal.htUtdVector, &utdVectorEntry->Node, &pNode); assert( pNode == NULL ); // assert the key of added node is unique } else { UptoDateVectorEntry * utdVectorEntry = NULL; utdVectorEntry = (UptoDateVectorEntry *)LW_STRUCT_FROM_FIELD(pNode, UptoDateVectorEntry, Node); if (origUsn > utdVectorEntry->reqLastOrigUsnProcessed ) { // Attribute is to be sent in the result entry. // Update if origUsn of this attribute is > the current highest if (origUsn > utdVectorEntry->currMaxOrigUsnProcessed ) { utdVectorEntry->currMaxOrigUsnProcessed = origUsn; } } else { VMDIR_LOG_VERBOSE( LDAP_DEBUG_REPL_ATTR, "IsAttrInReplScope: Attribute: %s, metaData: %s, replication scope = FALSE", attrType, attrMetaData ); // Reset metaData value so that we don't send metaData for this attribute back. attrMetaData[0] = '\0'; *inScope = FALSE; goto cleanup; } } } VMDIR_LOG_INFO( LDAP_DEBUG_REPL_ATTR, "IsAttrInReplScope: Attribute: %s, metaData: %s, replication scope = TRUE", attrType, attrMetaData ); *inScope = TRUE; cleanup: if (ppszErrorMsg) { *ppszErrorMsg = pszLocalErrorMsg; } else { VMDIR_SAFE_FREE_MEMORY(pszLocalErrorMsg); } return( retVal ); error: goto cleanup; }
DWORD VmDirCreateAccountEx( PVMDIR_SRV_ACCESS_TOKEN pAccessToken, PVMDIR_USER_CREATE_PARAMS_RPC pCreateParams ) { DWORD dwError = 0; PVDIR_SCHEMA_CTX pSchemaCtx = NULL; VMDIR_USER_CREATE_PARAMS_W createParamsW = {0}; PVMDIR_USER_CREATE_PARAMS_A pCreateParamsA = NULL; PSTR pszName_local = NULL; // Do not free PSTR pszName = NULL; PSTR pszUPN_local = NULL; // Do not free PSTR pszUPN = NULL; PSTR pszAccountDN = NULL; PSTR pszDomain = NULL; PSTR pszDomainDN = NULL; PSTR pszUpperDomain = NULL; DWORD i = 0; dwError = VmDirSrvValidateUserCreateParams(pCreateParams); BAIL_ON_VMDIR_ERROR(dwError); createParamsW.pwszName = pCreateParams->pwszName; createParamsW.pwszAccount = pCreateParams->pwszAccount; createParamsW.pwszUPN = pCreateParams->pwszUPN; createParamsW.pwszFirstname = pCreateParams->pwszFirstname; createParamsW.pwszLastname = pCreateParams->pwszLastname; createParamsW.pwszPassword = pCreateParams->pwszPassword; dwError = VmDirAllocateUserCreateParamsAFromW( &createParamsW, &pCreateParamsA); BAIL_ON_VMDIR_ERROR(dwError); if (IsNullOrEmptyString(pCreateParamsA->pszName)) { dwError = VmDirAllocateStringPrintf( &pszName, "%s %s", pCreateParamsA->pszFirstname, pCreateParamsA->pszLastname); BAIL_ON_VMDIR_ERROR(dwError); pszName_local = pszName; } else { pszName_local = pCreateParamsA->pszName; } dwError = VmDirSrvGetCallerDomain(pAccessToken, &pszDomain); BAIL_ON_VMDIR_ERROR(dwError); if (IsNullOrEmptyString(pCreateParamsA->pszUPN)) { if (VmDirStringChrA(pCreateParamsA->pszAccount, '@') == NULL) { dwError = VmDirAllocateStringPrintf( &pszUpperDomain, "%s", pszDomain); BAIL_ON_VMDIR_ERROR(dwError); for (i=0; pszUpperDomain[i]; i++) { VMDIR_ASCII_LOWER_TO_UPPER(pszUpperDomain[i]); } dwError = VmDirAllocateStringPrintf( &pszUPN, "%s@%s", pCreateParamsA->pszAccount, pszUpperDomain); BAIL_ON_VMDIR_ERROR(dwError); } else { dwError = VmDirAllocateStringA(pCreateParamsA->pszAccount, &pszUPN); BAIL_ON_VMDIR_ERROR(dwError); } pszUPN_local = pszUPN; } else { pszUPN_local = pCreateParamsA->pszUPN; } dwError = VmDirFQDNToDN(pszDomain, &pszDomainDN); BAIL_ON_VMDIR_ERROR(dwError); dwError = VmDirAllocateStringPrintf( &pszAccountDN, "CN=%s,%s,%s", pszName_local, DEFAULT_USER_CONTAINER_RDN, pszDomainDN); BAIL_ON_VMDIR_ERROR(dwError); do { PSTR ppszAttributes[] = { ATTR_OBJECT_CLASS, (PSTR)OC_USER, ATTR_CN, pszName_local, ATTR_USER_PASSWORD, pCreateParamsA->pszPassword, ATTR_SAM_ACCOUNT_NAME, pCreateParamsA->pszAccount, ATTR_KRB_UPN, pszUPN_local, ATTR_SN, pCreateParamsA->pszLastname, ATTR_GIVEN_NAME, pCreateParamsA->pszFirstname, NULL }; dwError = VmDirSchemaCtxAcquire( &pSchemaCtx ); BAIL_ON_VMDIR_ERROR(dwError); dwError = VmDirSimpleEntryCreate( pSchemaCtx, ppszAttributes, pszAccountDN, 0); BAIL_ON_VMDIR_ERROR(dwError); } while (0); cleanup: VmDirSchemaCtxRelease(pSchemaCtx); VMDIR_SAFE_FREE_MEMORY(pszName); VMDIR_SAFE_FREE_MEMORY(pszUPN); VMDIR_SAFE_FREE_MEMORY(pszDomain); VMDIR_SAFE_FREE_MEMORY(pszDomainDN); VMDIR_SAFE_FREE_MEMORY(pszAccountDN); VMDIR_SAFE_FREE_MEMORY(pszUpperDomain); if (pCreateParamsA) { VmDirFreeUserCreateParamsA(pCreateParamsA); } return dwError; error: VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "VmDirCreateAccountEx Account(%s) failed, (%u)", VDIR_SAFE_STRING(pCreateParamsA ? pCreateParamsA->pszAccount : NULL), dwError); goto cleanup; }
static int ParseSyncRequestControlVal( VDIR_OPERATION * op, BerValue * controlValue, // Input: control value encoded as ber SyncRequestControlValue * syncReqCtrlVal, // Output VDIR_LDAP_RESULT * lr // Output ) { int retVal = LDAP_SUCCESS; ber_tag_t tag = LBER_ERROR; ber_len_t len = 0; UptoDateVectorEntry * utdVectorEntry = NULL; BerElementBuffer berbuf; BerElement * ber = (BerElement *)&berbuf; PSTR pszLocalErrorMsg = NULL; VDIR_BACKEND_CTX backendCtx = {0}; USN maxPartnerVisibleUSN = 0; VMDIR_LOG_DEBUG( LDAP_DEBUG_TRACE, "ParseSyncRequestControlVal: Begin." ); ber_init2( ber, controlValue, LBER_USE_DER ); /* http://www.rfc-editor.org/rfc/rfc4533.txt * * syncCookie ::= OCTET STRING * * syncRequestValue ::= SEQUENCE { * mode ENUMERATED { * -- 0 unused * refreshOnly (1), * -- 2 reserved * refreshAndPersist (3) * }, * cookie syncCookie OPTIONAL, * reloadHint BOOLEAN DEFAULT FALSE * } */ if (ber_scanf( ber, "{i", &(syncReqCtrlVal->mode) ) == LBER_ERROR) { VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "ParseSyncRequestControlVal: ber_scanf failed while parsing the sync request " "control mode" ); lr->errCode = LDAP_PROTOCOL_ERROR; retVal = LDAP_NOTICE_OF_DISCONNECT; BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, (pszLocalErrorMsg), "Error in reading sync request control mode from PDU."); } syncReqCtrlVal->bvLastLocalUsnProcessed.lberbv.bv_val = ""; syncReqCtrlVal->intLastLocalUsnProcessed = 0; if (VmDirAllocateMemory( sizeof( VDIR_LDAP_CONTROL ), (PVOID *)&op->syncDoneCtrl) != 0) { VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "ParseSyncRequestControlVal: VmDirAllocateMemory failed " ); lr->errCode = retVal = LDAP_OPERATIONS_ERROR; BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, (pszLocalErrorMsg), "ParseSyncRequestControlVal: VmDirAllocateMemory failed."); } op->syncDoneCtrl->type = LDAP_CONTROL_SYNC_DONE; if (LwRtlCreateHashTable( &op->syncDoneCtrl->value.syncDoneCtrlVal.htUtdVector, UtdVectorEntryGetKey, LwRtlHashDigestPstr, LwRtlHashEqualPstr, NULL, VMDIR_UTD_VECTOR_HASH_TABLE_SIZE ) != 0) { VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "UpdateSyncDoneUtdVectorEntry: LwRtlCreateHashTable failed" ); lr->errCode = retVal = LDAP_OPERATIONS_ERROR; BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, (pszLocalErrorMsg), "UpdateSyncDoneUtdVectorEntry: LwRtlCreateHashTable failed"); } tag = ber_peek_tag( ber, &len ); if (tag == LBER_SEQUENCE) { // syncCookie /* syncCookie ::= SEQUENCE { * reqServerId LDAPString, * lastLocalUsnProcessed INTEGER (0 .. maxInt), * utdVector UptoDateVectorEntryList } * * UptoDateVectorEntryList ::= SEQUENCE OF uptoDateVectorEntry UptoDateVectorEntry * * UptoDateVectorEntry ::= SEQUENCE { * serverId LDAPString, * lastOrigUsnProcessed INTEGER (0 .. maxInt) } */ // {lastLocalUsnProcessed{{<serverid1><lastOrigUsnProcessed1>}{<serverid2><lastOrigUsnProcessed2>}...}} if (ber_scanf( ber, "{mmm}", &syncReqCtrlVal->reqInvocationId.lberbv, &syncReqCtrlVal->bvLastLocalUsnProcessed.lberbv, &syncReqCtrlVal->bvUtdVector.lberbv ) == LBER_ERROR ) { VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "ParseSyncRequestControlVal: ber_scanf failed while parsing " "lastLocalUsnProcessed in the sync request control value" ); lr->errCode = LDAP_PROTOCOL_ERROR; retVal = LDAP_NOTICE_OF_DISCONNECT; BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, (pszLocalErrorMsg), "Error in reading lastLocalUsnProcessed in the sync request control value"); } VMDIR_LOG_DEBUG( LDAP_DEBUG_REPL, "ParseSyncRequestControlVal: ServerId: %s, lastLocalUsnProcessed: %s, utdVector: %s", syncReqCtrlVal->reqInvocationId.lberbv.bv_val, syncReqCtrlVal->bvLastLocalUsnProcessed.lberbv.bv_val, syncReqCtrlVal->bvUtdVector.lberbv.bv_val ); syncReqCtrlVal->intLastLocalUsnProcessed = op->syncDoneCtrl->value.syncDoneCtrlVal.intLastLocalUsnProcessed = VmDirStringToLA( syncReqCtrlVal->bvLastLocalUsnProcessed.lberbv.bv_val, NULL, 10 ); { char * nextServerIdStr = NULL; char * nextOrigUsnStr = NULL; nextServerIdStr = syncReqCtrlVal->bvUtdVector.lberbv.bv_val; while( nextServerIdStr != NULL && nextServerIdStr[0] != '\0') { PLW_HASHTABLE_NODE pNode = NULL; if (VmDirAllocateMemory( sizeof(UptoDateVectorEntry), (PVOID *)&utdVectorEntry ) != 0) { VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "ParseSyncRequestControlVal: VmDirAllocateMemory failed " ); lr->errCode = retVal = LDAP_OPERATIONS_ERROR; BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, (pszLocalErrorMsg), "ParseSyncRequestControlVal: VmDirAllocateMemory failed"); } nextOrigUsnStr = VmDirStringChrA( nextServerIdStr, ':'); *nextOrigUsnStr = '\0'; nextOrigUsnStr++; utdVectorEntry->invocationId.lberbv.bv_val = nextServerIdStr; utdVectorEntry->invocationId.lberbv.bv_len = VmDirStringLenA( nextServerIdStr ); nextServerIdStr = VmDirStringChrA( nextOrigUsnStr, ','); *nextServerIdStr = '\0'; nextServerIdStr++; utdVectorEntry->currMaxOrigUsnProcessed = utdVectorEntry->reqLastOrigUsnProcessed = atol( nextOrigUsnStr ); LwRtlHashTableResizeAndInsert( op->syncDoneCtrl->value.syncDoneCtrlVal.htUtdVector, &utdVectorEntry->Node, &pNode); assert( pNode == NULL ); // assert the key of added node is unique. } } tag = ber_peek_tag( ber, &len ); } if (tag == LBER_BOOLEAN) { ber_int_t reloadHint; if (ber_scanf( ber, "b", &reloadHint) == LBER_ERROR) { VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "ParseSyncRequestControlVal: Error in reading reloadHint from the PDU" ); lr->errCode = LDAP_PROTOCOL_ERROR; retVal = LDAP_NOTICE_OF_DISCONNECT; BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, (pszLocalErrorMsg), "Error in reading reloadHint from the PDU."); } if (reloadHint) { syncReqCtrlVal->reloadHint = TRUE; } } if ( ber_scanf( ber, "}") == LBER_ERROR ) // End of control value { VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "ParseSyncRequestControlVal: ber_scanf failed while parsing the end of " "sync request control value." ); lr->errCode = LDAP_PROTOCOL_ERROR; retVal = LDAP_NOTICE_OF_DISCONNECT; BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, (pszLocalErrorMsg), "Decoding error while parsing the end of sync request control value."); } backendCtx.pBE = VmDirBackendSelect(""); maxPartnerVisibleUSN = backendCtx.pBE->pfnBEGetLeastOutstandingUSN( &backendCtx, FALSE ) - 1; if (syncReqCtrlVal->intLastLocalUsnProcessed > maxPartnerVisibleUSN) { VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "ParseSyncRequestControlVal: ServerId %s has processed my USN (%u), my max USN is (%u).", syncReqCtrlVal->reqInvocationId.lberbv.bv_val, syncReqCtrlVal->intLastLocalUsnProcessed, maxPartnerVisibleUSN ); lr->errCode = LDAP_UNWILLING_TO_PERFORM; retVal = LDAP_NOTICE_OF_DISCONNECT; BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, (pszLocalErrorMsg), "Partner is ahead of my changes."); } cleanup: // Even in the error case, syncDoneCtrl should be freed during operation delete. VMDIR_LOG_DEBUG( LDAP_DEBUG_TRACE, "ParseSyncRequestControlVal: End." ); VmDirBackendCtxContentFree( &backendCtx ); VMDIR_SAFE_FREE_MEMORY(pszLocalErrorMsg); return retVal; error: VMDIR_APPEND_ERROR_MSG(lr->pszErrMsg, pszLocalErrorMsg); goto cleanup; }
//TODO_REMOVE_REPLV2 DWORD VmDirAttributeMetaDataToHashMap( PVDIR_ATTRIBUTE pAttrAttrMetaData, PLW_HASHMAP* ppMetaDataMap ) { DWORD dwError = 0; DWORD dwCnt = 0; PLW_HASHMAP pMetaDataMap = NULL; PSTR pszKey = NULL; PVMDIR_ATTRIBUTE_METADATA pMetaData = NULL; if (!pAttrAttrMetaData || !ppMetaDataMap) { BAIL_WITH_VMDIR_ERROR(dwError, VMDIR_ERROR_INVALID_PARAMETER); } dwError = LwRtlCreateHashMap( &pMetaDataMap, LwRtlHashDigestPstrCaseless, LwRtlHashEqualPstrCaseless, NULL); BAIL_ON_VMDIR_ERROR(dwError); for (dwCnt = 0; pAttrAttrMetaData->vals[dwCnt].lberbv.bv_val != NULL; dwCnt++) { // Format is: <attr name>:<local USN>:<version no>:<originating server ID>:<originating time>:<originating USN> char* pszMetaData = VmDirStringChrA(pAttrAttrMetaData->vals[dwCnt].lberbv.bv_val, ':'); if (pszMetaData == NULL) { BAIL_WITH_VMDIR_ERROR(dwError, VMDIR_ERROR_BACKEND_INVALID_METADATA); } // pszMetaData now points to <local USN>... pszMetaData++; //pAttrAttrMetaData->vals[i] has <attr type>\0<pszMetaData> *(pszMetaData - 1) = '\0'; dwError = VmDirAllocateStringA(pAttrAttrMetaData->vals[dwCnt].lberbv.bv_val, &pszKey); BAIL_ON_VMDIR_ERROR(dwError); dwError = VmDirMetaDataDeserialize(pszMetaData, &pMetaData); BAIL_ON_VMDIR_ERROR(dwError); dwError = LwRtlHashMapInsert(pMetaDataMap, pszKey, pMetaData, NULL); BAIL_ON_VMDIR_ERROR(dwError); pszKey = NULL; pMetaData = NULL; } *ppMetaDataMap = pMetaDataMap; cleanup: return dwError; error: if (pMetaDataMap) { LwRtlHashMapClear( pMetaDataMap, VmDirFreeMetaDataMapPair, NULL); LwRtlFreeHashMap(&pMetaDataMap); } VmDirFreeMetaData(pMetaData); VMDIR_SAFE_FREE_MEMORY(pszKey); VMDIR_LOG_ERROR(VMDIR_LOG_MASK_ALL, "failed, error (%d)", dwError); goto cleanup; }
/* * Read schema definition from file * We ignore - * 1. DN/EntryDN * 2. ldapSyntax * 3. matchingRules */ static DWORD schemaReadFile( PCSTR pszSchemaFilePath, PSTR** pppszDescs, USHORT* pdwSize ) { static PSTR pszDNTag = "DN:"; static PSTR pszENTRYDNTag = "ENTRYDN:"; static PSTR pszSyntaxTag = "ldapSyntaxes:"; static PSTR pszMatchingRuleTag = "matchingRules:"; static PSTR pszName = "NAME "; DWORD dwError = 0; USHORT dwSize = 0; DWORD dwCnt = 100; size_t iOldLen = 0 ; size_t iNewLen = 0 ; PSTR* ppszDescs = NULL; PSTR pszTmp = NULL; char pbuf[2048] = {0}; FILE* fp = NULL; dwError = VmDirAllocateMemory( sizeof(*ppszDescs) * dwCnt, (PVOID*)&ppszDescs); BAIL_ON_VMDIR_ERROR(dwError); #ifndef _WIN32 fp=fopen(pszSchemaFilePath, "r"); #else if( fopen_s(&fp, pszSchemaFilePath, "r") != 0 ) { fp = NULL; } #endif if(NULL == fp) { dwError = errno; VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "Open schema file (%s) failed. Error (%d)", pszSchemaFilePath, dwError); BAIL_ON_VMDIR_ERROR(dwError); } while (fgets(pbuf, sizeof(pbuf), fp) != NULL) { PSTR pszTag = NULL; size_t len = VmDirStringLenA(pbuf)-1; if (pbuf[len] == '\n') { pbuf[len] = '\0'; } if ((pbuf[0] == '\0') || (pbuf[0] == '#') || (pbuf[0] != ' ' && (pszTag = VmDirStringChrA(pbuf, ':')) == NULL)) { continue; } if (VmDirStringNCompareA(pbuf, pszDNTag, VmDirStringLenA(pszDNTag), FALSE) == 0 || VmDirStringNCompareA(pbuf, pszENTRYDNTag, VmDirStringLenA(pszENTRYDNTag), FALSE) == 0 || VmDirStringNCompareA(pbuf, pszSyntaxTag, VmDirStringLenA(pszSyntaxTag), FALSE) == 0 || VmDirStringNCompareA(pbuf, pszMatchingRuleTag, VmDirStringLenA(pszMatchingRuleTag), FALSE) == 0) { continue; } if (dwCnt == dwSize + 1) { DWORD dwOldSize = dwCnt; dwCnt = dwCnt * 2; dwError = VmDirReallocateMemoryWithInit( ppszDescs, (PVOID*)&ppszDescs, dwCnt * sizeof(*ppszDescs), dwOldSize * sizeof(*ppszDescs)); BAIL_ON_VMDIR_ERROR(dwError); } if (pbuf[0] != ' ') { dwError = VmDirAllocateStringA(pbuf, &(ppszDescs[dwSize++])); BAIL_ON_VMDIR_ERROR(dwError); } else { // consolidate leading spaces into one char* pszNonSpace = pbuf+1; while (*pszNonSpace == ' ') { pszNonSpace++; } { // Normalising NAME field for everything attributeTypes,objectClasses,ditContentRules , i.e Removing multiple spaces if (VmDirStringNCompareA(pszNonSpace, pszName, VmDirStringLenA(pszName), TRUE) == 0) { _VmDirNormaliseNameField (pszNonSpace, VmDirStringLenA(pszNonSpace)); } iOldLen = VmDirStringLenA(ppszDescs[dwSize-1]); iNewLen = VmDirStringLenA(pszNonSpace-1); dwError = VmDirReallocateMemoryWithInit( ppszDescs[dwSize-1], (PVOID*)&pszTmp, sizeof(char) * (iOldLen + iNewLen + 1), sizeof(char) * iOldLen); BAIL_ON_VMDIR_ERROR(dwError); dwError = VmDirCopyMemory( &pszTmp[iOldLen], sizeof(char) * (iOldLen + iNewLen + 1), &(pszNonSpace-1)[0], iNewLen ); BAIL_ON_VMDIR_ERROR(dwError); ppszDescs[dwSize-1] = pszTmp; pszTmp = NULL; } } } *pppszDescs = ppszDescs; *pdwSize = dwSize; cleanup: if (fp) { fclose(fp); } return dwError; error: *pppszDescs = NULL; *pdwSize = 0; if (ppszDescs) { VmDirFreeStringArrayA(ppszDescs); VMDIR_SAFE_FREE_MEMORY(ppszDescs); } goto cleanup; }
/* * convert schema file into entry */ DWORD VmDirSchemaInitalizeFileToEntry( PCSTR pszSchemaFilePath, PVDIR_ENTRY* ppEntry ) { DWORD dwError = 0; USHORT dwCnt = 0; PVDIR_ENTRY pEntry = NULL; PSTR pszTag = NULL; PSTR pszTagEnd = NULL; USHORT dwTag = 0; PSTR* ppszDescs = NULL; USHORT dwDescSize = 0; PSTR* ppszSyntaxes = NULL; USHORT dwSyntaxSize = 0; PSTR* ppszMRs = NULL; USHORT dwMRSize = 0; PVDIR_SCHEMA_CTX pCtx = NULL; if ( !pszSchemaFilePath || !ppEntry ) { dwError = ERROR_INVALID_PARAMETER; BAIL_ON_VMDIR_ERROR(dwError); } dwError = schemaReadFile( pszSchemaFilePath, &ppszDescs, &dwDescSize); BAIL_ON_VMDIR_ERROR(dwError); // sort ppszDescs by tag order (i.e. ats, ocs, syntax...) qsort(ppszDescs, dwDescSize, sizeof(*ppszDescs), schemaInitPPSTRCmp); dwError = VmDirSchemaCtxAcquire(&pCtx); BAIL_ON_VMDIR_ERROR(dwError); dwError = VmDirAllocateMemory( sizeof(VDIR_ENTRY), (PVOID*)&pEntry); BAIL_ON_VMDIR_ERROR(dwError); dwError = VmDirAllocateStringA( SUB_SCHEMA_SUB_ENTRY_DN, &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), pCtx ); BAIL_ON_VMDIR_ERROR(dwError); pEntry->allocType = ENTRY_STORAGE_FORMAT_NORMAL; // load every thing from file except EntryDN, ldapSyntaxes and matchingRules { // By now, we know all PSTR have format - "tag: value" for (dwCnt=0; dwCnt < dwDescSize; dwCnt++) { PSTR pszNewTag = ppszDescs[dwCnt]; PSTR pszNewTagEnd = VmDirStringChrA(ppszDescs[dwCnt], ':'); if (pszTag == NULL) { pszTag = pszNewTag; pszTagEnd = pszNewTagEnd; dwTag = dwCnt; continue; } if (((pszTagEnd - pszTag) == (pszNewTagEnd - pszNewTag)) && VmDirStringNCompareA(pszTag, pszNewTag, pszTagEnd - pszTag, TRUE) == 0) { continue; } else { dwError = schemaInitFillAttrFromFile( pCtx, ppszDescs+dwTag, dwCnt - dwTag, pszTag, pszTagEnd - pszTag, pEntry); BAIL_ON_VMDIR_ERROR(dwError); pszTag = pszNewTag; pszTagEnd = pszNewTagEnd; dwTag = dwCnt; } } dwError = schemaInitFillAttrFromFile( pCtx, ppszDescs+dwTag, dwCnt - dwTag, pszTag, pszTagEnd - pszTag, pEntry); BAIL_ON_VMDIR_ERROR(dwError); } dwError = VdirSyntaxGetDefinition( &ppszSyntaxes, &dwSyntaxSize); BAIL_ON_VMDIR_ERROR(dwError); dwError = schemaInitFillAttrFromCache( pCtx, ppszSyntaxes, dwSyntaxSize, VDIR_ATTRIBUTE_LADPSYNTAXES, pEntry); BAIL_ON_VMDIR_ERROR(dwError); dwError = VdirMatchingRuleGetDefinition( &ppszMRs, &dwMRSize); BAIL_ON_VMDIR_ERROR(dwError); dwError = schemaInitFillAttrFromCache( pCtx, ppszMRs, dwMRSize, VDIR_ATTRIBUTE_MATCHINGRULES, pEntry); BAIL_ON_VMDIR_ERROR(dwError); pEntry->eId = SUB_SCEHMA_SUB_ENTRY_ID; // NOTE, entry is only partially constructed to bootstrap schema *ppEntry = pEntry; cleanup: if (pCtx) { VmDirSchemaCtxRelease(pCtx); } if (ppszDescs) { VmDirFreeStringArrayA(ppszDescs); VMDIR_SAFE_FREE_MEMORY(ppszDescs); } if (ppszSyntaxes) { VmDirFreeStringArrayA(ppszSyntaxes); VMDIR_SAFE_FREE_MEMORY(ppszSyntaxes); } if (ppszMRs) { VmDirFreeStringArrayA(ppszMRs); VMDIR_SAFE_FREE_MEMORY(ppszMRs); } return dwError; error: if (pEntry) { VmDirFreeEntry(pEntry); } goto cleanup; }