
/****************************************************************************
**
**  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.
**
*****************************************************************************/

/*****************************************************************************
**
**  File:    management_config.c
**  Date:    June 13, 2002
**
**  Author:  Brian Wotring
**  Purpose: read and parse management daemon's config file.
**
******************************************************************************/


#include "libosiris.h"
#include "management_config.h"

#ifdef _WIN32
#define strcasecmp(a,b) stricmp(a,b)
#else
#include <syslog.h>
#endif



#ifndef WIN32

/* translations for syslog facilities. */

static struct
{
    const char *name;
    unsigned int value;
}

log_facilities[] =
{
    { "DAEMON", LOG_DAEMON },
    { "USER",   LOG_USER },
    { "AUTH",   LOG_AUTH },
    { "LOCAL0", LOG_LOCAL0 },
    { "LOCAL1", LOG_LOCAL1 },
    { "LOCAL2", LOG_LOCAL2 },
    { "LOCAL3", LOG_LOCAL3 },
    { "LOCAL4", LOG_LOCAL4 },
    { "LOCAL5", LOG_LOCAL5 },
    { "LOCAL6", LOG_LOCAL6 },
    { "LOCAL7", LOG_LOCAL7 },
    { NULL, -1 }
};

/* translations for syslog levels. */

static struct
{
    const char *name;
    unsigned int value;
}

log_levels[] =
{
    { "WARNING",    LOG_WARNING },
    { "WARN",       LOG_WARNING },
    { "CRIT",       LOG_CRIT },
    { "CRITICAL",   LOG_CRIT },
    { "ERR",        LOG_ERR },
    { "ERROR",      LOG_ERR },
    { "INFO",       LOG_INFO },
    { "DEBUG",      LOG_DEBUG },
    { NULL,     -1 }
};

#endif

/* translations for log intensity levels. */

static struct
{
    const char *name;
    unsigned int value;
}

log_intensities[] =
{
    { "NONE",       LOG_NONE },
    { "NO",         LOG_NONE },
    { "LOW",        LOG_LOW },
    { "L",          LOG_LOW },
    { "MEDIUM",     LOG_MEDIUM },
    { "M",          LOG_MEDIUM },
    { "HIGH",       LOG_HIGH },
    { "H",          LOG_HIGH },
    { "ALL",        LOG_HIGH },
    { NULL,         -1 }
};

unsigned int get_log_intensity_number( char *name )
{
    int i;

    if( name != NULL )
    {
        for( i = 0; log_intensities[i].name; i++ )
        {
            if( strcasecmp( log_intensities[i].name, name ) == 0 )
            {
                return log_intensities[i].value;
            }
        }
    }

    return -1;
}


const char * get_log_intensity_name( int value )
{
    int i;

    if( value >= 0 )
    {
        for( i = 0; log_intensities[i].name; i++ )
        {
            if( log_intensities[i].value == (unsigned int)value )
            {
                return log_intensities[i].name;
            }
        }
    }

    return NULL;
}

#ifndef WIN32

unsigned int get_syslog_facility_number( char *name )
{
    int i;

    if( name != NULL )
    {
        for( i = 0; log_facilities[i].name; i++ )
        {
            if( strcasecmp( log_facilities[i].name, name ) == 0 )
            {
                return log_facilities[i].value;
            }
        }
    }

    return -1;
}

unsigned int get_syslog_level_number( char *name )
{
    int i;

    if( name != NULL )
    {
        for( i = 0; log_levels[i].name; i++ )
        {
            if( strcasecmp( log_levels[i].name, name ) == 0 )
            {
                return log_levels[i].value;
            }
        }
    }

    return -1;
}

const char * get_syslog_facility_name( int value )
{
    int i;

    if( value >= 0 )
    {
        for( i = 0; log_facilities[i].name; i++ )
        {
            if( log_facilities[i].value == value )
            {
                return log_facilities[i].name;
            }
        }
    }

    return NULL;
}

