#!/usr/bin/perl -w # # # config2xml # # Written by: Charlie Heselton (gentuxx@gmail.com) # Date: 08/22/2006 # Version: 0.1 # # Description: OSSEC-HIDS uses XML for it's configuration # and rules files. This script allows a user to use a # more traditional "key = value" format and convert it # to the XML required by OSSEC. # # require 5.006; use strict; use Getopt::Std; my (%opts, %config); getopts('f:', \%opts); my $current_line = 0; if ($opts{'f'}) { # open the "traditional" file and parse the contents. open CONF, $opts{'f'} or die "Couldn't open input config file ($opts{'f'}): $! \n"; while () { $current_line++; # skip commented or blank lines next if (/^#/); next if (/^$/); chomp; # strip out any double quotes #s/\"//g; # strip out spaces or tabs #s/(\s+|\t+)//g; my ($key, $value); #print STDERR "DEBUG: \$\_ ===> $_\n"; if (/^\s*(\S+)\s*\=\s*\"?([^=]+)\"?/) { $key = $1; $value = $2; } else { die "Config error! Found an extra equals sign (=) in line $current_line\. Input file not converted!\n"; } # the keys below will be repeated, but if the value is assigned initially, # then the script fails when unwrapping the hash. # key/value pairs that shouldn't be repeated throw a config error if they are repeated. if ($key =~ /monitor_file|rules_include|active_response_command/) { push @{$config{$key}}, $value; } else { if (exists($config{$key})) { die "$key has already been specified in the config file and can only be used once. Input file not converted!\n"; } $config{$key} = $value; } } close CONF; } else { die "No input file specified.\n"; } undef $current_line; # strip out any double-quotes # this is handled for all the rest of the key/value pairs when the input file is initially parsed foreach my $key ( qw/ active_response_command / ) { foreach ( @{$config{$key}} ) { s!\"!!g; } } # separate the "complex" options into arrays my @whitelisted = split(/\,/, $config{'whitelist_ips'}); my @ignored = split(/\,/, $config{'ignore'}); # Write the xml file. Easiest way is just to be deliberate. Not the most elegant solution, but it should work. print < $config{'email_notify'} $config{'email_addr'} $config{'smtp_server'} $config{'email_from'} END foreach my $wip ( sort( @whitelisted ) ) { print " $wip\n"; } print " \n\n"; print " \n"; foreach my $rulesfile ( sort( @{$config{'rules_include'}} ) ) { print " $rulesfile\n"; } print < $config{'frequency'} $config{'directories_check_all'} END foreach my $ignored ( @ignored ) { print " $ignored\n"; } print < $config{'rootkit_files_db'} $config{'rootkit_trojans_db'} END if ( exists($config{'remote'}) ) { print " \n"; if ((exists($config{'connection_type'})) && ($config{'connection_type'} eq 'secure')) { print " $config{'connection_type'}\n"; } print " \n"; } print < $config{'log_alert_level'} $config{'email_alert_level'} END if ( exists($config{'active_response'}) ) { # should always be true if ($config{'active_response'} eq 'disabled') { print " \n yes\n \n\n"; } else { # Could use some comments/insight here, since I don't use the active response features. foreach my $cmd ( sort(@{$config{'active-response-command'}}) ) { my ( $name, $exe, $expect, $timeout ) = split(/\,/, $cmd); print < $name $exe $expect $timeout END } print < host-deny local 6 600 firewall-drop local 6 600 END } } foreach my $file ( sort( @{$config{'monitor_file'}} ) ) { my ($fileloc, $fformat) = split(/\,/, $file); print " \n"; print " $fformat\n"; print " $fileloc\n"; print " \n"; } print "\n";