Changeset 163

Show
Ignore:
Timestamp:
01/19/07 14:01:41 (2 years ago)
Author:
mbriggs
Message:

DB bug fixes

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • honeyclient/branches/exp/mbriggs-db/lib/HoneyClient/Manager/DB.pm

    r162 r163  
    99############################################################################## 
    1010# Package:     HoneyClient::Manager::DB  
    11 # $LastChangedRevision: 1835
     11# $LastChangedRevision: 1836
    1212# File:        DB.pm 
    1313# Description: A module server that provides an interface to the Honeyclient DB 
    1414# Author:      mbriggs 
    1515# 
    16 # CVS:         $Id: DB.pm 1835 2007-01-16 13:06:53Z mbriggs $ 
     16# CVS:         $Id: DB.pm 1836 2007-01-19 18:45:32Z mbriggs $ 
    1717# 
    1818# Copyright (C) 2006 The MITRE Corporation.  All rights reserved. 
     
    7373    use Relations::Query; 
    7474    use Relations::Abstract; 
     75    use Data::Dumper; 
    7576 
    7677    # Traps signals, allowing END: blocks to perform cleanup. 
     
    129130                name    => 1, 
    130131                new_val => 1, 
    131                 old_val => 1
     132                old_val => 0
    132133            }, 
    133134            datecreated => 0, 
    134135            notes       => 0, 
    135136        }, 
    136         selectFunc => undef
     137        selectFunc => \&_SelectRegKeys
    137138        insertFunc => \&_InsertRegKey, 
    138139    }, 
     
    160161# Returns ID of Inserted File 
    161162 
     163sub _quote { 
     164    my ($self,$ref) = @_; 
     165    if (!ref $ref) { 
     166        return $self->{dbh}->quote($ref); 
     167    } 
     168    elsif (ref $ref eq 'HASH') { 
     169        my %hash = %$ref; 
     170        foreach (keys %hash) { 
     171            $hash{$_} = $self->_quote($hash{$_}); 
     172        } 
     173        return \%hash; 
     174    } 
     175    elsif (ref $ref eq 'ARRAY') { 
     176        my @arr = @$ref; 
     177        foreach (@arr) { 
     178            $_ = $self->_quote($_); 
     179        } 
     180    } 
     181    elsif (ref $ref eq 'SCALAR') { $ref = $self->_quote($$ref);} 
     182    else {Carp::croak(__PACKAGE__."->_quote was passed an illegal reference type: ".ref $ref);} 
     183} 
     184 
    162185sub _InsertFile { 
    163186    my ($self,$h_file,$serial) = @_; 
    164     my ($contentid,$rc); 
     187    my ($contentid,$rc,%file); 
    165188    eval { 
    166189         
    167190        if (!$self->_VerifyHash($h_file,$tables{Files}{fields},1)) {return;} 
    168         my %fileContent = map { $_ => $self->{dbh}->quote($h_file->{content}->{$_}) } ('md5','sha1','type','size'); 
     191        %file = %{$self->_quote($h_file)}; 
     192        %fileContent = %{ delete $file{content} }; 
    169193         
    170194        my $abstract = new Relations::Abstract($self->{dbh}); 
     
    178202        # If content found, record instance only and link to file content 
    179203        if (defined($row) && $row > 0) { 
    180             $contentid = $row->{id}; 
     204           $file{contentid} = $row->{id}; 
    181205        } 
    182206        else { 
    183             $contentid = $abstract->insert_id( 
     207            $file{contentid} = $abstract->insert_id( 
    184208                -id    => 'id', 
    185209                -table => 'FileContent', 
    186210                -set   => \%fileContent); 
    187211        } 
    188         my %file = map { $_ => $self->{dbh}->quote($h_file->{$_}) } ('path','name','datecreated');#,'subsecs'); 
    189         $file{contentid} = $self->{dbh}->quote($contentid); $file{serial} = $self->{dbh}->quote($serial); 
    190          
     212        $file{serial} = $self->_quote($serial); 
    191213        $rc = $abstract->insert_id( 
    192214                -id    => 'id', 
     
    211233        my $abstract = new Relations::Abstract($self->{dbh}); 
    212234         
    213         my %proc = map { $_ => $self->{dbh}->quote($h_proc->{$_}) } (keys %$h_proc)
    214         $proc{serial} = $serial
     235       my %proc = %{$self->_quote($h_proc)}
     236        $proc{serial} = $self->_quote($serial)
    215237     
    216238        $rc = $abstract->insert_id( 
     
    236258        my $abstract = new Relations::Abstract($self->{dbh}); 
    237259         
    238         my %regkey = map { $_ => $self->{dbh}->quote($h_regkey->{$_}) } ('key_name','status','datecreated','notes')
    239         $regkey{serial} = $serial
    240      
     260       my %regkey = %{$self->_quote($h_regkey)}
     261        $regkey{serial} = $self->_quote($serial)
     262        my @entries = @{delete $regkey{entries}} if (exists $h_regkey->{entries}); 
    241263        $id = $abstract->insert_id( 
    242264            -id    => 'id', 
     
    244266            -set   => \%regkey 
    245267        ); 
    246         foreach my $entry (@{$h_regkey->{entries}}) { 
    247             my %entry = map { $_ => $self->{dbh}->quote($entry->{$_}) } (keys %$entry)
     268        foreach my $entry (@entries) { 
     269            $entry{rkid} = $id
    248270            $abstract->insert_id( 
    249271                -id     => 'id', 
    250                 -table  => 'RegKeyEntries', 
     272                -table  => 'RKEntries', 
    251273                -set    => \%entry 
    252274            ) or Carp::croak __PACKAGE__."->_InsertRegKey Failed: Insert returned a NULL ID"; 
     
    293315    my %fields = %$h_fields; 
    294316    my $key; 
    295      
    296     foreach $key (keys %$hash) { 
    297         if (ref $key && ref $fields{$key}) { 
    298             $self->_VerifyHash($hash{$key},$h_fields{$key},$required); 
    299         } 
     317  
     318    foreach $key (keys %{$hash}) { 
     319        if (ref $fields{$key}) { 
     320            my $rc = 0; 
     321            if (ref $hash->{$key} eq 'HASH') { 
     322                eval {$self->_VerifyHash($hash->{$key},$h_fields->{$key},$required)}; 
     323                if ($@) { 
     324                    Carp::croak($@); 
     325                } 
     326            } 
     327            if (ref $hash->{$key} eq 'ARRAY') { 
     328                foreach (@{$hash->{$key}}) { 
     329                    eval {$self->_VerifyHash($_,$h_fields->{$key},$required)}; 
     330                    if ($@) { 
     331                        Carp::croak($@); 
     332                    } 
     333                } 
     334            } 
     335        } 
    300336        elsif (exists $fields{$key}) { 
    301337            delete $fields{$key}; 
    302338        } 
    303339        else { 
    304             Carp::croak("Invalid Record. $key is not a member of the Table"); 
     340            Carp::croak("Invalid Record. $key is not a member of the Table\n"); 
    305341        } 
    306342    } 
     
    376412    while ($dbname = $sth->fetchrow_array()) { 
    377413        if ($dbname eq 'HoneyClient') { 
    378             print "It thinks DB exists!\n";#TODO: Delete Debug statement 
    379414            return 1; 
    380415        } 
     
    435470    "); # or die "Failed Creating RegKeys Table"; not necessary because of RaiseError?? 
    436471    $abstract->run_query(" 
    437         CREATE TABLE RegKeyEntries 
     472        CREATE TABLE RKEntries 
    438473        ( 
    439474            id INT UNSIGNED AUTO_INCREMENT, 
    440             regkeyid INT UNSIGNED NOT NULL, 
     475            rkid INT UNSIGNED NOT NULL, 
    441476            name VARCHAR(255) NOT NULL, 
    442477            new_val VARCHAR(255) NOT NULL, 
    443             old_val VARCHAR(255) NOT NULL
     478            old_val VARCHAR(255)
    444479            PRIMARY KEY (id) 
    445480        ) ENGINE=InnoDB 
     
    680715     
    681716    eval { 
    682         my $fingerprint = {vmid => $self->{dbh}->quote($fpData->{vmid})}; 
     717        my $fingerprint = {vmid => $self->_quote($fpData->{vmid})}; 
    683718        $fingerprint->{numfiles}   = ref $fpData->{Files} eq 'ARRAY' ? scalar(@{$fpData->{Files}}) : 0; 
    684719        $fingerprint->{numregkeys} = ref $fpData->{RegKeys} eq 'ARRAY' ? scalar(@{$fpData->{RegKeys}}) : 0; 
     
    812847    my ($i,$rows,$r,$serial); 
    813848    for ($i = 0; $i < $numfiles; $i++) { 
    814          
    815     } 
    816849        $rows = $self->Select({ 
    817850            table => 'Files', 
    818             where  => {'md5'=>$h_sigData->{Files}->[$i]->{md5},'sha1'=>$h_sigData->{Files}->[$i]->{sha1}} 
     851            where  => { 
     852                'content' => { 
     853                    'md5' => $h_sigData->{Files}->[$i]->{content}->{md5}, 
     854                    'sha1' => $h_sigData->{Files}->[$i]->{content}->{sha1}, 
     855                } 
     856            } 
    819857        }); 
    820         while ($r = shift(@$rows)) { 
    821             $serial = delete $r->{serial}; 
    822             $fileMatches{$serial}{$i} = $r; 
    823         } 
     858        foreach (@$rows) { 
     859            $serial = $_->{serial}; 
     860            $serial = delete $_->{serial}; 
     861            $fileMatches->{$serial}->{$i} = $_; 
     862        } 
     863    } 
    824864    for ($i = 0; $i < $numregkeys; $i++) { 
    825865        $rows = $self->Select({ 
    826866            table => 'RegKeys', 
    827             where  => {'`key`' => $h_sigData->{RegKeys}->[$i]->{key}, 
    828                        'name'  => $h_sigData->{RegKeys}->[$i]->{name}, 
    829                        'value' => $h_sigData->{RegKeys}->[$i]->{value}, 
     867            where  => {'key_name' => $h_sigData->{RegKeys}->[$i]->{key}, 
     868                       'entries'  => $h_sigData->{RegKeys}->[$i]->{entries}, 
    830869            } 
    831870        }); 
     
    901940 
    902941sub Select { 
    903     my ($self,$h_query) = @_;     
     942    my ($self,$h_query) = @_; 
    904943    if (!exists $tables{$h_query->{table}}){ 
    905944        Carp::carp("Attempted query on non-existent table: $h_query->{table}"); 
    906945        return; 
    907946    } 
    908     if ( !$self->_VerifyHash($h_query->{where}, $tables{$h_query->{table}}{fields},0) ){ 
    909         my @f = keys %{$h_query->{where}}; 
    910         Carp::carp("Query contains invalid fields: @f"); 
    911         return; 
    912     } 
    913     map {$h_query->{where}->{$_} = $self->{dbh}->quote($h_query->{where}->{$_})} (keys %{$h_query->{where}}); 
    914     if ($tables{$h_query->{table}}{selectFunc}) { 
    915         return &{$tables{$h_query->{table}}{selectFunc}}($self,$h_query); 
     947    if (!$self->_VerifyHash($h_query->{where}, $tables{$h_query->{table}}{fields},0) ) { 
     948        my $f = join ',',(keys %{$h_query->{where}});#TODO: Error Handling 
     949        Carp::carp("Query contains invalid fields $f"); 
     950        return; 
     951    } 
     952    if ($tables{ $h_query->{table} }{selectFunc}) { 
     953        return &{ $tables{$h_query->{table}}{selectFunc} }($self,$h_query); 
    916954    } 
    917955    else { 
    918956        my $query = new Relations::Query( 
    919             -select   => '*', 
    920             -from     => $h_query->{table}, 
    921             -where    => $h_query->{where}, 
    922             -order_by => $h_query->{order_by}, 
    923             -limit    => $h_query->{limit} 
     957            -select => '*', 
     958            -from   => $h_query->{table} 
    924959        ); 
     960        foreach ('order_by','limit') { 
     961            $query->set("-$_" => $h_query->{$_}) if (defined $h_query->{$_}); 
     962        } 
     963        if ( defined $h_query->{where} ) { 
     964            my %where = %{$self->_quote($h_query->{where})}; 
     965            $query->set(-where => \%where); 
     966        } 
    925967        return $self->{dbh}->selectall_arrayref($query->get(),{ Slice => {} }); 
    926968    } 
     
    933975sub _SelectFiles { 
    934976    my ($self,$q) = @_; 
    935     $q->{'select'} = [ 'Files.id','Files.contentid','Files.serial','Files.name', 
    936        'Files.path','Files.datecreated','Files.notes','FileContent.md5','FileContent.sha1', 
    937        'FileContent.size','FileContent.type' 
     977    my (%where,%content); 
     978    my $select = [ 'Files.id','Files.contentid','Files.serial','Files.name', 
     979       'Files.path','Files.datecreated','FileContent.md5','FileContent.sha1', 
     980       'FileContent.size','FileContent.type','FileContent.notes' 
    938981    ]; 
    939     #map {$q->{where}->{$_} = $self->{dbh}->quote($q->{where}->{$_})} (keys %{$q->{where}}); 
    940982    my $query = new Relations::Query( 
    941        -select => $q->{'select'}
     983       -select => $select
    942984       -from   => 'Files JOIN FileContent on Files.contentid=FileContent.id', 
    943985    ); 
    944     foreach my $property ('where','order_by','limit') { 
    945         $query->add("-$property" => $q->{$property}) if( $q->{$property} ); 
     986    if (exists $q->{where}) { 
     987        %where = %{$self->_quote($q->{where})}; 
     988        %content = %{delete $where{content}} if (exists $where{content}); 
     989        $query->set(-where => \%where) if (keys %where); 
     990        $query->add(-where => \%content) if (keys %content); 
     991    } 
     992    foreach ('order_by','limit') { 
     993        $query->set("-$_" => $q->{$_}) if( $q->{$_} ); 
    946994    } 
    947995    my $sth = $self->{dbh}->prepare($query->get()); 
    948996    $sth->execute(); 
    949997     
    950     my $file = {}; my @files;    
    951     map {$file->{$_}=undef} ('id','contentid','serial','name','path','datecreated','notes'); 
    952     map {$file->{content}->{$_}=undef} ('md5','sha1','size','type'); 
    953     $sth->bind_columns(\$file->{id},\$file->{contentid},\$file->{serial},\$file->{name}, 
    954        \$file->{path},\$file->{datecreated},\$file->{notes},\$file->{content}->{md5},\$file->{content}->{sha1}, 
    955        \$file->{content}->{size},\$file->{content}->{type} 
    956     ); 
     998    my %file; my @files;     
     999    map {$file{$_}=''} ('id','contentid','serial','name','path','datecreated'); 
     1000    map {$file{content}{$_}=undef} ('md5','sha1','size','type','notes'); 
     1001    eval { 
     1002        $sth->bind_columns( 
     1003            \($file{id},$file{contentid},$file{serial},$file{name},$file{path},$file{datecreated},$file{content}{md5}, 
     1004            $file{content}{sha1},$file{content}{size},$file{content}{type},$file{content}{notes}) 
     1005        ); 
     1006    }; 
     1007    if ($@) { 
     1008        Carp::croak($@); 
     1009    } 
     1010 
    9571011    while ($sth->fetch) { 
    958         push @files, $file; 
    959     }    
     1012        my %tempf = %file; 
     1013        my %tempc = %{$file{content}}; 
     1014        $tempf{content} = \%tempc; 
     1015        push @files, \%tempf; 
     1016    } 
    9601017    return \@files; 
    9611018} 
     
    9681025    #TODO: _SelectRegKeys function 
    9691026    my ($self,$q) = @_; 
    970  
    971     my ($rowR,$rowE,@regkeys,%ids); 
    972     %$rowR = map {$_,undef}, ('id','serial','key_name','status','datecreated','notes'); 
    973     %$rowE = map {$_,undef}, ('name','new_val','old_val','rkid'); 
    974  
    975     my $query = new Relations::Query(); my $entries; 
    976     if ($entries = delete exists $q->{where}->{entries}) { 
    977         $query->set( 
    978             -select => "RegKeys.*,RKEntries.name,RKEntries.new_val,RKEntries.old_val,RKEntries.rkid", 
    979             -from   => "RegKeys JOIN RKEntries ON RegKeys.id=RKEntries.rkid" 
    980         ); 
    981         foreach my $entry (@{$entries}) { 
    982             $query->set(-where => $q->{where}); 
    983             $query->add(-where => $entry); 
    984             my $sth = $self->{dbh}->prepare($query->get()); 
    985             $sth->execute(); 
    986             $sth->bind_columns(\$rowR->{id},\$rowR->{serial},\$rowR->{key_name},\$rowR->{status}, 
    987                 \$rowR->{datecreated},\$rowR->{notes},\$rowE->{name},\$rowE->{new_val}, 
    988                 \$rowE->{old_val},\$rowE->{rkid}); 
    989             $sth->fetch(); 
    990             if(exists $ids{$rowR->{id}) { 
    991                 push @($regkeys[$rowR->{id}]->{entries}),$rowE; 
     1027    my (@regkeys,%ids,%entries); 
     1028    my %rowR = map {$_,undef} ('id','serial','key_name','status','datecreated','notes'); 
     1029    my %rowE = map {$_,undef} ('name','new_val','old_val','rkid'); 
     1030    my $query = new Relations::Query(); 
     1031    if ($q->{where}) { 
     1032        my %where = %{$self->_quote(delete $q->{where})}; 
     1033        if (%entries = %{delete $where{entries}}) { 
     1034            $query->set( 
     1035                    -select => "RegKeys.*,RKEntries.name,RKEntries.new_val,RKEntries.old_val,RKEntries.rkid", 
     1036                    -from   => "RegKeys JOIN RKEntries ON RegKeys.id=RKEntries.rkid" 
     1037            ); 
     1038            foreach my $entry (@{$entries}) { 
     1039                $query->set(-where => \%where) if (keys %where); 
     1040                $query->add(-where => \%$entry); 
     1041                my $sth = $self->{dbh}->prepare($query->get()); 
     1042                $sth->execute(); 
     1043                $sth->bind_columns(\$rowR{id},\$rowR{serial},\$rowR{key_name},\$rowR{status}, 
     1044                        \$rowR{datecreated},\$rowR{notes},\$rowE{name},\$rowE{new_val}, 
     1045                        \$rowE{old_val},\$rowE{rkid}); 
     1046                while($sth->fetch()) { 
     1047                    if(exists $ids{$rowR{id}}) { 
     1048                        push @{$regkeys[$rowR{id}]->{entries}},\%rowE; 
     1049                    } 
     1050                    else { 
     1051                        push @regkeys, \%rowR; 
     1052                        $ids{$rowR{id}} = $#regkeys; 
     1053                        push @{$regkeys[$rowR{id}]->{entries}},\%rowE; 
     1054                    } 
     1055                } 
    9921056            } 
    993             else { 
    994                 push $regkeys, $rowR; 
    995                 $ids{$rowR->{id}} = $#regkeys; 
    996                 push @{$regkeys[$#regkeys]->{entries}},$rowE; 
     1057        } 
     1058        else { 
     1059            $query->set( 
     1060                    -select => "*", 
     1061                    -from   => "RegKeys", 
     1062                    -where  => $q->{where} 
     1063                    ); 
     1064            @regkeys = @{$self->{dbh}->selectall_arrayref($query->get(),{ Slice => {} })}; 
     1065            foreach my $row (@regkeys) { 
     1066                my $subquery = new Relations::Query( 
     1067                        -select => ['name','new_val','old_val'], 
     1068                        -from   => 'RKEntries', 
     1069                        -where  => {rkid => $row->{id}} 
     1070                        ); 
     1071                $rowE = $self->{dbh}->selectall_arrayref($query->get(),{ Slice => {} }); 
     1072                if(scalar @{$rowE}) { $row->{entries} = $rowE; } 
    9971073            } 
    998         } 
    999     } 
    1000     else { 
    1001         $query->set( 
    1002             -select => "*", 
    1003             -from   => "RegKeys", 
    1004             -where  => $q->{where} 
    1005         ); 
    1006         @regkeys = @{$self->{dbh}->selectall_arrayref($query->get(),{ Slice => {} })}; 
    1007         foreach my $row (@regkeys) { 
    1008             my $subquery = new Relations::Query( 
    1009                 -select => ['name','new_val','old_val'], 
    1010                 -from   => 'RKEntries', 
    1011                 -where  => {rkid => $row->{id}} 
    1012             ); 
    1013             $rowE = $self->{dbh}->selectall_arrayref($query->get(),{ Slice => {} }); 
    1014             if(scalar @{$rowE}) { $row->{entries} = $rowE; } 
    10151074        } 
    10161075    } 
     
    10231082sub _SelectFingerprint { 
    10241083    my ($self,$q) = @_; 
    1025     map {$q->{where}->{$_} = $self->{dbh}->quote($q->{where}->{$_})} (keys %{$q->{where}}); 
    10261084    my $query = new Relations::Query( 
    10271085        -select => '*', 
    10281086        -from   => 'Fingerprints', 
    1029         -where  => $q->where, 
    10301087        -limit  => 1 
    10311088    ); 
     1089    if (exists $q->{where} ) { 
     1090        my %where = %{$self->_quote($q->{where})}; 
     1091        $query->set(-where => \%where); 
     1092    } 
    10321093    my $fingerprint = $self->{dbh}->selectrow_hashref($query->get()) or return undef; 
    10331094    # Get Files