const char * get_syslog_level_name( int value )
{
    int i;

    if( value >= 0 )
    {
        for( i = 0; log_levels[i].name; i++ )
        {
            if( log_levels[i].value == value )
            {
                return log_levels[i].name;
            }
        }
    }

    return NULL;
}

#endif


OSI_MANAGEMENT_CONFIG * osi_management_config_new()
{
    OSI_MANAGEMENT_CONFIG *config = NULL;
    
    config = osi_malloc( sizeof( OSI_MANAGEMENT_CONFIG ) );
    
    if( config != NULL )
    {
        memset( config, 0, sizeof( OSI_MANAGEMENT_CONFIG ) );
        
        config->authorized_hosts = string_list_new();
        config->data = string_list_new();
    }
    
    return config;
}

void osi_management_config_destroy( OSI_MANAGEMENT_CONFIG *config )
{
    if( config != NULL )
    {
        if( config->authorized_hosts != NULL )
        {
            string_list_destroy( config->authorized_hosts );
            string_list_destroy( config->data );
        }
        
        osi_free( config );
    }
}

void osi_management_config_set_defaults( OSI_MANAGEMENT_CONFIG *config )
{
    if( config != NULL )
    {
        osi_strlcpy( config->syslog_facility, DEFAULT_SYSLOG_FACILITY,
                     sizeof( config->syslog_facility ) );

        osi_strlcpy( config->syslog_level, DEFAULT_SYSLOG_LEVEL,
                     sizeof( config->syslog_level ) );

        config->log_intensity     = DEFAULT_LOG_INTENSITY;
        config->control_port      = DEFAULT_CONTROL_PORT;
        config->http_port         = DEFAULT_HTTP_PORT;

        config->notify_smtp_port  = DEFAULT_NOTIFY_SMTP_PORT;

        osi_strlcpy( config->notify_smtp_host, DEFAULT_NOTIFY_SMTP_HOST,
                     sizeof( config->notify_smtp_host ) );
        
        if( config->authorized_hosts != NULL )
        {
            string_list_add_item( config->authorized_hosts,
                                  DEFAULT_AUTHORIZED_HOSTS );
        }
    }
}

OSI_MANAGEMENT_CONFIG * osi_management_config_new_from_file( 
                                            const char *filepath )
{
    OSI_MANAGEMENT_CONFIG *config = NULL;
    
    config = osi_management_config_new();
    osi_management_config_read_file( filepath, config );
    
    return config;
}

osi_bool osi_management_config_receive_first( OSI_MANAGEMENT_CONFIG *config,
                                              unsigned char *data,
                                              int data_length )
{
    if( config != NULL )
    {
        /* destroy data if not destroyed already, then create a new list */
        /* and set state to receiving.  then add incoming data.          */

        string_list_destroy( config->data );
        string_list_destroy( config->authorized_hosts );

        config->data = string_list_new();
        config->authorized_hosts = string_list_new();

        return osi_management_config_receive( config, data, data_length );
    }

    return FALSE;
}

osi_bool osi_management_config_receive( OSI_MANAGEMENT_CONFIG *config,
                                        unsigned char *data, int data_length )
{
    if( ( config != NULL ) && ( data != NULL ) && ( data_length > 0 ) )
    {
        data = trim_white_space( data );
        
        string_list_add_item( config->data, data );
        parse_management_config_line( data, config );

        return TRUE;
    }

    return FALSE;
}

osi_bool osi_management_config_receive_last( OSI_MANAGEMENT_CONFIG *config,
                                             unsigned char *data,
                                             int data_length )
{
    osi_bool result = FALSE;

    if( config != NULL )
    {
        osi_management_config_receive( config, data, data_length );
    }

    return result;
}

