
/******************************************************************************
**
**  Copyright (C) 2001  - the shmoo group -
**
**  This program is free software; you can redistribute it and/or
**  modify it, however, you cannot sell it.
**
**  This program is distributed in the hope that it will be useful,
**  but WITHOUT ANY WARRANTY; without even the implied warranty of
**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
**
**  You should have received a copy of the license attached to the
**  use of this software.  If not, visit www.shmoo.com/osiris for
**  details.
**
******************************************************************************/

/******************************************************************************
**
**    The Shmoo Group (TSG)
**
**    File:      filter.c
**    Author:    Brian Wotring
**
**    Date:      June 22, 2001.
**    Project:   osiris
**
******************************************************************************/

#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>

#include <string.h>

#include <ctype.h>
#include <fcntl.h>
#include <sys/stat.h>

#include "utilities.h"
#include "scan_record.h"
#include "filter.h"

/******************************************************************************
**
**    Function: setup_filter_function
**
**    Purpose:  based upon the value/type of the filter, we
**              set the filter process function pointer to
**              the correct one.
**
******************************************************************************/

int setup_filter_function( filter *action_filter, int type )
{
    if( action_filter == NULL )
    {
        return 0;
    }

    switch( type )
    {
        case FILTER_TYPE_STICKY:
            action_filter->perform = filter_sticky;
            break;

        case FILTER_TYPE_SUID:
            action_filter->perform = filter_suid;
            break;

        case FILTER_TYPE_GUID:
            action_filter->perform = filter_guid;
            break;

        case FILTER_TYPE_EXECUTABLE:
            action_filter->perform = filter_executable;
            break;

        case FILTER_TYPE_PERL:
            action_filter->perform = filter_perl;
            break;

        case FILTER_TYPE_PYTHON:
            action_filter->perform = filter_python;
            break;

        case FILTER_TYPE_SCRIPT:
            action_filter->perform = filter_script;
            break;

        case FILTER_TYPE_GZIP:
            action_filter->perform = filter_gzip;
            break;

        case FILTER_TYPE_ZIP:
            action_filter->perform = filter_zip;
            break;

        case FILTER_TYPE_TAR:
            action_filter->perform = filter_tar;
            break;

        case FILTER_TYPE_PGP:
            action_filter->perform = filter_pgp;
            break;

        case FILTER_TYPE_RPM:
            action_filter->perform = filter_rpm;
            break;

        case FILTER_TYPE_UID:
            action_filter->perform = filter_uid;
            break;

        case FILTER_TYPE_GID:
            action_filter->perform = filter_gid;
            break;

        case FILTER_TYPE_SID:
            action_filter->perform = filter_sid;
            break;
            
        case FILTER_TYPE_USER:
            action_filter->perform = filter_user;
            break;

        case FILTER_TYPE_GROUP:
            action_filter->perform = filter_group;
            break;

        case FILTER_TYPE_HEADER:
            action_filter->perform = filter_header;
            break;

        case FILTER_TYPE_FILE:
            action_filter->perform = filter_file;
            break;

        case FILTER_TYPE_SUFFIX:
            action_filter->perform = filter_suffix;
            break;

        case FILTER_TYPE_MD5:
            action_filter->perform = filter_md5;
            break;

        case FILTER_TYPE_SHA:
            action_filter->perform = filter_sha;
            break;

        case FILTER_TYPE_RIPEMD:
            action_filter->perform = filter_ripemd;
            break;

        case FILTER_TYPE_PERMISSIONS:
            action_filter->perform = filter_permissions;
            break;

        case FILTER_TYPE_UNKNOWN:
        default:

        return 0;
        break;
    }

    return 1;
}

/******************************************************************************
**
**    Function: filter_is_dynamic
**
**    Purpose:  determine if the filter takes an context->filter_argument
**              ( dyname ) or if it's just a static filter.
**
******************************************************************************/

osi_bool filter_is_dynamic( int filter_type )
{
    switch( filter_type )
    {
        case FILTER_TYPE_UID:
        case FILTER_TYPE_GID:
        case FILTER_TYPE_SID:
        case FILTER_TYPE_USER:
        case FILTER_TYPE_GROUP:
        case FILTER_TYPE_HEADER:
        case FILTER_TYPE_FILE:
        case FILTER_TYPE_SUFFIX:
        case FILTER_TYPE_MD5:
        case FILTER_TYPE_SHA:
        case FILTER_TYPE_RIPEMD:
        case FILTER_TYPE_PERMISSIONS:

            return TRUE;
            break;

        default:

            return FALSE;
            break;
     }
}


/******************************************************************************
**
**    Function: get_filter_type
**
**    Purpose:  determines the type of the filter based upon the
**              filter names we have.
**
******************************************************************************/

int get_filter_type( char *line )
{
    int index = 0;
    int type  = FILTER_TYPE_UNKNOWN;

    if( line == NULL )
    {
        return type;
    }

    /* check for static filter first. */

    for( index = 0; filter_keywords[index].word != NULL; index++ )
    {
        int size   = strlen( filter_keywords[index].word );
        int type   = filter_keywords[index].type;

        char *word = filter_keywords[index].word;

        if( strncmp( line, word, size ) == 0 )
        {
            /* skip over the filter name, to next visible character. */

            line = line + size;

            if( !isgraph( *line ) || *line == '(' )
            {
                return type;
            }

            /* whoops, not quite right, restore line back to          */
            /* normal, we might still find this to be a valid filter. */

            line = line - size;
        }

    }

    return FILTER_TYPE_UNKNOWN;
}


/******************************************************************************
**
**    Function: get_filter_value
**
**    Purpose:  gets the value found in the first filter found.
**              the filter name need not be valid, but the
**              syntax of the filter must be.  if not, the
**              buffer contents is undefined and NULL is
**              returned.  otherwise, the buffer contains the
**              value ( minus any outside quotes ) and a valid
**              pointer to the data after the filter is returned.
**
******************************************************************************/


char * get_filter_value( char *line, char *value )
{
    char *end;
    char *start;
    char *attributes;

    if( line == NULL || value == NULL )
    {
        return NULL;
    }

    /* define the start and end of the filter. */

    start = strchr( line, '(' );

    if( start == NULL )
    {
        return NULL;
    }

    end = strstr( start, ")" );

    if( end == NULL )
    {
        return NULL;
    }

    attributes = ( end + 1 );

    /*  remove the () from each end. */

    start++;
    end--;

    /* remove white space. */

    while( *start && !isgraph( *start ) )
    {
        start++;
    }

    while( *end && !isgraph( *end ) )
    {
        end--;
    }

    if( start > end )
    {
        return NULL;
    }

    /* remove any quotes, and basic consistency. */

    if( *start == '"' || *end == '"' )
    {
        if( *end != '"' || *start != '"' )
        {
            return NULL;
        }

        start++;
        end--;
    }

    /* copy value into the buffer. */

    while( start <= end )
    {
        *value = *start;

        start++;
        value++;
    }

    *value = '\0';
    return attributes;
}


/******************************************************************************
**
**    Function: get_filter_name_from_type
**
**    Purpose:  use our filter name->constant table to return
**              the string name of the specified filter type.
**
******************************************************************************/

char *get_filter_name_from_type( int filter_type )
{
    int index;

    for( index = 0; filter_keywords[index].word != NULL; index++ )
    {
        if( filter_keywords[index].type == filter_type )
        {
            return filter_keywords[index].word;
        }
    }

    return NULL;
}

