Changeset 1460

Show
Ignore:
Timestamp:
04/04/08 17:15:49 (6 months ago)
Author:
kindlund
Message:

Still working on the integration.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • honeyclient/branches/exp/kindlund-simpler_agent/lib/HoneyClient/Manager/VM/Clone.pm

    r1453 r1460  
    264264 
    265265# Make sure Storable loads. 
    266 BEGIN { use_ok('Storable', qw(dclone)) or diag("Can't load Storable package.  Check to make sure the package library is correctly listed within the path."); } 
     266BEGIN { use_ok('Storable', qw(dclone thaw)) or diag("Can't load Storable package.  Check to make sure the package library is correctly listed within the path."); } 
    267267require_ok('Storable'); 
    268268can_ok('Storable', 'dclone'); 
    269 use Storable qw(dclone); 
     269can_ok('Storable', 'thaw'); 
     270use Storable qw(dclone thaw); 
     271 
     272# Make sure MIME::Base64 loads. 
     273BEGIN { use_ok('MIME::Base64', qw(encode_base64 decode_base64)) or diag("Can't load MIME::Base64 package.  Check to make sure the package library is correctly listed within the path."); } 
     274require_ok('MIME::Base64'); 
     275can_ok('MIME::Base64', 'encode_base64'); 
     276can_ok('MIME::Base64', 'decode_base64'); 
     277use MIME::Base64 qw(encode_base64 decode_base64); 
    270278 
    271279# Make sure Data::Dumper loads 
     
    331339 
    332340# Use Storable Library 
    333 use Storable qw(dclone); 
     341use Storable qw(dclone thaw); 
    334342 
    335343# Use Dumper Library 
     
    360368# Include Database Libraries 
    361369use HoneyClient::Manager::Database; 
     370 
     371# Include Base64 Libraries 
     372use MIME::Base64 qw(encode_base64 decode_base64); 
    362373 
    363374=pod 
     
    526537            HoneyClient::Manager::VM->destroy(); 
    527538             
    528             # Sleep a bit, in order for the terminated VM daemon to release 
    529             # its network bindings. 
    530             # XXX: See if this is still needed. 
    531             #sleep(20); 
    532  
    533539            # Reinitialize VM daemon. 
    534540            HoneyClient::Manager::VM->init(); 
     
    543549        if (!defined($som)) { 
    544550            $LOG->error("Unable to suspend VM (" . $self->{'config'} . ")."); 
     551            $self->_changeStatus(status => "error"); 
     552        } else { 
     553            $self->_changeStatus(status => "suspended"); 
    545554        } 
    546555    } 
     
    553562    # Upon termination, destroy the global instance of the VM manager. 
    554563    if ($OBJECT_COUNT == 0) { 
    555         # XXX: Delete this, eventually. 
    556         $LOG->info("Destroying VM daemon."); 
     564        $LOG->debug("Destroying VM daemon."); 
    557565        HoneyClient::Manager::VM->destroy(); 
    558566    } 
     
    695703            $LOG->info("Initialized clone VM (" . $self->{'name'} . ") using IP (" . 
    696704                       $self->{'ip_address'} . ") and MAC (" . $self->{'mac_address'} . ")."); 
     705            $LOG->info("Waiting for Agent daemon to initialize inside clone VM."); 
    697706            $logMsgPrinted = 1; 
    698707        } 
     
    739748} 
    740749 
    741 # TODO: Comment this. 
     750# Helper function designed to "pop" a key off a given hashtable. 
     751# When given a hashtable reference, this function will extract a valid key 
     752# from the hashtable and delete the (key, value) pair from the 
     753# hashtable.  The link with the highest score is returned. 
     754
     755# Inputs: hashref 
     756# Outputs: valid key, or undef if the hash is empty 
     757sub _pop { 
     758 
     759    # Get supplied hash reference. 
     760    my $hash = shift; 
     761 
     762    # Get the highest score. 
     763    my @array = sort {$$hash{$b} <=> $$hash{$a}} keys %{$hash}; 
     764    my $topkey = $array[0]; 
     765 
     766    # Delete the key from the hashtable. 
     767    if (defined($topkey)) { 
     768        delete $hash->{$topkey}; 
     769    } 
     770 
     771    # Return the key found. 
     772    return $topkey; 
     773
     774 
     775# Helper function designed to change the status of a supplied 
     776# VM Clone object. 
     777
     778# Output: The updated Clone $object, reflecting the status change 
     779# of the clone VM.  Will croak if this operation fails. 
    742780# XXX: Should this be made public? 
    743781sub _changeStatus { 
     
    788826            } elsif (/deleted/) { 
    789827                HoneyClient::Manager::Database::set_client_deleted($self->{'database_id'}); 
     828            } elsif (/error/) { 
     829                HoneyClient::Manager::Database::set_client_error($self->{'database_id'}); 
    790830            } 
    791831        } 
     
    793833 
    794834    return $self; 
     835} 
     836 
     837# XXX: Comment this. 
     838sub _dumpFingerprint { 
     839 
     840    # Dump the fingerprint to a file, if needed. 
     841    my $COMPROMISE_FILE = getVar(name => "fingerprint_dump"); 
     842    if (length($COMPROMISE_FILE) > 0 && 
     843        defined($fingerprint)) { 
     844        $LOG->info("Saving fingerprint to '" . $COMPROMISE_FILE . "'."); 
     845        my $dump_file = new IO::File($COMPROMISE_FILE, "a"); 
     846 
     847        # XXX: Delete this block, eventually. 
     848        $Data::Dumper::Terse = 0; 
     849        $Data::Dumper::Indent = 2; 
     850        print $dump_file "\$vmName = \"" . $vmName . "\";\n"; 
     851        print $dump_file Dumper($fingerprint); 
     852        $dump_file->close(); 
     853    } 
    795854} 
    796855 
     
    875934    # Now, kill the VM daemon. 
    876935    HoneyClient::Manager::VM->destroy(); 
    877     # XXX: See if this is still needed. 
    878     #sleep (10); 
    879936 
    880937    # Create a generic empty clone, with test state data. 
     
    910967# Kill the child daemon, if it still exists. 
    911968HoneyClient::Manager::VM->destroy(); 
    912 # XXX: See if this is still needed. 
    913 #sleep (1); 
    914969 
    915970# Report any failure found. 
     
    10951150                       "# Your master VM is: " . getVar(name => "master_vm_config", namespace => "HoneyClient::Manager::VM") . "\n" . 
    10961151                       "#\n" . 
    1097                        "# Do you want to test cloning this master VM?", "no"); 
     1152                       "# Do you want to test cloning and archiving this master VM?", "no"); 
    10981153    if ($question =~ /^y.*/i) { 
    10991154 
     
    11241179# Kill the child daemon, if it still exists. 
    11251180HoneyClient::Manager::VM->destroy(); 
    1126 # XXX: See if this is still needed. 
    1127 #sleep (1); 
    11281181 
    11291182# Report any failure found. 
     
    11841237} 
    11851238 
    1186 # TODO: Comment this. 
    1187 sub something { 
     1239=pod 
     1240 
     1241=head2 $object->drive(work => $work) 
     1242 
     1243=over 4 
     1244 
     1245Drives the Agent running inside the Clone VM, based upon 
     1246the work supplied.  If any portion of the work causes the 
     1247VM to become compromised, then the compromised VM will be 
     1248suspended, archived, and logged -- while a new clone VM 
     1249will be created to continue processing the remaining 
     1250work. 
     1251 
     1252I<Inputs>: 
     1253 B<$work> is a required argument, referencing a hashtable of 
     1254different parameters to pass to the driven application, 
     1255which is running on the Agent inside the cloned VM. 
     1256 
     1257I<Notes>: 
     1258 Each "key" in the $work hashtable is a parameter; 
     1259each "value" in the $work hashtable is an integer, 
     1260reflecting the priority assigned to that key.  Large values 
     1261indicate high priority. 
     1262 
     1263Here is an example of a possible $work hashtable: 
     1264 
     1265 my $work = { 
     1266     "http://www.mitre.org/"  => 10, # First to process 
     1267     "http://www.google.com/" =>  5, # Second to process 
     1268     "http://www.cnn.com/"    =>  1, # Last to process 
     1269 }; 
     1270 
     1271=back 
     1272 
     1273=begin testing 
     1274 
     1275# Shared test variables. 
     1276my ($stub, $som, $URL); 
     1277my $testVM = $ENV{PWD} . "/" . getVar(name      => "test_vm_config", 
     1278                                      namespace => "HoneyClient::Manager::VM::Test"); 
     1279 
     1280# Catch all errors, in order to make sure child processes are 
     1281# properly killed. 
     1282eval { 
     1283 
     1284    # Pretend as though no other Clone objects have been created prior 
     1285    # to this point. 
     1286    $HoneyClient::Manager::VM::Clone::OBJECT_COUNT = -1; 
     1287     
     1288    my $question; 
     1289    $question = prompt("#\n" . 
     1290                       "# Note: Testing real drive operations will *ONLY* work\n" . 
     1291                       "# with a fully functional master VM that has the HoneyClient code\n" . 
     1292                       "# loaded upon boot-up.\n" . 
     1293                       "#\n" . 
     1294                       "# Your master VM is: " . getVar(name => "master_vm_config", namespace => "HoneyClient::Manager::VM") . "\n" . 
     1295                       "#\n" . 
     1296                       "# Do you want to test cloning and driving this master VM?", "no"); 
     1297    if ($question =~ /^y.*/i) { 
     1298 
     1299        # Create a generic empty clone, with test state data. 
     1300        my $clone = HoneyClient::Manager::VM::Clone->new(); 
     1301        my $cloneConfig = $clone->{config}; 
     1302 
     1303# TODO: Fix this. 
     1304 
     1305        # Archive the clone. 
     1306        #$clone->archive(snapshot_file => $snapshot); 
     1307 
     1308        # Wait for the archive to complete. 
     1309        #sleep (45); 
     1310     
     1311        # Test if the archive worked. 
     1312        #is(-f $snapshot, 1, "archive(snapshot_file => '$snapshot')") or diag("The archive() call failed."); 
     1313    
     1314        #unlink $snapshot; 
     1315        #$clone = undef; 
     1316     
     1317        # Connect to daemon as a client. 
     1318        $stub = getClientHandle(namespace => "HoneyClient::Manager::VM"); 
     1319     
     1320        # Destroy the clone VM. 
     1321        $som = $stub->destroyVM(config => $cloneConfig); 
     1322    } 
     1323}; 
     1324 
     1325# Kill the child daemon, if it still exists. 
     1326HoneyClient::Manager::VM->destroy(); 
     1327 
     1328# Report any failure found. 
     1329if ($@) { 
     1330    fail($@); 
     1331
     1332 
     1333=end testing 
     1334 
     1335=cut 
     1336 
     1337sub drive { 
    11881338 
    11891339    # Extract arguments. 
     
    12061356    }); 
    12071357 
    1208     # Sanity checks; check if any args were specified
     1358    # Sanity check.  Make sure we get a valid argument
    12091359    my $argsExist = scalar(%args); 
    1210  
     1360    if (!$argsExist ||  
     1361        !exists($args{'work'}) || 
     1362        !defined($args{'work'})) { 
     1363 
     1364        # Croak if no valid argument is supplied. 
     1365        $LOG->error("Error: No work argument supplied."); 
     1366        Carp::croak "Error: No work argument supplied."; 
     1367    } 
     1368 
     1369    # TODO: Add more. 
     1370    my $som; 
     1371    my $result; 
     1372    my $currentWork; 
     1373    my $finishedWork = { 
     1374        'client_id'     => $self->{'database_id'}, 
     1375        'links_visited' => {},  
     1376        'links_timed_out' => {}, 
     1377        'links_ignored' => {}, 
     1378    }; 
     1379    my $numWorkInserted; 
     1380 
     1381    while (scalar(%{$args{'work'}})) { 
     1382 
     1383        # Extract the highest priority work. 
     1384        $currentWork = _pop($args{'work'}); 
     1385 
     1386        $LOG->info("(" . $self->{'name'} . ") - " . $self->{'driver_name'} . " - Driving To Resource: " . $currentWork); 
     1387        $som = $self->{'_agent_handle'}->drive(driver_name => $self->{'driver_name'}, 
     1388                                           parameters  => encode_base64($currentWork)); 
     1389        $result = thaw(decode_base64($som->result())); 
     1390 
     1391# XXX: Delete this, eventually. 
     1392print Dumper($result); 
     1393     
     1394        # Figure out if there was a compromise found. 
     1395        if (scalar(@{$result->{'fingerprint'}->{os_processes}})) { 
     1396            $LOG->warn("(" . $self->{'name'} . ") - " . $self->{'driver_name'} . " - Integrity Check: FAILED"); 
     1397            # XXX: Test this. 
     1398            _dumpFingerprint($result->{'fingerprint'}); 
     1399        } else { 
     1400            $LOG->info("(" . $self->{'name'} . ") - " . $self->{'driver_name'} . " - Integrity Check: PASSED"); 
     1401        } 
     1402 
     1403        $finishedWork->{'links_visited'}->{$currentWork} = $result->{'time_at'}; 
     1404 
     1405        $numWorkInserted = HoneyClient::Manager::Database::insert_history_urls($finishedWork); 
     1406        $LOG->info($numWorkInserted . " URL(s) Inserted."); 
     1407 
     1408        # Flush the work history, after committing to the database. 
     1409        $finishedWork->{'links_visited'} = {}; 
     1410 
     1411    } 
    12111412} 
    12121413