osi_bool osi_management_config_read_file( const char *filepath,
                                          OSI_MANAGEMENT_CONFIG *config )
{
    osi_bool result = FALSE;
    FILE *file  = NULL;

    char *line;
    char temp_line[MAX_MANAGEMENT_CONFIG_LINE_LENGTH] = "";

    if( ( filepath != NULL ) && ( config != NULL ) )
    {
        file = osi_fopen( filepath, "r", MANAGEMENT_CONFIG_FILE_PERMISSIONS );

        if( file != NULL )
        {
            /* if we are reading a config file, we need to clobber the host */
            /* list, it can't simply be overwritten like the other fields.  */
            
            string_list_destroy( config->authorized_hosts );
            string_list_destroy( config->data );
            
            config->authorized_hosts = string_list_new();
            config->data             = string_list_new();
            
            for(;;)
            {
                line = fgets( temp_line, sizeof( temp_line ), file );

                if( line == NULL )
                {
                    break;
                }

                line = trim_white_space( line );

                if( line != NULL )
                {
                    string_list_add_item( config->data, line );
                    parse_management_config_line( line, config );
                }
            }

            fclose( file );
            result = TRUE;
        }
    }

    return result;
}

osi_bool osi_management_config_write_file( const char *filepath,
                                           OSI_MANAGEMENT_CONFIG *config )
{
    int index;

    osi_bool result = FALSE;
    FILE *config_file = NULL;

    if( ( filepath == NULL ) || ( config == NULL ) )
    {
        return FALSE;
    }

    /* now, we open the config file, and write each value. */

    config_file = osi_fopen( filepath, "w+",
                             MANAGEMENT_CONFIG_FILE_PERMISSIONS );

    if( config_file != NULL )
    {
        char line[MAX_MANAGEMENT_CONFIG_LINE_LENGTH];
        char data[MAX_MANAGEMENT_CONFIG_KEY_LENGTH];
            
        const char *name;
        int index2;

        /* loop through the list of keywords and print each one's value. */
                  
        for( index = 0;
             management_config_keywords[index].word != NULL;
             index++ )
        {
            /* print the name. */
                
            osi_strlcpy( line, management_config_keywords[index].word,
                         sizeof( line ) );

            osi_strlcat( line, " = ", sizeof( line ) );
                
            /* we now write the value, different for each keyword. */
                
            switch( management_config_keywords[index].type )
            {
                case MANAGEMENT_CONFIG_KEYWORD_SYSLOG_FACILITY:

                    osi_strlcat( line, config->syslog_facility,
                                 sizeof( line ) );

                    osi_strlcat( line, "\n", sizeof( line ) );

                    fwrite( line, sizeof( char ), strlen( line ),
                            config_file );
                        
                    break;
                        
                case MANAGEMENT_CONFIG_KEYWORD_SYSLOG_LEVEL:

                    osi_strlcat( line, config->syslog_level, sizeof( line ) );
                    osi_strlcat( line, "\n", sizeof( line ) );

                    fwrite( line, sizeof( char ), strlen( line ),
                            config_file );
                        
                    break;
                        
                case MANAGEMENT_CONFIG_KEYWORD_LOG_INTENSITY:
                    
                    name = get_log_intensity_name( config->log_intensity );
                        
                    if( name != NULL )
                    {
                        osi_strlcat( line, name, sizeof( line ) );
                    }
                        
                    osi_strlcat( line, "\n", sizeof( line ) );

                    fwrite( line, sizeof( char ), strlen( line ),
                            config_file );
                       
                    break;
                       
                case MANAGEMENT_CONFIG_KEYWORD_CONTROL_PORT:

                    osi_snprintf( data, sizeof( data ), "%d\n",
                                  config->control_port );

                    osi_strlcat( line, data, sizeof( line ) );

                    fwrite( line, sizeof( char ), strlen( line ),
                            config_file );
                        
                    break;

                case MANAGEMENT_CONFIG_KEYWORD_HTTP_PORT:

                    osi_snprintf( data, sizeof( data ), "%d\n",
                                  config->http_port );

                    osi_strlcat( line, data, sizeof( line ) );

                    fwrite( line, sizeof( char ), strlen( line ),
                            config_file );

                    break;

                case MANAGEMENT_CONFIG_KEYWORD_NOTIFY_EMAIL:

                    osi_strlcat( line, config->notify_email,
                                 sizeof( line ) );

                    osi_strlcat( line, "\n", sizeof( line ) );

                    fwrite( line, sizeof( char ), strlen( line ),
                            config_file );
   
                    break;

                case MANAGEMENT_CONFIG_KEYWORD_NOTIFY_SMTP_HOST:
        
                    osi_strlcat( line, config->notify_smtp_host, 
                                 sizeof( line ) );
                
                    osi_strlcat( line, "\n", sizeof( line ) );
        
                    fwrite( line, sizeof( char ), strlen( line ),
                            config_file );
    
                    break;

                case MANAGEMENT_CONFIG_KEYWORD_HTTP_HOST:
         
                    osi_strlcat( line, config->http_host, 
                                 sizeof( line ) );
                 
                    osi_strlcat( line, "\n", sizeof( line ) );
         
                    fwrite( line, sizeof( char ), strlen( line ),
                            config_file );
     
                    break;


                case MANAGEMENT_CONFIG_KEYWORD_NOTIFY_SMTP_PORT:

                    osi_snprintf( data, sizeof( data ), "%d\n",
                                  config->notify_smtp_port );

                    osi_strlcat( line, data, sizeof( line ) );

                    fwrite( line, sizeof( char ), strlen( line ),
                            config_file );

                    break;
                        
                case MANAGEMENT_CONFIG_KEYWORD_AUTHORIZED_HOST:
                  
                    if( config->authorized_hosts != NULL )
                    {
                        char temp_line[MAX_MANAGEMENT_CONFIG_LINE_LENGTH];

                        for( index2 = 0;
                             index2 < (int)config->authorized_hosts->size;
                             index2++ )
                        {
                            osi_strlcpy( temp_line, line, sizeof( temp_line ) );
                            osi_strlcat( temp_line,
                                         config->authorized_hosts->list[index2],
                                         sizeof( temp_line ) );

                            osi_strlcat( temp_line, "\n", sizeof( line ) );

                            fwrite( temp_line, sizeof( char ),
                                    strlen( temp_line ), config_file );
                        }
                    }
                        
                    break;
                        
                default:
                    break;
            }
        }
        
        fclose( config_file );
        result = TRUE;
    }

    return result;
}

