int LoadPolicy()

in lsvmutils/policy.c [304:468]


int LoadPolicy(
    const char* path,
    Policy* policy,
    Error* err)
{
    int rc = -1;
    UINT32 line = 1;
    const char* file = path;
    StrArr arr = STRARR_INITIALIZER;
    UINTN i;

    ClearErr(err);

    /* Check for null parameters */
    if (!path || !policy)
    {
        SetErr(err, "invalid parametrer");
        goto done;
    }

    /* Clear the policy */
    Memset(policy, 0, sizeof(Policy));

    /* Read file(s) into string array */
    if (_ReadFile(path, &arr, err) != 0)
    {
        goto done;
    }

    /* Read line-by-line */
    for (i = 0; i < arr.size; i++)
    {
        char* p = arr.data[i];
        PolicyEntry ent;

        /* Handle line directives */
        if (Strncmp(p, "#line", sizeof("#line") - 1) == 0)
        {
            const char* tmpFile = NULL;
            UINT32 tmpLine = 0;

            if (!(tmpFile = _ParseLineDirective(p, &tmpLine)))
            {
                SetErr(err, "%s(%u): invalid line directive", file, line);
                goto done;
            }

            file = tmpFile;
            line = tmpLine;
            continue;
        }

        /* Skip comment lines */
        if (p[0] == '#')
        {
            line++;
            continue;
        }

        /* Too many entries */
        if (policy->nentries == POLICY_MAX_ENTRIES)
        {
            SetErr(err, "%s(%u): too many entries", file, line);
            goto done;
        }

        /* Remove trailing whitespace */
        {
            char* end = p + strlen(p);

            while (end != p && isspace(end[-1]))
                *--end = '\0';
        }

        /* PolicyEntry.path */
        {
            const char* name;
            char tmp[POLICY_MAX_LINE];

            if (!(name = _GetNextField(&p)))
            {
                SetErr(err, "%s(%u): syntax: expected file", file, line);
                goto done;
            }

            /* Get the name */
            Strlcpy(tmp, name, sizeof(tmp));

            /* Expand any environment variables */
            if (ExpandEnvVars(ent.path, sizeof(ent.path), tmp) != 0)
            {
                SetErr(err, "%s(%u): failed to expand variables", file, line);
                goto done;
            }
        }

        /* PolicyEntry.type */
        {
            const char* type;
            
            if (!(type = _GetNextField(&p)))
            {
                SetErr(err, "%s(%u): syntax: expected type", file, line);
                goto done;
            }

            if (strcmp(type, "PEIMAGE") == 0)
                ent.type = POLICY_PEIMAGE;
            else if (strcmp(type, "BINARY") == 0)
                ent.type = POLICY_BINARY;
            else if (strcmp(type, "BINARY32") == 0)
                ent.type = POLICY_BINARY32;
            else if (strcmp(type, "EFIVAR") == 0)
                ent.type = POLICY_EFIVAR;
            else if (strcmp(type, "CAP") == 0)
                ent.type = POLICY_CAP;
            else if (strcmp(type, "PCR") == 0)
                ent.type = POLICY_PCR;
            else
            {
                SetErr(err, "%s(%u): bad hash type: %s", file, line, type);
                goto done;
            }
        }

        /* PolicyEntry.pcr */
        {
            const char* pcrStr;
            
            if (!(pcrStr = _GetNextField(&p)))
            {
                SetErr(err, "%s(%u): syntax: expected PCR", file, line);
                goto done;
            }

            char* end = NULL;
            unsigned long pcr = strtoul(pcrStr, &end, 10);

            if (!end || *end != '\0' || pcr >= MAX_PCRS)
            {
                SetErr(err, "%s(%u): bad PCR index: %s", file, line, pcrStr);
                goto done;
            }

            ent.pcr = (UINT32)pcr;
        }

        if (*p != '\0')
        {
            SetErr(err, "%s(%u): extraneous characters", file, line);
            goto done;
        }

        policy->entries[policy->nentries++] = ent;
        line++;
    }

    rc = 0;

done:

    StrArrRelease(&arr);

    return rc;
}