Beispiel #1
0
/*
 * 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;
}
Beispiel #2
0
/*
 * 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;
}
Beispiel #3
0
/*
 * 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;

}