/* given the config attributes, update the raw data portion */

osi_bool osi_management_config_sync( OSI_MANAGEMENT_CONFIG *config )
{
    int index;
    int index2;

    osi_bool result = FALSE;
    
    char line[MAX_MANAGEMENT_CONFIG_LINE_LENGTH];
    char data[MAX_MANAGEMENT_CONFIG_KEY_LENGTH];
            
    const char *name;

    if( config == NULL)
    {
        return FALSE;
    }

    /* first destroy the data section and create a new list. */

    string_list_destroy( config->data );
    config->data = string_list_new();

    /* loop through the list of keywords and print each one's value. */
                  
    for( index = 0;
         management_config_keywords[index].word != NULL;
         index++ )
    {
        /* print the name. */
                
        osi_strlcpy( line, management_config_keywords[index].word,
                     sizeof( line ) );

        osi_strlcat( line, " = ", sizeof( line ) );
                
        /* we now write the value, different for each keyword. */
                
        switch( management_config_keywords[index].type )
        {
            case MANAGEMENT_CONFIG_KEYWORD_SYSLOG_FACILITY:

                osi_strlcat( line, config->syslog_facility, sizeof( line ) );
                string_list_add_item( config->data, line );

                break;
                        
            case MANAGEMENT_CONFIG_KEYWORD_SYSLOG_LEVEL:

                osi_strlcat( line, config->syslog_level, sizeof( line ) );
                string_list_add_item( config->data, line );

                break;
                        
            case MANAGEMENT_CONFIG_KEYWORD_LOG_INTENSITY:
                    
                name = get_log_intensity_name( config->log_intensity );
                        
                if( name != NULL )
                {
                    osi_strlcat( line, name, sizeof( line ) );
                }
                        
                string_list_add_item( config->data, line );

                break;
                       
            case MANAGEMENT_CONFIG_KEYWORD_CONTROL_PORT:

                osi_snprintf( data, sizeof( data ), "%d",
                              config->control_port );

                osi_strlcat( line, data, sizeof( line ) );
                string_list_add_item( config->data, line );

                break;

            case MANAGEMENT_CONFIG_KEYWORD_HTTP_PORT:

                osi_snprintf( data, sizeof( data ), "%d",
                              config->http_port );

                osi_strlcat( line, data, sizeof( line ) );
                string_list_add_item( config->data, line );

                break;

            case MANAGEMENT_CONFIG_KEYWORD_NOTIFY_EMAIL:

                osi_strlcat( line, config->notify_email, sizeof( line ) );
                string_list_add_item( config->data, line );
   
                break;

            case MANAGEMENT_CONFIG_KEYWORD_NOTIFY_SMTP_HOST:
        
                osi_strlcat( line, config->notify_smtp_host, sizeof( line ) );
                string_list_add_item( config->data, line );
 
                break;

            case MANAGEMENT_CONFIG_KEYWORD_NOTIFY_SMTP_PORT:

                osi_snprintf( data, sizeof( data ), "%d",
                              config->notify_smtp_port );

                osi_strlcat( line, data, sizeof( line ) );
                string_list_add_item( config->data, line );

                break;

            case MANAGEMENT_CONFIG_KEYWORD_HTTP_HOST:
         
                osi_strlcat( line, config->http_host, sizeof( line ) );
                string_list_add_item( config->data, line );
  
                break;
                        
            case MANAGEMENT_CONFIG_KEYWORD_AUTHORIZED_HOST:
                  
                if( config->authorized_hosts != NULL )
                {
                    char temp_line[MAX_MANAGEMENT_CONFIG_LINE_LENGTH];

                    for( index2 = 0;
                         index2 < (int)config->authorized_hosts->size;
                         index2++ )
                    {
                        osi_strlcpy( temp_line, line, sizeof( temp_line ) );

                        osi_strlcat( temp_line,
                                     config->authorized_hosts->list[index2],
                                     sizeof( temp_line ) );

                        string_list_add_item( config->data, temp_line );

                    }
                }
                        
                break;
                        
            default:
                break;

        } /* end switch */

    } /* end for loop. */

    return result;
}


