Changeset 1421

Show
Ignore:
Timestamp:
04/02/08 16:42:12 (5 months ago)
Author:
kindlund
Message:

Housekeeping.

Files:

Legend:

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

    r1420 r1421  
    103103    } 
    104104 
    105     # XXX: Not sure if this is still needed. 
    106     # Check to see if ithreads are compiled into this version of Perl. 
    107     #$Config{useithreads} or Carp::croak "Error: Recompile Perl with ithread support, in order to use this module.\n"; 
    108  
    109105    $SIG{PIPE} = 'IGNORE'; # Do not exit on broken pipes. 
    110106} 
     
    176172use HoneyClient::Agent::Integrity; 
    177173 
    178 # Include Thread Libraries 
    179 #use threads; 
    180 #use threads::shared; 
    181 #use Thread::Semaphore; 
    182 #use Thread::Queue; 
    183  
    184174# Include utility access to global configuration. 
    185175use HoneyClient::Util::Config qw(getVar); 
     
    220210our $PERFORM_INTEGRITY_CHECKS = 
    221211    getVar(name => "perform_integrity_checks"); 
    222  
    223 # A globally shared object, containing the initialized integrity 
    224 # state of the VM -- ready to be checked against, at any time after 
    225 # initialization. 
    226 #our $integrityData; 
    227  
    228 # A globally shared, serialized hashtable, containing data per 
    229 # registered driver.  Specifically, for each @DRIVER <entry>, 
    230 # the following data is created: 
    231 #   '<entry_name>' => { 
    232 #       'state'     => undef; # Driver-specific state information. 
    233 #       'thread_id' => undef; # The thread registered to handle 
    234 #                             # the driver. 
    235 #       'status'    => undef; # Driver-specific status information. 
    236 #       'next'      => undef; # Driver-specific connection information. 
    237 #   } 
    238 #our $driverData     : shared = undef; 
    239  
    240 # A global shared semaphore, designed to limit read/write 
    241 # access to $driverData, by only allowing one thread 
    242 # at a time to freeze/thaw the data.  While $driverData is 
    243 # a scalar, the freeze/thaw operation is not atomic; thus, 
    244 # this semaphore ensures all operations remain atomic. 
    245 #our $driverDataSemaphore     = Thread::Semaphore->new(1); 
    246  
    247 # A globally shared hashtable, containing one "update queue" 
    248 # per driver.  This allows different "driver threads" to 
    249 # receive asynchronous updates to their state information 
    250 # in a thread-safe manor. 
    251 #our %driverUpdateQueues : shared = ( ); 
    252212 
    253213####################################################################### 
     
    329289    # Figure out what our list of allowed Drivers are.  
    330290    $ALLOWED_DRIVERS = getVar(name => 'allowed_drivers')->{name}; 
    331  
    332     # Acquire data lock. 
    333     #_lock(); 
    334  
    335     # Initialize the $driverData shared hashtable. 
    336 #    my $data = { }; 
    337 #    for my $driverName (@{$ALLOWED_DRIVERS}) { 
    338 #     
    339 #        eval "use $driverName"; 
    340 #        if ($@) { 
    341 #            $LOG->fatal($@); 
    342 #            Carp::croak $@; 
    343 #        } 
    344 #  
    345 #        $data->{$driverName} = {  
    346 #            'state'     => undef, 
    347 #            'thread_id' => undef, 
    348 #            'status'    => undef, 
    349 #            'next'      => undef, 
    350 #        }; 
    351 # 
    352 #        # Initialize the corresponding %driverUpdateQueues 
    353 #        $driverUpdateQueues{$driverName} = new Thread::Queue; 
    354 #    } 
    355 # 
    356 #    # Perform initial integrity baseline check. 
    357 #    if ($PERFORM_INTEGRITY_CHECKS) { 
    358 #        $integrityData = HoneyClient::Agent::Integrity->new(); 
    359 #        $integrityData->closeFiles(); 
    360 #    } 
    361 # 
    362 #    # Release data lock. 
    363 #    _unlock($data); 
    364291 
    365292    my $argsExist = scalar(%args); 
     
    396323        } 
    397324 
    398         my $daemon = getServerHandle(address => $args{'address'}, 
    399                                      port    => $args{'port'}); 
     325        our $daemon = getServerHandle(address => $args{'address'}, 
     326                                      port    => $args{'port'}); 
    400327 
    401328        # Unbind port, if we're shutting down. 
     
    413340            $daemon->handle(); 
    414341        } 
    415  
    416 #        # Populate our driver's object state with the remaining 
    417 #        # arguments. 
    418 #        delete($args{'address'}); 
    419 #        delete($args{'port'}); 
    420 # 
    421 #        # If this call fails, an exception is thrown or the process 
    422 #        # remains locked.  If the process locks, then external 
    423 #        # detection is used to catch for these types of failures. 
    424 #        updateState($class, encode_base64(nfreeze(\%args))); 
    425 #     
    426 #        for (;;) { 
    427 #            $daemon->handle(); 
    428 #        } 
    429342    } 
    430343} 
     
    476389    } 
    477390    if ($ret) { 
    478 #        # Acquire data lock. 
    479 #        _lock(); 
    480 # 
    481 #        # Destroy all globally shared state data. 
    482 #        $URL                  = undef; 
    483 #        $URL_BASE             = undef; 
    484391        $DAEMON_PID           = undef; 
    485  
    486 #        $driverData           = undef; 
    487 #        $driverDataSemaphore  = Thread::Semaphore->new(1); 
    488 #        %driverUpdateQueues   = ( ); 
    489 # 
    490 #        # Destroy all integrity data, if defined. 
    491 #        if (defined($integrityData)) { 
    492 #            $integrityData->destroy(); 
    493 #        } 
    494 #        $integrityData        = undef; 
    495 #         
    496 #        # Release data lock. 
    497 #        _unlock(); 
    498392    } 
    499393    return $ret; 
     
    503397# Private Methods Implemented                                         # 
    504398####################################################################### 
    505  
    506 # Helper function designed to acquire exclusive access to the 
    507 # shared $driverData, for use within any thread. 
    508 # 
    509 # In perl, it is difficult to share hashtables between threads. 
    510 # However, it is easy to share scalars between threads. 
    511 # As such, we share a hashtable between threads by *serializing* 
    512 # the data using nfreeze().  The result can be stored in a scalar. 
    513 #  
    514 # When we are in a thread where we subsequently want to read/use 
    515 # this hashtable, we thaw() the serialized data (it performs the 
    516 # deserialization process) and use the hashtable accordingly. 
    517 # 
    518 # This function guarantees that no other thread will access 
    519 # $driverData and returns the thaw()'d contents of $driverData. 
    520 # 
    521 # Input: None 
    522 # Output: driverData (deserialized) 
    523 # XXX: DELETE 
    524 sub _lock { 
    525     # Acquire lock on stored driver state. 
    526     $driverDataSemaphore->down(); 
    527          
    528     # Thaw the data. 
    529     return thaw($driverData); 
    530 } 
    531  
    532 # Helper function designed to release exclusive access to the 
    533 # shared $driverData, for use within any thread. 
    534 # 
    535 # By calling this function, we assume that the thread has already 
    536 # called _lock() and would like to (optionally) update $driverData 
    537 # with a new, modified hashtable, prior to releasing the lock 
    538 # on $driverData. 
    539 # 
    540 # This function can optionally take in a normal hashtable reference, 
    541 # overwriting the $driverData with the contents of the supplied 
    542 # hashtable.  Once the $driverData's updated contents has been 
    543 # set and serialized, this function releases the corresponding 
    544 # lock. 
    545 # 
    546 # Input: driverData (deserialized, optional) 
    547 # Output: None 
    548 # XXX: DELETE 
    549 sub _unlock { 
    550     my $data = shift; 
    551  
    552     if (defined($data)) { 
    553         # Refreze changed data. 
    554         $driverData = nfreeze($data); 
    555     } 
    556      
    557     # Release lock on stored driver state. 
    558     $driverDataSemaphore->up(); 
    559 } 
    560  
    561 # Helper function designed to retrieve queued, external 
    562 # updates to driver state information from %driverUpdateQueues. 
    563 #  
    564 # When called from run(), this function takes in the corresponding 
    565 # Driver object; checks to see if there's a new entry within the 
    566 # driver's corresponding update queue; and dequeues the *all* 
    567 # entries in the queue, overwriting the Driver's state data 
    568 # accordingly. 
    569 # 
    570 # The external updateState() call adds new driver state into the queue, 
    571 # one entry per call.  The internal _update() function merges this 
    572 # driver state with the currently running driver, merging everything 
    573 # queued per call.  In order words, a single call to _update() 
    574 # *WILL* empty the corresponding Driver update queue completely 
    575 # -- all entries within the queue will be dequeued per _update() 
    576 # call made. 
    577 # 
    578 # Input: driver 
    579 # Output: driver (updated) 
    580 # XXX: DELETE 
    581 sub _update { 
    582     # Extract arguments. 
    583     my $driver = shift; 
    584  
    585     # Figure out the corresponding driver name. 
    586     my $driverName = ref($driver); 
    587  
    588     # Extract the corresponding queue. 
    589     my $queue = $driverUpdateQueues{$driverName}; 
    590  
    591     # XXX: One possible DoS condition here; what if 
    592     # the manager keeps feeding updates to the Agent 
    593     # before the Agent has a chance to do any work? 
    594      
    595     # If we have data in our driver specific queue... 
    596     while ($queue->pending) { 
    597  
    598         # Update our driver state with the first entry 
    599         # found... 
    600         my $queuedData = thaw($queue->dequeue_nb); 
    601  
    602         # Sanity check: Only copy defined data. 
    603         if (defined($queuedData)) { 
    604  
    605             # Copy (and overwrite) overloaded object data  
    606             # into shared memory.  This looks creepy, I know, but 
    607             # it actually works.  We're essentially identifying 
    608             # driver-specific parameters that the user supplied 
    609             # via $queuedData and overwriting our current driver state 
    610             # with any matching, user supplied values. 
    611             @{$driver}{keys %{$queuedData}} = values %{$queuedData}; 
    612         } 
    613     } 
    614  
    615     # Return the modified driver state. 
    616     return $driver; 
    617 } 
    618399 
    619400####################################################################### 
     
    784565} 
    785566 
    786 # TODO: Clean up this comment block. 
    787 # This function should do the following: 
    788 # - Initialize all drivers with starting state. 
    789 # - "Drive" each driver, one-by-one. 
    790 # - Collect any integrity violations found, with offending 
    791 #   state information. 
    792 # 
    793 # Notes: 
    794 # This function will eventually sit in a sub-thread, allowing the parent 
    795 # thread to return without any delay.  It is expected that the Manager 
    796 # would then subsequently call a getStatus() operation, in order to 
    797 # then poll for any new violations found. 
    798 # 
    799 # TODO: We need to create a fault reporting mechanism, in order 
    800 # to properly deal with exceptions/faults that occur within this 
    801 # thread. 
    802 # XXX: DELETE 
    803 sub worker { 
    804  
    805     # Extract arguments. 
    806     my $args = shift; 
    807     my $driverName = $args->{'driver_name'}; 
    808     my $integrity  = $args->{'integrity'}; 
    809  
    810     # Temporary variable, used to hold thawed driver data. 
    811     my $data = undef; 
    812  
    813     # Yield processing to parent thread. 
    814     threads->yield(); 
    815  
    816     # Trap all faults that may occur from these asynchronous operations. 
    817     eval { 
    818  
    819         ################################### 
    820         ### Driver Initialization Phase ### 
    821         ################################### 
    822  
    823         # Initially set all driver objects to undef.  
    824         my $driver = undef; 
    825  
    826         # Last resource used by driver. 
    827         my $lastResource = undef; 
    828      
    829         # Acquire lock on stored driver state. 
    830         $data = _lock(); 
    831  
    832         # Now, initialize each driver object.  
    833         # Figure out which $driver object to use... 
    834         my $driverClass = $driverName; 
    835  
    836         if (!defined($data->{$driverName}->{'state'})) { 
    837      
    838             # If the driver state is undefined, then 
    839             # create a new state object. 
    840             $driver = $driverClass->new(); 
    841  
    842         } else { 
    843             # Then the driver state object is already defined, 
    844             # so go ahead and reuse it. 
    845             $driver = $driverClass->new( 
    846                 %{$data->{$driverName}->{'state'}},  
    847             ); 
    848         } 
    849  
    850         # Next, we make sure we have no updates, before we update 
    851         # the corresponding shared memory version. 
    852         $driver = _update($driver); 
    853  
    854         # Once we've initialized the object, be sure to update 
    855         # the corresponding shared memory version.  We do this 
    856         # one time before the loop starts, in case we end up 
    857         # finishing before we drove anywhere. 
    858                  
    859         # Copy object data to shared memory. 
    860         $data->{$driverName}->{'next'} = $driver->next(); 
    861         $data->{$driverName}->{'status'} = $driver->status(); 
    862         $data->{$driverName}->{'status'}->{'is_compromised'} = 0; 
    863         $data->{$driverName}->{'status'}->{'is_running'} = 1; 
    864         $data->{$driverName}->{'state'} = $driver; 
    865  
    866         # Release lock on stored driver state. 
    867         _unlock($data); 
    868                  
    869         ################################### 
    870         ### Driver Running Phase        ### 
    871         ################################### 
    872  
    873         # Boolean to indicate that the driver is about to transition 
    874         # to a new set of targets upon the next drive() operation. 
    875         my $driverTargetsChanged = 0; 
    876  
    877         # Boolean to indicate that the driver has been compromised. 
    878         my $isCompromised = 0; 
    879  
    880         # Variable to hold any changes found in a compromise. 
    881         my $changes = undef; 
    882  
    883         while (!$driver->isFinished() && !$driverTargetsChanged) { 
    884             # XXX: Debug.  Remove this. 
    885             # We assume $driver->next() returns defined data. 
    886             foreach my $resource (keys %{$driver->next()->{resources}}) { 
    887                 $LOG->info($driverName . " - Driving To Resource: " . $resource); 
    888                 $lastResource = $resource; 
    889             } 
    890  
    891             # Drive the driver for one step. 
    892             # If the operation fails, then an exception will be generated. 
    893             $driver->drive(); 
    894    
    895             # Perform an integrity check, if needed. 
    896             if (defined($integrity)) { 
    897                 # For now, we update a scalar called 'is_compromised' within 
    898                 # the $data->{$driverName}->{'status'} sub-hashtable. 
    899                 $LOG->info($driverName . " - Performing Integrity Checks."); 
    900                 $changes = $integrity->check(); 
    901                 if (scalar(@{$changes->{os_processes}})) {  
    902                     $LOG->warn($driverName . " - Integrity Check: FAILED"); 
    903                     $isCompromised = 1; 
    904                     $changes->{'last_resource'} = $lastResource; 
    905          
    906                     # Release our copy of the integrity object, but do not destroy  
    907                     # any internal references. 
    908                     $integrity = undef; 
    909  
    910                     # Exit the while block. 
    911                     last; 
    912  
    913                 } else { 
    914                     $LOG->info($driverName . " - Integrity Check: PASSED"); 
    915                 } 
    916             } 
    917  
    918             # Acquire lock on stored driver state. 
    919             $data = _lock(); 
    920                      
    921             # Check for any additional external driver updates. 
    922             $driver = _update($driver); 
    923  
    924             # Check to see if our driver's targets have changed. 
    925             $driverTargetsChanged = not(Compare($data->{$driverName}->{'next'}->{'targets'}, $driver->next()->{'targets'})); 
    926             # XXX: Delete this, eventually. 
    927             if ($driverTargetsChanged) { 
    928                 $LOG->info($driverName . " - Driver targets have changed."); 
    929                 #$Data::Dumper::Terse = 0; 
    930                 #$Data::Dumper::Indent = 1; 
    931                 #print "Current: " . Dumper($data->{$driverName}->{'next'}->{'targets'}) . "\n"; 
    932                 #print "Next: " . Dumper($driver->next()->{'targets'}) . "\n"; 
    933             } 
    934  
    935             # Copy object data to shared memory. 
    936             $data->{$driverName}->{'next'} = $driver->next(); 
    937             $data->{$driverName}->{'status'} = $driver->status(); 
    938             $data->{$driverName}->{'status'}->{'is_compromised'} = $isCompromised; 
    939             $data->{$driverName}->{'status'}->{'is_running'} = 1; 
    940             $data->{$driverName}->{'state'} = $driver; 
    941  
    942             # Release lock on stored driver state. 
    943             _unlock($data); 
    944         } 
    945          
    946         # XXX: This code may come in handy again, if we decide to keep the 
    947         # old-style integrity checks. 
    948         # Perform an integrity check, if needed. 
    949         # if (defined($integrity)) { 
    950         #     # For now, we update a scalar called 'is_compromised' within 
    951         #     # the $data->{$driverName}->{'status'} sub-hashtable. 
    952         #     $LOG->info($driverName . " - Performing Integrity Checks."); 
    953         #     $changes = $integrity->check(); 
    954         #     if (scalar(@{$changes->{os_processes}})) {  
    955         #         $LOG->warn($driverName . " - Integrity Check: FAILED"); 
    956         #         $isCompromised = 1; 
    957         #         $changes->{'last_resource'} = $lastResource; 
    958         #     } else { 
    959         #         $LOG->info($driverName . " - Integrity Check: PASSED"); 
    960         #     } 
    961         # } 
    962  
    963         # Release our copy of the integrity object, but do not destroy  
    964         # any internal references. 
    965         $integrity = undef; 
    966  
    967         # Update driver state one last time, before exiting. 
    968         # Acquire lock on stored driver state. 
    969         $data = _lock(); 
    970                      
    971         # Check for any additional external driver updates. 
    972         $driver = _update($driver); 
    973  
    974         # Copy object data to shared memory. 
    975         $data->{$driverName}->{'next'} = $driver->next(); 
    976         $data->{$driverName}->{'status'} = $driver->status(); 
    977         $data->{$driverName}->{'status'}->{'is_compromised'} = $isCompromised; 
    978         $data->{$driverName}->{'status'}->{'fingerprint'} = $changes; 
    979         $data->{$driverName}->{'status'}->{'is_running'} = 0; 
    980         $data->{$driverName}->{'state'} = $driver; 
    981   
    982         # Release lock on stored driver state. 
    983         _unlock($data); 
    984     }; 
    985      
    986     ################################### 
    987     ### Driver Cleanup Phase        ### 
    988     ################################### 
    989             
    990     # Check to see if any errors occurred within the thread. 
    991     # Queue any faults found, to transmit back to the next SOAP 
    992     # caller.  
    993     if ($@) { 
    994         # Release any pending locks, to avoid deadlocks. 
    995         _unlock(); 
    996  
    997         # TODO: Do proper fault queuing. 
    998         $LOG->error($driverName . " - FAULT: " . $@); 
    999     } 
    1000  
    1001     # XXX: Debugging, remove eventually.  
    1002     print $driverName . " - About to return out of child thread.\n"; 
    1003     if (!threads->is_detached()) { 
    1004         threads->detach(); 
    1005     } 
    1006     threads->exit(); 
    1007 } 
    1008  
    1009 # XXX: Document this. 
    1010 # Should be something like: 
    1011 #  updateState( 
    1012 #    IE => { 
    1013 #       links  => [ url1, url2, ... , ], 
    1014 #       params => { 
    1015 #           timeout => 5, 
    1016 #           blah    => "testing", 
    1017 #       }, 
    1018 #    }, 
    1019 #  ) 
    1020 # TODO: When updateState() hashtable data is sent across SOAP, 
    1021 # we get the warning message: 
    1022 #  
    1023 # Cannot encode 'links_to_visit' element as 'hash'. 
    1024 # Will be encoded as 'map' instead. 
    1025 # 
    1026 # Check to make sure this issue is not critical. 
    1027 # 
    1028 # We must base64 encode the data, since SOAP doesn't like URLs 
    1029 # that contain amperstands. 
    1030 # XXX: DELETE 
    1031 sub updateState { 
    1032  
    1033     # Extract arguments. 
    1034     my ($class, $arg) = @_; 
    1035     my %args = (); 
    1036  
    1037     # Decode serialized hash. 
    1038     if (defined($arg)) { 
    1039         %args = %{thaw(decode_base64($arg))}; 
    1040     } 
    1041  
    1042     my $argsExist = scalar(%args); 
    1043  
    1044     # Temporary variable, used to hold thawed driver data. 
    1045     my $data = undef; 
    1046  
    1047     # Temporary variable, used to hold thread IDs. 
    1048     my $tid = undef; 
    1049  
    1050     # Temporary variable, used to hold retrieved driver state. 
    1051     my $driver = undef; 
    1052  
    1053     # Temporary variable, used to hold thread objects. 
    1054     my $thread = undef; 
    1055  
    1056     # Figure out which driver to use. 
    1057     for my $driverName (@{$ALLOWED_DRIVERS}) { 
    1058    
    1059         # If the corresponding key within the argument 
    1060         # hash does not exist or is not defined, then 
    1061         # go ahead and skip to the next   
    1062         if (!($argsExist &&  
    1063               exists($args{$driverName}) && 
    1064               defined($args{$driverName}))) { 
    1065             next; 
    1066         } 
    1067  
    1068         # Enqueue the updated state information. 
    1069         # If this call fails, an exception is thrown or the process 
    1070         # remains locked.  If the process locks, then external 
    1071         # detection is used to catch for these types of failures. 
    1072         $driverUpdateQueues{$driverName}->enqueue(nfreeze($args{$driverName})); 
    1073  
    1074         # Acquire data lock. 
    1075         $data = _lock(); 
    1076  
    1077         # Sanity check: See if the run() thread is already running. 
    1078         $tid = $data->{$driverName}->{'thread_id'}; 
    1079         if (defined($tid) && 
    1080             defined($thread = threads->object($tid)) && 
    1081             $thread->is_running()) { 
    1082  
    1083             # The run() thread is active, so we assume that the run() thread will actually 
    1084             # merge these updates into the shared driver state. 
    1085  
    1086             # Release data lock. 
    1087             _unlock(); 
    1088  
    1089         } else { 
    1090  
    1091             # If we've gotten this far, then the run() thread is no longer active, 
    1092             # which means that we have to manually update the driver state 
    1093             # information. 
    1094  
    1095             # Initialize the driver object.  
    1096             # Figure out which $driver object to use... 
    1097             my $driverClass = $driverName; 
    1098  
    1099             if (!defined($data->{$driverName}->{'state'})) { 
    1100      
    1101                 # If the existing driver state is undefined, then 
    1102                 # create a new state object. 
    1103                 $driver = $driverClass->new(); 
    1104  
    1105             } else { 
    1106                 # Else the driver state object is already defined, 
    1107                 # so go ahead and reuse it. 
    1108                 $driver = $driverClass->new( 
    1109                     %{$data->{$driverName}->{'state'}},  
    1110                 ); 
    1111             } 
    1112  
    1113             # Once we have the correct driver state (either newly initialized or 
    1114             # preinitialized from a prior run() thread), we need to update this  
    1115             # state with our new information. 
    1116             $driver = _update($driver); 
    1117  
    1118             # Copy object data to shared memory. 
    1119             $data->{$driverName}->{'next'} = $driver->next(); 
    1120             $data->{$driverName}->{'status'} = $driver->status(); 
    1121             # XXX: This may not be ideal, as a previous compromised status indicator 
    1122             # would get overwritten, during the next updateState() call. 
    1123             $data->{$driverName}->{'status'}->{'is_compromised'} = 0; 
    1124             $data->{$driverName}->{'status'}->{'is_running'} = 0; 
    1125             $data->{$driverName}->{'state'} = $driver; 
    1126  
    1127             # Release data lock. 
    1128             _unlock($data); 
    1129         } 
    1130     } 
    1131 } 
    1132  
    1133 # XXX: Document this. 
    1134 # XXX: DELETE 
    1135 sub getState { 
    1136     my $ret  = undef; 
    1137     _lock(); 
    1138  
    1139     # Sanity check. 
    1140     if (defined($driverData)) { 
    1141  
    1142         # We're only interested in driver state information 
    1143         # (and no other status information).  Thus, we prune the 
    1144         # hashtable, before transmitting. 
    1145         my $data = thaw($driverData); 
    1146         my $driverName = undef; 
    1147         my @driverNames = keys %{$data}; 
    1148  
    1149         foreach $driverName (@driverNames) { 
    1150             $data->{$driverName} = $data->{$driverName}->{'state'}; 
    1151         } 
    1152         $ret = encode_base64(nfreeze($data)); 
    1153     } 
    1154     _unlock(); 
    1155     return $ret; 
    1156 } 
    1157  
    1158 # XXX: DELETE 
    1159 # XXX: Document this. 
    1160 sub getStatus { 
    1161     my $ret = undef; 
    1162     _lock(); 
    1163     if (defined($driverData)) { 
    1164         $ret = encode_base64($driverData); 
    1165     } 
    1166     _unlock(); 
    1167     return $ret; 
    1168 } 
    1169  
    1170 # XXX: DELETE 
    1171 # XXX: Document this. 
    1172 # XXX: Do we really need this? 
    1173 sub shutdown { 
    1174  
    1175     print "Shutting down...\n"; 
    1176  
    1177     # Shutdown in 5 seconds after returning. 
    1178     my $thread = async { 
    1179         threads->yield(); 
    1180         sleep(5); 
    1181         exit; 
    1182     }; 
    1183  
    1184     # Return true. 
    1185     return 1; 
    1186 } 
    1187  
    1188 # XXX: DELETE 
    1189 # XXX: Document this. 
    1190 # TODO: Make this more robust. 
    1191 sub killProcess { 
    1192  
    1193     # Extract arguments. 
    1194     my ($class, $processName) = @_; 
    1195  
    1196     # Sanity check. 
    1197     unless (defined($processName)) { 
    1198         return 0; 
    1199     } 
    1200  
    1201     # TODO: Need unit tests. 
    1202     require Win32::Process; 
    1203     require Win32::Process::Info; 
    1204  
    1205     # Create a new process inspector. 
    1206     my $inspector = Win32::Process::Info->new(); 
    1207     my @procs = $inspector->GetProcInfo(); 
    1208  
    1209     foreach my $proc (@procs) { 
    1210         if ($proc->{Name} eq $processName) { 
    1211             # TODO: Should this statement be in here? 
    1212             $LOG->warn("Killing Process ID: " . $proc->{ProcessId}); 
    1213             Carp::carp "Killing Process ID: " . $proc->{ProcessId} . "\n"; 
    1214             Win32::Process::KillProcess($proc->{ProcessId}, 0); 
    1215         } 
    1216     } 
    1217  
    1218     return 1; 
    1219 } 
    1220  
    1221567####################################################################### 
    1222568 
     
    1232578 
    1233579# XXX: Fill this in. 
     580# XXX: If, at any time, the Manager's SOAP connection to the Agent 
     581is disrupted during a drive() operation, then the Manager should assume 
     582that the VM has been compromised and proceed to handle the VM as such. 
    1234583 
    1235584=head1 SEE ALSO