Esempio n. 1
0
File: modes.c Progetto: lra/core
int ParseModeString(const char *modestring, mode_t *plusmask, mode_t *minusmask)
{
    int affected = 0, value = 0, gotaction, no_error = true;
    char action = '=';
    enum modestate state = wild;
    enum modesort found_sort = unknown; /* Already found "sort" of mode */
    enum modesort sort = unknown;       /* Sort of started but not yet finished mode */

    *plusmask = *minusmask = 0;

    if (modestring == NULL)
    {
        return true;
    }

    gotaction = false;

    for (const char *sp = modestring; true; sp++)
    {
        switch (*sp)
        {
        case 'a':
            no_error = CheckModeState(who, state, symbolic, sort, *sp);
            affected |= 07777;
            sort = symbolic;
            break;

        case 'u':
            no_error = CheckModeState(who, state, symbolic, sort, *sp);
            affected |= 04700;
            sort = symbolic;
            break;

        case 'g':
            no_error = CheckModeState(who, state, symbolic, sort, *sp);
            affected |= 02070;
            sort = symbolic;
            break;

        case 'o':
            no_error = CheckModeState(who, state, symbolic, sort, *sp);
            affected |= 00007;
            sort = symbolic;
            break;

        case '+':
        case '-':
        case '=':
            if (gotaction)
            {
                Log(LOG_LEVEL_ERR, "Too many +-= in mode string");
                return false;
            }

            no_error = CheckModeState(who, state, symbolic, sort, *sp);
            action = *sp;
            state = which;
            gotaction = true;
            sort = unknown;
            break;

        case 'r':
            no_error = CheckModeState(which, state, symbolic, sort, *sp);
            value |= 0444 & affected;
            sort = symbolic;
            break;

        case 'w':
            no_error = CheckModeState(which, state, symbolic, sort, *sp);
            value |= 0222 & affected;
            sort = symbolic;
            break;

        case 'x':
            no_error = CheckModeState(which, state, symbolic, sort, *sp);
            value |= 0111 & affected;
            sort = symbolic;
            break;

        case 's':
            no_error = CheckModeState(which, state, symbolic, sort, *sp);
            value |= 06000 & affected;
            sort = symbolic;
            break;

        case 't':
            no_error = CheckModeState(which, state, symbolic, sort, *sp);
            value |= 01000;
            sort = symbolic;
            break;

        case '0':
        case '1':
        case '2':
        case '3':
        case '4':
        case '5':
        case '6':
        case '7':
            no_error = CheckModeState(which, state, numeric, sort, *sp);
            sort = numeric;
            gotaction = true;
            state = which;
            affected = 07777;   /* TODO: Hard-coded; see below */
            sscanf(sp, "%o", &value);

            if (value & S_IFMT)
            {
                Log(LOG_LEVEL_INFO, "Mode-Value is not entirely within the system's allowed permissions (octal %o) and will be filtered accordingly : %s",
                    S_IFMT, modestring);
            }

            /* stat() returns the file types in the mode, but they
             * can't be set.  So we clear the file-type as per POSIX
             * 2001 instead of erroring out, leaving just the
             * permissions. */
            value &= ~S_IFMT;
            
            if (value > 07777)  /* TODO: Hardcoded !
                                   Is this correct for all sorts of Unix ?
                                   What about NT ?
                                   Any (POSIX)-constants ??
                                 */
            {
                Log(LOG_LEVEL_ERR, "Mode-Value too big : %s", modestring);
                return false;
            }

            while ((isdigit((int) *sp)) && (*sp != '\0'))
            {
                sp++;
            }
            sp--;
            break;

        case ',':
            if (!SetModeMask(action, value, affected, plusmask, minusmask))
            {
                return false;
            }

            if ((found_sort != unknown) && (found_sort != sort))
            {
                Log(LOG_LEVEL_INFO, "Symbolic and numeric form for modes mixed");
            }

            found_sort = sort;
            sort = unknown;
            action = '=';
            affected = 0;
            value = 0;
            gotaction = false;
            state = who;
            break;

        case '\0':
            if ((state == who) || (value == 0))
            {
                if ((strcmp(modestring, "0000") != 0) && (strcmp(modestring, "000") != 0))
                {
                    Log(LOG_LEVEL_ERR, "mode string is incomplete");
                    return false;
                }
            }

            if (!SetModeMask(action, value, affected, plusmask, minusmask))
            {
                return false;
            }

            if ((found_sort != unknown) && (found_sort != sort))
            {
                Log(LOG_LEVEL_INFO, "Symbolic and numeric form for modes mixed");
            }

            Log(LOG_LEVEL_DEBUG, "Modestring [PLUS = %" PRIoMAX "] [MINUS = %" PRIoMAX "]", (uintmax_t)*plusmask, (uintmax_t)*minusmask);
            return true;

        default:
            Log(LOG_LEVEL_ERR, "Invalid mode string (%s)", modestring);
            return false;
        }
    }

    if (!no_error)
    {
        Log(LOG_LEVEL_ERR, "Error validating mode string %s", modestring);
    }

    return no_error;
}
Esempio n. 2
0
File: modes.c Progetto: frerich/core
int ParseModeString(const char *modestring, mode_t *plusmask, mode_t *minusmask)
{
    int affected = 0, value = 0, gotaction, no_error = true;
    char action = '=';
    enum modestate state = wild;
    enum modesort found_sort = unknown; /* Already found "sort" of mode */
    enum modesort sort = unknown;       /* Sort of started but not yet finished mode */

    *plusmask = *minusmask = 0;

    if (modestring == NULL)
    {
        return true;
    }

    CfDebug("ParseModeString(%s)\n", modestring);

    gotaction = false;

    for (const char *sp = modestring; true; sp++)
    {
        switch (*sp)
        {
        case 'a':
            no_error = CheckModeState(who, state, symbolic, sort, *sp);
            affected |= 07777;
            sort = symbolic;
            break;

        case 'u':
            no_error = CheckModeState(who, state, symbolic, sort, *sp);
            affected |= 04700;
            sort = symbolic;
            break;

        case 'g':
            no_error = CheckModeState(who, state, symbolic, sort, *sp);
            affected |= 02070;
            sort = symbolic;
            break;

        case 'o':
            no_error = CheckModeState(who, state, symbolic, sort, *sp);
            affected |= 00007;
            sort = symbolic;
            break;

        case '+':
        case '-':
        case '=':
            if (gotaction)
            {
                CfOut(cf_error, "", "Too many +-= in mode string");
                return false;
            }

            no_error = CheckModeState(who, state, symbolic, sort, *sp);
            action = *sp;
            state = which;
            gotaction = true;
            sort = unknown;
            break;

        case 'r':
            no_error = CheckModeState(which, state, symbolic, sort, *sp);
            value |= 0444 & affected;
            sort = symbolic;
            break;

        case 'w':
            no_error = CheckModeState(which, state, symbolic, sort, *sp);
            value |= 0222 & affected;
            sort = symbolic;
            break;

        case 'x':
            no_error = CheckModeState(which, state, symbolic, sort, *sp);
            value |= 0111 & affected;
            sort = symbolic;
            break;

        case 's':
            no_error = CheckModeState(which, state, symbolic, sort, *sp);
            value |= 06000 & affected;
            sort = symbolic;
            break;

        case 't':
            no_error = CheckModeState(which, state, symbolic, sort, *sp);
            value |= 01000;
            sort = symbolic;
            break;

        case '0':
        case '1':
        case '2':
        case '3':
        case '4':
        case '5':
        case '6':
        case '7':
            no_error = CheckModeState(which, state, numeric, sort, *sp);
            sort = numeric;
            gotaction = true;
            state = which;
            affected = 07777;   /* TODO: Hard-coded; see below */
            sscanf(sp, "%o", &value);
            if (value > 07777)  /* TODO: Hardcoded !
                                   Is this correct for all sorts of Unix ?
                                   What about NT ?
                                   Any (POSIX)-constants ??
                                 */
            {
                CfOut(cf_error, "", "Mode-Value too big : %s\n", modestring);
                return false;
            }

            while (isdigit((int) *sp) && (*sp != '\0'))
            {
                sp++;
            }
            sp--;
            break;

        case ',':
            if (!SetModeMask(action, value, affected, plusmask, minusmask))
            {
                return false;
            }

            if (found_sort != unknown && found_sort != sort)
            {
                CfOut(cf_inform, "", "Symbolic and numeric form for modes mixed");
            }

            found_sort = sort;
            sort = unknown;
            action = '=';
            affected = 0;
            value = 0;
            gotaction = false;
            state = who;
            break;

        case '\0':
            if (state == who || value == 0)
            {
                if (strcmp(modestring, "0000") != 0 && strcmp(modestring, "000") != 0)
                {
                    CfOut(cf_error, "", "mode string is incomplete");
                    return false;
                }
            }

            if (!SetModeMask(action, value, affected, plusmask, minusmask))
            {
                return false;
            }

            if (found_sort != unknown && found_sort != sort)
            {
                CfOut(cf_inform, "", "Symbolic and numeric form for modes mixed");
            }

            CfDebug("[PLUS=%jo][MINUS=%jo]\n", (uintmax_t)*plusmask, (uintmax_t)*minusmask);
            return true;

        default:
            CfOut(cf_error, "", "Invalid mode string (%s)", modestring);
            return false;
        }
    }

    if (!no_error)
    {
        CfOut(cf_error, "", "Error validating mode string %s\n", modestring);
    }

    return no_error;
}