osi_bool parse_management_config_line( char *line,
                                       OSI_MANAGEMENT_CONFIG *config )
{
    osi_bool result = FALSE;
    char value[MAX_MANAGEMENT_CONFIG_KEY_LENGTH] = "";
    
    if( ( line != NULL ) && ( config != NULL ) )
    {
        int line_type = get_management_config_line_type( line );
        int number_value;
        
        switch( line_type )
        {
            case MANAGEMENT_CONFIG_KEYWORD_SYSLOG_FACILITY:

                get_management_config_line_value( line,
                                                  value, sizeof( value ) );

                if( strlen( value ) > 0 )
                {
                    osi_strlcpy( config->syslog_facility, value,
                                 sizeof( config->syslog_facility ) );
                }

                break;
                
            case MANAGEMENT_CONFIG_KEYWORD_SYSLOG_LEVEL:

                get_management_config_line_value( line,
                                                  value, sizeof( value ) );

                if( strlen( value ) > 0 )
                {
                    osi_strlcpy( config->syslog_level, value,
                                 sizeof( config->syslog_level ) );
                }

                break;
                
            case MANAGEMENT_CONFIG_KEYWORD_LOG_INTENSITY:

                get_management_config_line_value( line,
                                                  value, sizeof( value ) );

                if( strlen( value ) > 0 )
                {
                     number_value = get_log_intensity_number( value );
                     
                     if( number_value >= 0 )
                     {
                         config->log_intensity = number_value;
                     }
                }
                
                break;
                
            case MANAGEMENT_CONFIG_KEYWORD_CONTROL_PORT:

                get_management_config_line_value( line,
                                                  value, sizeof( value ) );
                
                if( ( strlen( value ) > 0 ) && ( atoi( value ) > 0 ) )
                {
                    config->control_port = atoi( value );
                }
                
                break;

            case MANAGEMENT_CONFIG_KEYWORD_HTTP_PORT:

                get_management_config_line_value( line,
                                                  value, sizeof( value ) );

                if( strlen( value ) > 0 )
                {
                    config->http_port = atoi( value );
                }

                break;

            case MANAGEMENT_CONFIG_KEYWORD_NOTIFY_EMAIL:

                get_management_config_line_value( line,
                                                  value, sizeof( value ) );

                if( strlen( value ) > 0 )
                {
                    osi_strlcpy( config->notify_email, value,
                                 sizeof( config->notify_email ) );
                }

                break;

            case MANAGEMENT_CONFIG_KEYWORD_NOTIFY_SMTP_HOST:

                get_management_config_line_value( line,
                                                  value, sizeof( value ) );

                if( strlen( value ) > 0 )
                {
                    osi_strlcpy( config->notify_smtp_host, value,
                                 sizeof( config->notify_smtp_host ) );
                }

                break;

            case MANAGEMENT_CONFIG_KEYWORD_NOTIFY_SMTP_PORT:

                get_management_config_line_value( line,
                                                  value, sizeof( value ) );

                if( ( strlen( value ) > 0 ) && ( atoi( value ) > 0 ) )
                {
                    config->notify_smtp_port = atoi( value );
                }

                break;

                
            case MANAGEMENT_CONFIG_KEYWORD_AUTHORIZED_HOST:

                get_management_config_line_value( line,
                                                  value, sizeof( value ) );
                
                if( strlen( value ) > 0 )
                {
                    string_list_add_item( config->authorized_hosts, value );
                }

                break;
                
            case MANAGEMENT_CONFIG_KEYWORD_COMMENT:
            
                /* suck up the rest of the line, do nothing with it. */
                
                get_management_config_line_value( line,
                                                  value, sizeof( value ) );
                break;

                       
            case MANAGEMENT_CONFIG_KEYWORD_HTTP_HOST:
 
                get_management_config_line_value( line,
                                                  value, sizeof( value ) );
 
                if( strlen( value ) > 0 )
                {
                    osi_strlcpy( config->http_host, value,
                                 sizeof( config->http_host ) );
                }
 
                break;
 
            case MANAGEMENT_CONFIG_KEYWORD_UNKNOWN:
            default:
                break;
        }
    }

    return result;
}


