#!/usr/bin/perl -w

use strict;

use Data::Dumper;
use Getopt::Std;
use CIF::Client;

my %opts;
getopt('O:G:l:g:hTHL:p:f:q:c:s:r:C:z', \%opts);

my $outfile     = $opts{'O'};
my $query       = $opts{'q'} || shift;
our $debug       = ($opts{'d'}) ? 1 : 0;
my $c           = $opts{'C'} || $ENV{'HOME'}.'/.cif';
my $fields      = $opts{'f'};
my $severity    = $opts{'s'};
my $restriction = $opts{'r'} || 'private';
my $plugin      = $opts{'p'} || 'table';
my $max_desc    = $opts{'L'} || 100;
my $nolog       = $opts{'n'} || 0;
my $summary     = $opts{'S'};
my $nomap       = $opts{'N'};
my $confidence  = $opts{'c'} || 0;
our $uuid        = $opts{'u'} || 0;
our $relateduuid = $opts{'R'} || 0;
my $guid         = $opts{'g'};
my $limit       = $opts{'l'};
my $group_map   = (defined($opts{'G'})) ? $opts{'G'} : 1;
my $plugs = join(',',CIF::Client::_plugins);
my $simple_hashes = (defined($opts{'H'})) ? $opts{'H'} : 1;
my $verify_tls = $opts{'T'};
my $compress_address = (defined($opts{'z'})) ? $opts{'z'} : 1;

die(usage()) unless($query || $opts{'h'});


sub usage {
    return <<EOF;
Usage: perl $0 -q xyz.com

    -h  --help:             this message
    -C  --config:           specify cofiguration file, default: $c
    -q  --query:            query string (use 'url\\/<md5|sha1>' for url hash lookups)
    -p  --plugin:           output plugin ($plugs), default: $plugin
    -n  --nolog:            perform a "silent" query (no log query), default: $nolog
    -O  --outfile:          specify an output file to print to
    
Common Filters:
    -l  --limit:            set the default result limit (queries only), default is set on server, usually around 500.
    -s  --severity:         severity (low,medium,high), default: high
    -c  --confidence:       lowest tolerated confidence (0.00 -- 100.00), default $confidence
    -r  --restriction:      restriction to be applied to results, default: $restriction

Advanced:
    -f  --fields:           set default output fields for default table display
    -S  --summary:          consolidated Text::Table output (default: 1 -- True)
    -N  --nomap:            don't map restrictions on server (queries only)
    -H  --simplehashes:     translate the complex json documents to simplified key value pairs, default: $simple_hashes
    -T  --verify_tls:       verify tls FQDN
    -g  --guid:             filter by a specific group id (guid), ex: group1.example.com
    -G  --groupmap:         turn group mapping (guid to 'group name') on/off, default: $group_map
    -z                      compact address field to 32 chars, applies only to defalt table output, default: 1 (0 turns it off)

Queries:

    \$> perl $0 -q 1.2.3.4
    \$> perl $0 -q 1.2.3.0/24
    \$> perl $0 -q f8e74165fb840026fd0fce1fd7d62f5d0e57e7ac
    \$> perl $0 -q hut2.ru
    \$> perl $0 -q hut2.ru,f8e74165fb840026fd0fce1fd7d62f5d0e57e7ac
    \$> perl $0 hut2.ru

Feeds:
    
    \$> perl $0 -q malware
    \$> perl $0 -q malware -s low
    \$> perl $0 -q infrastructure/network -s medium -p snort
    \$> perl $0 -q domain/malware -p bindzone -c 95 -s medium
    \$> perl $0 -q domain -s medium -c 40 -p raw -H 0 -r private

Configuration:

    configuration file ~/.cif should be readable and look something like:

    [client]
    host = https://example.com:443/api
    apikey = xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
    timeout = 60
    # add this if you have a self signed cert
    verify_tls = 0

Plugin Specific Configurations:

    Table:
        
        [clent]
        table_nowarning = 1

    Bindzone:
        
        [client]
        bindzone_path = /etc/namedb/

    Snort:
    
        [client]
        snort_startsid = 10000000

EOF
}
my ($client,$err) = CIF::Client->new({ 
    config      => $c,
    fields      => $fields,
    max_desc    => $max_desc,
    nolog       => $nolog,
    simple_hashes => $simple_hashes,
    verify_tls  => $verify_tls,
    guid        => $guid,
    group_map   => $group_map,
    compress_address    => $compress_address,
});

die($err) unless($client);

my @q = split(/\,/,$query);
foreach (@q){
    my $feed = $client->GET(
        query       => $_,
        severity    => $severity,
        restriction => $restriction,
        nolog       => $nolog,
        nomap       => $nomap,
        confidence  => $confidence,
        limit       => $limit,
        group_map   => $group_map,
    );
    unless($client->responseCode() == 200){
        my $json = JSON::from_json($client->responseContent());
        print 'request failed with code: '.$json->{'status'}." ".$json->{'message'}."\n";
        exit(-1);
    }
   
    my $plug = 'CIF::Client::Plugin::'.ucfirst($plugin);
    eval "require $plug";
    die($@) if($@);
    $feed->{'query'} = $_;
    if($feed->{'feed'}){
        my $text = $plug->write_out($client,$feed,$summary);
        if($outfile){
            open(F,">",$outfile) || die($!);
            print F $text;
            close(F);
        } else {
            print $text;
        }
    }
}
