Changeset 364

Show
Ignore:
Timestamp:
05/25/07 16:16:50 (1 year ago)
Author:
kindlund
Message:

Rearchitecture design.

Files:

Legend:

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

    r363 r364  
    726726        _unlock($data); 
    727727 
    728         # TODO: Clean up this comment block. 
    729         # This function should do the following: 
    730         # - Initialize all drivers with starting state. 
    731         # - "Drive" each driver, one-by-one. 
    732         # - Collect any integrity violations found, with offending 
    733         #   state information. 
    734         # 
    735         # Notes: 
    736         # This function will eventually sit in a sub-thread, allowing the parent 
    737         # thread to return without any delay.  It is expected that the Manager 
    738         # would then subsequently call a getStatus() operation, in order to 
    739         # then poll for any new violations found. 
    740         # 
    741         # TODO: We need to create a fault reporting mechanism, in order 
    742         # to properly deal with exceptions/faults that occur within this 
    743         # thread. 
    744         $thread = async { 
    745             threads->yield(); 
    746  
    747             # Trap all faults that may occur from these asynchronous operations. 
    748             eval { 
    749  
    750                 ################################### 
    751                 ### Driver Initialization Phase ### 
    752                 ################################### 
    753  
    754                 # Initially set local integrity object to undef. 
    755                 my $integrity = undef; 
    756                  
    757                 # Initially set all driver objects to undef.  
    758                 my $driver = undef; 
    759      
    760                 # Acquire lock on stored driver state. 
    761                 $data = _lock(); 
    762  
    763                 if ($PERFORM_INTEGRITY_CHECKS) { 
    764                     # XXX: WARNING - The $integrityState object data is NOT thread-safe 
    765                     # (since it relies on external data stored on the file system). 
    766                     # As such, do NOT try to call integrity checks on multiple, simultaneous 
    767                     # asynchronous threaded drivers. 
    768                     $integrity = thaw($integrityState); 
    769                     # Perform initial integrity baseline check. 
    770                     #print "Initializing Integrity Check...\n"; 
    771                     # TODO: Initialize Integrity Checks 
    772                     #$integrity = HoneyClient::Agent::Integrity->new(); 
    773                 } 
    774  
    775                 # Now, initialize each driver object.  
    776                 # Figure out which $driver object to use... 
    777                 my $driverClass = 'HoneyClient::Agent::Driver::Browser::' . $driverName; 
    778                  
    779                 if (!defined($data->{$driverName}->{'state'})) { 
    780      
    781                     # If the driver state is undefined, then 
    782                     # create a new state object. 
    783                     $driver = $driverClass->new(); 
    784  
    785                 } else { 
    786                     # Then the driver state object is already defined, 
    787                     # so go ahead and reuse it. 
    788                     $driver = $driverClass->new( 
    789                         %{$data->{$driverName}->{'state'}},  
    790                     ); 
    791                 } 
    792  
    793                 # Next, we make sure we have no updates, before we update 
    794                 # the corresponding shared memory version. 
    795                 $driver = _update($driver); 
    796  
    797                 # Once we've initialized the object, be sure to update 
    798                 # the corresponding shared memory version.  We do this 
    799                 # one time before the loop starts, in case we end up 
    800                 # finishing before we drove anywhere. 
    801                  
    802                 # Copy object data to shared memory. 
    803                 $data->{$driverName}->{'next'} = $driver->next(); 
    804                 $data->{$driverName}->{'status'} = $driver->status(); 
    805                 $data->{$driverName}->{'status'}->{'is_compromised'} = 0; 
    806                 $data->{$driverName}->{'status'}->{'is_running'} = 1; 
    807                 $data->{$driverName}->{'state'} = $driver; 
    808  
    809 # XXX: Check to see if this is okay. 
    810 #                if ($driver->isFinished()) { 
    811 #                    # Thread is about to finish, set the ID back to undef. 
    812 #                    # This looks ugly, but setting it this early avoids the 
    813 #                    # potential race condition of when the run() thread is finished 
    814 #                    # and when updateState() checks for $driverData->{$driverName}->{'thread_id'} 
    815 #                    # to be set to undef. 
    816 #                    $data->{$driverName}->{'thread_id'} = undef; 
    817 #                } 
    818  
    819                 # Release lock on stored driver state. 
    820                 _unlock($data); 
    821                  
    822                 ################################### 
    823                 ### Driver Running Phase        ### 
    824                 ################################### 
    825  
    826                 # Boolean to indicate that the driver is about to transition 
    827                 # to a new set of targets upon the next drive() operation. 
    828                 my $driverTargetsChanged = 0; 
    829  
    830                 while (!$driver->isFinished() && !$driverTargetsChanged) { 
    831                     # XXX: Debug.  Remove this. 
    832                     # We assume $driver->next() returns defined data. 
    833                     foreach my $resource (keys %{$driver->next()->{resources}}) { 
    834                         print "Using Resource: " . $resource . "\n"; 
    835                     } 
    836  
    837                     # Drive the driver for one step. 
    838                     # If the operation fails, then an exception will be generated. 
    839                     $driver->drive(); 
    840     
    841                     # Acquire lock on stored driver state. 
    842                     $data = _lock(); 
    843                      
    844                     # Check for any additional external driver updates. 
    845                     $driver = _update($driver); 
    846  
    847                     # Check to see if our driver's targets have changed. 
    848                     $driverTargetsChanged = not(Compare($data->{$driverName}->{'next'}->{'targets'}, $driver->next()->{'targets'})); 
    849                     # XXX: Delete this, eventually. 
    850                     if ($driverTargetsChanged) { 
    851                         print "Driver targets have changed.\n"; 
    852                         #$Data::Dumper::Terse = 0; 
    853                         #$Data::Dumper::Indent = 1; 
    854                         #print "Current: " . Dumper($data->{$driverName}->{'next'}->{'targets'}) . "\n"; 
    855                         #print "Next: " . Dumper($driver->next()->{'targets'}) . "\n"; 
    856                     } 
    857  
    858                     # Copy object data to shared memory. 
    859                     $data->{$driverName}->{'next'} = $driver->next(); 
    860                     $data->{$driverName}->{'status'} = $driver->status(); 
    861                     $data->{$driverName}->{'status'}->{'is_compromised'} = 0; 
    862                     $data->{$driverName}->{'status'}->{'is_running'} = 1; 
    863                     $data->{$driverName}->{'state'} = $driver; 
    864  
    865                     # Release lock on stored driver state. 
    866                     _unlock($data); 
    867                 } 
    868                  
    869                 # TODO: Perform Integrity Check 
    870                 my $isCompromised = 0; 
    871                 if (defined($integrity)) { 
    872                     # For now, we update a scalar called 'is_compromised' within 
    873                     # the $data->{$driverName}->{'status'} sub-hashtable. 
    874                     print "Performing Integrity Checks...\n"; 
    875                     my $changes = $integrity->check(); 
    876                     if (scalar(@{$changes->{registry}}) ||  
    877                         scalar(@{$changes->{filesystem}})) { 
    878                         print "Integrity Check: FAILED\n"; 
    879                         $isCompromised = 1; 
    880                     } else { 
    881                         print "Integrity Check: PASSED\n"; 
    882                     } 
    883                 } 
    884                 # XXX: Check to make sure this doesn't destroy the integrity 
    885                 # object prematurely. 
    886                 # DESTROY this reference, but don't kill any temporary files created. 
    887                 $integrity = undef; 
    888  
    889                 # Update driver state one last time, before exiting. 
    890                  
    891                 # Acquire lock on stored driver state. 
    892                 $data = _lock(); 
    893                      
    894                 # Check for any additional external driver updates. 
    895                 $driver = _update($driver); 
    896  
    897                 # Copy object data to shared memory. 
    898                 $data->{$driverName}->{'next'} = $driver->next(); 
    899                 $data->{$driverName}->{'status'} = $driver->status(); 
    900                 $data->{$driverName}->{'status'}->{'is_compromised'} = $isCompromised; 
    901                 $data->{$driverName}->{'status'}->{'is_running'} = 0; 
    902                 $data->{$driverName}->{'state'} = $driver; 
    903   
    904                 # Thread is about to finish, set the ID back to undef. 
    905 # XXX: Check to see if this is okay. 
    906 #                $data->{$driverName}->{'thread_id'} = undef; 
    907  
    908                 # Release lock on stored driver state. 
    909                 _unlock($data); 
    910  
    911                 # XXX: Debugging, remove eventually.  
    912                 print "Exiting run() thread.\n"; 
    913                 #print Dumper($driver); 
    914                 # Verbose debugging: 
    915                 #print Dumper($driver->status()); 
    916                 # Short-hand debugging: 
    917                 #my $status = $driver->status(); 
    918                 #print "R(" . $status->{relative_links_remaining} . ") | [ " . 
    919                 #      "V(" . $status->{links_remaining} . ") + ". 
    920                 #      "P(" . $status->{links_processed} . ") = " . 
    921                 #      "T(" . $status->{links_total} . ") ] " . 
    922                 #      "| (" . $status->{percent_complete} . ")\n"; 
    923             }; 
    924      
    925             ################################### 
    926             ### Driver Cleanup Phase        ### 
    927             ################################### 
    928             
    929             # Check to see if any errors occurred within the thread. 
    930             # Queue any faults found, to transmit back to the next SOAP 
    931             # caller.  
    932             if ($@) { 
    933                 # Release any pending locks, to avoid deadlocks. 
    934                 _unlock(); 
    935  
    936                 # Acquire lock on stored driver state. 
    937                 $data = _lock(); 
    938                   
    939                 # Make sure we update our state to reflect ourself dying. 
    940 # XXX: Check to see if this is okay. 
    941 #                $data->{$driverName}->{'thread_id'} = undef; 
    942  
    943                 # Release lock on stored driver state. 
    944                 _unlock($data); 
    945      
    946                 # TODO: Do proper fault queuing. 
    947                 print "FAULT: " . $@ . "\n"; 
    948             } 
    949  
    950             # This threads->detach() call needs to be at the end of the 
    951             # thread code, because by calling this, we signal that the 
    952             # child thread is no longer running and thus the 
    953             # thread->is_running() would return false. 
    954             #threads->detach(); 
    955             # XXX: Debugging, remove eventually.  
    956             print "About to return out of child thread.\n"; 
    957             #return; 
    958         }; 
     728        $thread = threads->create(\&childThread, $driverName); 
    959729             
    960730        # Acquire data lock. 
     
    973743            #$data->{$driverName}->{'thread_id'} = undef; 
    974744        } 
    975 # XXX: Check to see if this works okay. 
    976         $thread->detach(); 
    977745 
    978746        # Release data lock. 
    979747        _unlock($data); 
     748 
     749# XXX: Check to see if this works okay. 
     750#        $thread->join(); 
    980751    } 
    981752 
     
    986757    # return true. 
    987758    return 1; 
     759} 
     760 
     761# TODO: Clean up this comment block. 
     762# This function should do the following: 
     763# - Initialize all drivers with starting state. 
     764# - "Drive" each driver, one-by-one. 
     765# - Collect any integrity violations found, with offending 
     766#   state information. 
     767# 
     768# Notes: 
     769# This function will eventually sit in a sub-thread, allowing the parent 
     770# thread to return without any delay.  It is expected that the Manager 
     771# would then subsequently call a getStatus() operation, in order to 
     772# then poll for any new violations found. 
     773# 
     774# TODO: We need to create a fault reporting mechanism, in order 
     775# to properly deal with exceptions/faults that occur within this 
     776# thread. 
     777sub childThread { 
     778 
     779    # Extract arguments. 
     780    my $driverName = shift; 
     781 
     782# XXX: Check if we need this. 
     783#    threads->yield(); 
     784 
     785    # Trap all faults that may occur from these asynchronous operations. 
     786    eval { 
     787 
     788        ################################### 
     789        ### Driver Initialization Phase ### 
     790        ################################### 
     791 
     792        # Initially set local integrity object to undef. 
     793        my $integrity = undef; 
     794                 
     795        # Initially set all driver objects to undef.  
     796        my $driver = undef; 
     797     
     798        # Acquire lock on stored driver state. 
     799        $data = _lock(); 
     800 
     801        if ($PERFORM_INTEGRITY_CHECKS) { 
     802            # XXX: WARNING - The $integrityState object data is NOT thread-safe 
     803            # (since it relies on external data stored on the file system). 
     804            # As such, do NOT try to call integrity checks on multiple, simultaneous 
     805            # asynchronous threaded drivers. 
     806            $integrity = thaw($integrityState); 
     807            # Perform initial integrity baseline check. 
     808            #print "Initializing Integrity Check...\n"; 
     809            # TODO: Initialize Integrity Checks 
     810            #$integrity = HoneyClient::Agent::Integrity->new(); 
     811        } 
     812 
     813        # Now, initialize each driver object.  
     814        # Figure out which $driver object to use... 
     815        my $driverClass = 'HoneyClient::Agent::Driver::Browser::' . $driverName; 
     816                 
     817        if (!defined($data->{$driverName}->{'state'})) { 
     818     
     819            # If the driver state is undefined, then 
     820            # create a new state object. 
     821            $driver = $driverClass->new(); 
     822 
     823        } else { 
     824            # Then the driver state object is already defined, 
     825            # so go ahead and reuse it. 
     826            $driver = $driverClass->new( 
     827                        %{$data->{$driverName}->{'state'}},  
     828            ); 
     829        } 
     830 
     831        # Next, we make sure we have no updates, before we update 
     832        # the corresponding shared memory version. 
     833        $driver = _update($driver); 
     834 
     835        # Once we've initialized the object, be sure to update 
     836        # the corresponding shared memory version.  We do this 
     837        # one time before the loop starts, in case we end up 
     838        # finishing before we drove anywhere. 
     839                 
     840        # Copy object data to shared memory. 
     841        $data->{$driverName}->{'next'} = $driver->next(); 
     842        $data->{$driverName}->{'status'} = $driver->status(); 
     843        $data->{$driverName}->{'status'}->{'is_compromised'} = 0; 
     844        $data->{$driverName}->{'status'}->{'is_running'} = 1; 
     845        $data->{$driverName}->{'state'} = $driver; 
     846 
     847# XXX: Check to see if this is okay. 
     848#       if ($driver->isFinished()) { 
     849#           # Thread is about to finish, set the ID back to undef. 
     850#           # This looks ugly, but setting it this early avoids the 
     851#           # potential race condition of when the run() thread is finished 
     852#           # and when updateState() checks for $driverData->{$driverName}->{'thread_id'} 
     853#           # to be set to undef. 
     854#           $data->{$driverName}->{'thread_id'} = undef; 
     855#       } 
     856 
     857        # Release lock on stored driver state. 
     858        _unlock($data); 
     859                 
     860        ################################### 
     861        ### Driver Running Phase        ### 
     862        ################################### 
     863 
     864        # Boolean to indicate that the driver is about to transition 
     865        # to a new set of targets upon the next drive() operation. 
     866        my $driverTargetsChanged = 0; 
     867 
     868        while (!$driver->isFinished() && !$driverTargetsChanged) { 
     869            # XXX: Debug.  Remove this. 
     870            # We assume $driver->next() returns defined data. 
     871            foreach my $resource (keys %{$driver->next()->{resources}}) { 
     872                print "Using Resource: " . $resource . "\n"; 
     873            } 
     874 
     875            # Drive the driver for one step. 
     876            # If the operation fails, then an exception will be generated. 
     877            $driver->drive(); 
     878    
     879            # Acquire lock on stored driver state. 
     880            $data = _lock(); 
     881                     
     882            # Check for any additional external driver updates. 
     883            $driver = _update($driver); 
     884 
     885            # Check to see if our driver's targets have changed. 
     886            $driverTargetsChanged = not(Compare($data->{$driverName}->{'next'}->{'targets'}, $driver->next()->{'targets'})); 
     887            # XXX: Delete this, eventually. 
     888            if ($driverTargetsChanged) { 
     889                print "Driver targets have changed.\n"; 
     890                #$Data::Dumper::Terse = 0; 
     891                #$Data::Dumper::Indent = 1; 
     892                #print "Current: " . Dumper($data->{$driverName}->{'next'}->{'targets'}) . "\n"; 
     893                #print "Next: " . Dumper($driver->next()->{'targets'}) . "\n"; 
     894            } 
     895 
     896            # Copy object data to shared memory. 
     897            $data->{$driverName}->{'next'} = $driver->next(); 
     898            $data->{$driverName}->{'status'} = $driver->status(); 
     899            $data->{$driverName}->{'status'}->{'is_compromised'} = 0; 
     900            $data->{$driverName}->{'status'}->{'is_running'} = 1; 
     901            $data->{$driverName}->{'state'} = $driver; 
     902 
     903            # Release lock on stored driver state. 
     904            _unlock($data); 
     905        } 
     906                 
     907        # TODO: Perform Integrity Check 
     908        my $isCompromised = 0; 
     909        if (defined($integrity)) { 
     910            # For now, we update a scalar called 'is_compromised' within 
     911            # the $data->{$driverName}->{'status'} sub-hashtable. 
     912            print "Performing Integrity Checks...\n"; 
     913            my $changes = $integrity->check(); 
     914            if (scalar(@{$changes->{registry}}) ||  
     915                scalar(@{$changes->{filesystem}})) { 
     916                print "Integrity Check: FAILED\n"; 
     917                $isCompromised = 1; 
     918            } else { 
     919                print "Integrity Check: PASSED\n"; 
     920            } 
     921        } 
     922        # XXX: Check to make sure this doesn't destroy the integrity 
     923        # object prematurely. 
     924        # DESTROY this reference, but don't kill any temporary files created. 
     925        $integrity = undef; 
     926 
     927        # Update driver state one last time, before exiting. 
     928                 
     929        # Acquire lock on stored driver state. 
     930        $data = _lock(); 
     931                     
     932        # Check for any additional external driver updates. 
     933        $driver = _update($driver); 
     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'} = 0; 
     940        $data->{$driverName}->{'state'} = $driver; 
     941  
     942        # Thread is about to finish, set the ID back to undef. 
     943# XXX: Check to see if this is okay. 
     944#       $data->{$driverName}->{'thread_id'} = undef; 
     945 
     946        # Release lock on stored driver state. 
     947        _unlock($data); 
     948 
     949        # XXX: Debugging, remove eventually.  
     950        print "Exiting run() thread.\n"; 
     951        #print Dumper($driver); 
     952        # Verbose debugging: 
     953        #print Dumper($driver->status()); 
     954        # Short-hand debugging: 
     955        #my $status = $driver->status(); 
     956        #print "R(" . $status->{relative_links_remaining} . ") | [ " . 
     957        #      "V(" . $status->{links_remaining} . ") + ". 
     958        #      "P(" . $status->{links_processed} . ") = " . 
     959        #      "T(" . $status->{links_total} . ") ] " . 
     960        #      "| (" . $status->{percent_complete} . ")\n"; 
     961    }; 
     962     
     963    ################################### 
     964    ### Driver Cleanup Phase        ### 
     965    ################################### 
     966            
     967    # Check to see if any errors occurred within the thread. 
     968    # Queue any faults found, to transmit back to the next SOAP 
     969    # caller.  
     970    if ($@) { 
     971        # Release any pending locks, to avoid deadlocks. 
     972        _unlock(); 
     973 
     974        # Acquire lock on stored driver state. 
     975        $data = _lock(); 
     976                  
     977        # Make sure we update our state to reflect ourself dying. 
     978# XXX: Check to see if this is okay. 
     979#       $data->{$driverName}->{'thread_id'} = undef; 
     980 
     981        # Release lock on stored driver state. 
     982        _unlock($data); 
     983     
     984        # TODO: Do proper fault queuing. 
     985        print "FAULT: " . $@ . "\n"; 
     986    } 
     987 
     988    # This threads->detach() call needs to be at the end of the 
     989    # thread code, because by calling this, we signal that the 
     990    # child thread is no longer running and thus the 
     991    # thread->is_running() would return false. 
     992    #threads->detach(); 
     993    # XXX: Debugging, remove eventually.  
     994    print "About to return out of child thread.\n"; 
     995    #return; 
    988996} 
    989997