/*****************************************************************************
**
**    Function: get_management_config_line_type
**
**    Purpose:  determine the type of keyword this is based upon
**              our lists.
**
*****************************************************************************/

int get_management_config_line_type( char *string )
{
    int type = MANAGEMENT_CONFIG_KEYWORD_UNKNOWN;
    int index;
    
    char word[MAX_MANAGEMENT_CONFIG_KEY_LENGTH] = "";

    if( string != NULL )
    {
        get_string_up_to_token( string, word,
                                sizeof( word ),
                                MANAGEMENT_CONFIG_KEY_VALUE_SEPARATOR );

        lowercase_string( word );

        for( index = 0;
             management_config_keywords[index].word != NULL;
             index++ )
        {
            if( strncmp( word, management_config_keywords[index].word,
                     strlen( management_config_keywords[index].word ) ) == 0 )
            {
                type = ( management_config_keywords[index].type );
                break;
            }
            
            if( word[0] == MANAGEMENT_CONFIG_COMMENT_LINE )
            {
                type = MANAGEMENT_CONFIG_KEYWORD_COMMENT;
                break;
            }
        }
    }

    return type;
}

osi_bool get_management_config_line_value( char *line, char *value,
                                           int value_size )
{
    osi_bool result = FALSE;
    char *start = NULL;

    if( ( line != NULL ) && ( value != NULL ) )
    {
        start = (char *)strchr( line, MANAGEMENT_CONFIG_KEY_VALUE_SEPARATOR );

        if( start != NULL )
        {
            start++;
            start = trim_white_space( start );

            if( ( start != NULL ) && ( (*start) != '\0' ) )
            {
                osi_strlcpy( value, start, value_size );

                if( strlen( value ) > 0 )
                {
                    result = TRUE;
                }
            }
        }
    }

    return result;
}

