[Oval-commits] r65 - trunk/Interpreters/src/probes/linux

Pavel Vinogradov blaze-guest at alioth.debian.org
Tue Jul 10 17:37:50 UTC 2007


Author: blaze-guest
Date: 2007-07-10 17:37:50 +0000 (Tue, 10 Jul 2007)
New Revision: 65

Added:
   trunk/Interpreters/src/probes/linux/DPKGInfoProbe.cpp
Modified:
   trunk/Interpreters/src/probes/linux/DPKGInfoProbe.h
Log:
Implement DPKGInfoProbe class

Added: trunk/Interpreters/src/probes/linux/DPKGInfoProbe.cpp
===================================================================
--- trunk/Interpreters/src/probes/linux/DPKGInfoProbe.cpp	                        (rev 0)
+++ trunk/Interpreters/src/probes/linux/DPKGInfoProbe.cpp	2007-07-10 17:37:50 UTC (rev 65)
@@ -0,0 +1,373 @@
+//
+// $Id: DPKGInfoProbe.cpp 4194 2007-07-10 15:33:35Z blaze $
+//
+//****************************************************************************************//
+// Copyright (c) 2002-2007, The MITRE Corporation
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without modification, are
+// permitted provided that the following conditions are met:
+//
+//     * Redistributions of source code must retain the above copyright notice, this list
+//       of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above copyright notice, this 
+//       list of conditions and the following disclaimer in the documentation and/or other
+//       materials provided with the distribution.
+//     * Neither the name of The MITRE Corporation nor the names of its contributors may be
+//       used to endorse or promote products derived from this software without specific 
+//       prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 
+// SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+// OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+// TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+// EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+//****************************************************************************************//
+
+#include "DPKGInfoProbe.h"
+
+//****************************************************************************************//
+//				DPKGInfoProbe Class					  //	
+//****************************************************************************************//
+DPKGInfoProbe *DPKGInfoProbe::instance = NULL;
+
+DPKGInfoProbe::DPKGInfoProbe() {
+	this->StatusFile = "/var/lib/dpkg/status";
+}
+
+DPKGInfoProbe::~DPKGInfoProbe() {
+
+}
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~  Public Members  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
+AbsProbe* DPKGInfoProbe::Instance() {
+
+	// Use lazy initialization
+	if(instance == NULL) 
+		instance = new DPKGInfoProbe();
+
+	return instance;	
+}
+
+//bad
+ItemVector* DPKGInfoProbe::CollectItems(Object* object) {
+
+	ItemVector *collectedItems = new ItemVector();
+
+	ObjectEntity* name = object->GetElementByName("name");
+
+	// check datatypes - only allow string
+	if(name->GetDatatype() != OvalEnum::DATATYPE_STRING) {
+		throw ProbeException("Error: invalid data type specified on name. Found: " + OvalEnum::DatatypeToString(name->GetDatatype()));
+	}
+
+	// check operation - only allow  equals, not equals and pattern match
+	if(name->GetOperation() != OvalEnum::OPERATION_EQUALS && name->GetOperation() != OvalEnum::OPERATION_PATTERN_MATCH && name->GetOperation() != OvalEnum::OPERATION_NOT_EQUAL) {
+		throw ProbeException("Error: invalid operation specified on name. Found: " + OvalEnum::OperationToString(name->GetOperation()));
+	}
+
+	StringVector* names = this->GetDPKGNames(name);
+	if(names->size() > 0) {
+		StringVector::iterator iterator;
+		for(iterator = names->begin(); iterator != names->end(); iterator++) {		
+			this->GetDPKGInfo((*iterator), collectedItems);
+		}
+	} else {
+
+		if(name->GetOperation() == OvalEnum::OPERATION_EQUALS) {
+
+			if(name->GetVarRef() == NULL) {
+
+				Item* item = this->CreateItem();
+				item->SetStatus(OvalEnum::STATUS_DOES_NOT_EXIST);
+				item->AppendElement(new ItemEntity("name",  name->GetValue(), OvalEnum::DATATYPE_STRING, true, OvalEnum::STATUS_DOES_NOT_EXIST));
+				collectedItems->push_back(item);
+
+			} else {
+
+				VariableValueVector::iterator iterator;
+				for(iterator = name->GetVarRef()->GetValues()->begin(); iterator != name->GetVarRef()->GetValues()->end(); iterator++) {
+
+					Item* item = this->CreateItem();
+					item->SetStatus(OvalEnum::STATUS_DOES_NOT_EXIST);
+					item->AppendElement(new ItemEntity("name",  (*iterator)->GetValue(), OvalEnum::DATATYPE_STRING, true, OvalEnum::STATUS_DOES_NOT_EXIST));
+					collectedItems->push_back(item);
+				}
+			}
+		}
+	}
+	names->clear();
+	delete names;
+
+	return collectedItems;
+}  
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~  Private Members  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
+Item* DPKGInfoProbe::CreateItem() {
+	// -----------------------------------------------------------------------
+	//
+	//  ABSTRACT
+	//
+	//  Return a new Item created for storing file information
+	//
+	// -----------------------------------------------------------------------
+
+	Item* item = new Item(0, 
+						"http://oval.mitre.org/XMLSchema/oval-system-characteristics-5#linux", 
+						"linux-sc", 
+						"http://oval.mitre.org/XMLSchema/oval-system-characteristics-5#linux linux-system-characteristics-schema.xsd", 
+						OvalEnum::STATUS_ERROR, 
+						"dpkginfo_item");
+
+	return item;
+}
+
+StringVector* DPKGInfoProbe::GetDPKGNames(ObjectEntity* name) {
+	// -----------------------------------------------------------------------
+	//
+	//  ABSTRACT
+	//
+	//  Get the set of all rpm names on the system that match the object
+	//
+	// -----------------------------------------------------------------------
+	StringVector* names = NULL;
+
+	// does this name use variables?
+	if(name->GetVarRef() == NULL) {
+		
+		// proceed based on operation
+		if(name->GetOperation() == OvalEnum::OPERATION_EQUALS) {
+			names = new StringVector();
+			// if the name exists add it to the list 
+			if(this->DPKGExists(name->GetValue())) {
+				names->push_back(name->GetValue());
+			}
+
+		} else if(name->GetOperation() == OvalEnum::OPERATION_NOT_EQUAL) {
+			
+			names = this->GetMatchingDPKGNames(name->GetValue(), false);
+
+		} else if(name->GetOperation() == OvalEnum::OPERATION_PATTERN_MATCH) {
+			names = this->GetMatchingDPKGNames(name->GetValue(), true);
+		}		
+
+	} else {
+
+		names = new StringVector();
+
+		// Get all names
+		StringVector allNames;
+
+		if(name->GetOperation() == OvalEnum::OPERATION_EQUALS) {
+			// in the case of equals simply loop through all the 
+			// variable values and add them to the set of all names
+			// if they exist on the system
+			VariableValueVector::iterator iterator;
+			for(iterator = name->GetVarRef()->GetValues()->begin(); iterator != name->GetVarRef()->GetValues()->end(); iterator++) {
+				
+				if(this->DPKGExists((*iterator)->GetValue())) {
+					allNames.push_back((*iterator)->GetValue());
+				}
+			}
+
+		} else {
+            		this->GetMatchingDPKGNames(".*", &allNames);
+		}
+	
+		// loop through all names on the system
+		// only keep names that match operation and value and var check
+		ItemEntity* tmp = this->CreateItemEntity(name);
+		StringVector::iterator it;
+		for(it = allNames.begin(); it != allNames.end(); it++) {
+			tmp->SetValue((*it));
+			
+			if(name->Analyze(tmp) == OvalEnum::RESULT_TRUE) {
+				names->push_back((*it));
+			}
+		}
+	}
+
+	return names;
+}
+
+//bad
+StringVector* DPKGInfoProbe::GetMatchingDPKGNames(string pattern, bool isRegex) {
+	// -----------------------------------------------------------------------
+	//
+	//  ABSTRACT
+	//
+	//  Get the set of all rpm names on the system that match the pattern
+	//
+	// -----------------------------------------------------------------------
+	
+	string installed_dpkg_name;
+	string installed_dpkg_status;
+
+	StringVector* names = new StringVector ();
+
+	FileFd Fd(this->StatusFile, FileFd::ReadOnly);
+	pkgTagFile Tags(&Fd);
+
+	if (_error->PendingError() == true)
+		throw ProbeException("Error: (DPKGInfoProbe) Could not read DPKG status file, which is necessary to read the packages status.");
+   
+	pkgTagSection Section;
+		
+	while (Tags.Step(Section) == true)
+   	{
+		/* Fetch the name, auto-detecting if this is a source file or a package file */
+		installed_dpkg_name = readHeaderString (Section, "Package");
+      		installed_dpkg_status = readHeaderString (Section, "Status");
+		if ( installed_dpkg_status.compare ("install ok installed") == 0 ) 
+		{
+			if (this->IsMatch (pattern, installed_dpkg_name, isRegex))
+				names->push_back (installed_dpkg_name);
+		}
+   	}
+	
+   	if (_error->PendingError() == true)
+   		throw ProbeException("Error: (DPKGInfoProbe) Error while walking DPKG database.");
+
+	return names;
+}
+
+bool DPKGInfoProbe::DPKGExists(string name) {
+	// -----------------------------------------------------------------------
+	//
+	//  ABSTRACT
+	//
+	//  return true if the specifeid deb exists
+	//
+	// -----------------------------------------------------------------------
+	bool exist = false;
+	bool found = false;
+	
+	FileFd Fd(this->StatusFile, FileFd::ReadOnly);
+	pkgTagFile Tags(&Fd);
+
+	if (_error->PendingError() == true) {
+		throw ProbeException("Error: (DPKGInfoProbe) Could not read DPKG status file, which is necessary to read the DPKG database.");
+	}
+   
+	pkgTagSection Section;
+	
+	while (Tags.Step(Section) == true && found == false)
+   	{
+    		/* Fetch the name, auto-detecting if this is a source file or a package file */
+      		string installed_dpkg_name = readHeaderString (Section, "Package");
+      		string installed_dpkg_status = readHeaderString (Section, "Status");
+      		
+      		if (installed_dpkg_name.empty() == true)
+      			throw ProbeException("Error: (DPKGInfoProbe) Error while walking DPKG database.");
+      
+      		if ( installed_dpkg_name.compare (name) == 0 ) 
+      		{
+      			if (installed_dpkg_status.compare ("install ok installed") == 0 ) 
+      			{
+      				exist = true;
+	      		}	
+	      		found = true; 
+      		}
+		}
+	
+   	if (_error->PendingError() == true)
+   		throw ProbeException("Error: (DPKGInfoProbe) Error while walking DPKG database.");
+   	
+   	return exist;
+}
+
+//bad
+void DPKGInfoProbe::GetDPKGInfo(string name, ItemVector* items) {
+  //------------------------------------------------------------------------------------//
+  //
+  //  ABSTRACT
+  //
+  //  Get the data for all packages that have the name that matches dpkg_name.  
+  //
+  //------------------------------------------------------------------------------------//
+
+  /* Get the dpkg_name form the data object. */
+  const char *dpkg_name = name.c_str();
+
+  /* Create a tmp data object reference. */
+  Item *item = NULL;
+
+  /* Epoch, version, release and architecture data for output. */
+  string installed_epoch, installed_version, installed_release,installed_architecture, installed_evr;
+  string installedEpochEvr;
+
+    /* Header object for the installed package. */
+  pkgTagSection section;
+
+  /* Read in the DPKG status files */
+  FileFd Fd(this->StatusFile, FileFd::ReadOnly);
+  pkgTagFile Tags(&Fd);
+
+  if (_error->PendingError() == true) {
+	  throw ProbeException("Error: (DPKGInfoProbe) Could not read DPKG status file, which is necessary to read the DPKG database.");
+  }
+
+  while (Tags.Step(section) == true)
+  {
+	  /* Fetch the name, auto-detecting if this is a source file or a package file */
+	  string installed_dpkg_name = readHeaderString (section, "Package");
+	  string installed_dpkg_status = readHeaderString (section, "Status");
+    		
+	  if ( installed_dpkg_name.compare (dpkg_name) == 0 ) 
+	  {
+		  if (installed_dpkg_status.compare ("install ok installed") == 0 ) 
+		  {
+			  /* epoch is an int_32 -- we'll display a string to handle the None case well. */
+			  /*    char intermediate_string[11];
+			      int_32 epoch = readHeaderInt32(header, RPMTAG_EPOCH);
+			  	string installedEpochEvr;
+			  	if (epoch == -1 ) {
+			        installed_epoch = "(none)";
+			  		installedEpochEvr = "0";
+			  	} else {
+			        snprintf(intermediate_string,11,"%d",epoch);
+			        installed_epoch = intermediate_string;
+			  	  installedEpochEvr = installed_epoch;
+			      }
+			*/
+			  	installed_epoch = "(none)";
+			  	installedEpochEvr = installed_epoch;
+			  /* the remaining arguments are all normal strings */
+			    installed_version = this->readHeaderString(section, "Version");
+			    installed_release = this->readHeaderString(section, "Version");
+			    installed_architecture = this->readHeaderString(section, "Architecture");
+				installed_evr = installedEpochEvr + ":" + installed_version + "-" + installed_release;
+
+			    /* Put the data in a data object. */
+			    item = this->CreateItem();
+			    item->SetStatus(OvalEnum::STATUS_EXISTS);
+				item->AppendElement(new ItemEntity("name",  name, OvalEnum::DATATYPE_STRING, true, OvalEnum::STATUS_EXISTS));
+				item->AppendElement(new ItemEntity("arch",  installed_architecture, OvalEnum::DATATYPE_STRING, false, OvalEnum::STATUS_EXISTS));
+				item->AppendElement(new ItemEntity("epoch",  installed_epoch, OvalEnum::DATATYPE_STRING, false, OvalEnum::STATUS_EXISTS));
+				item->AppendElement(new ItemEntity("release",  installed_release, OvalEnum::DATATYPE_STRING, false, OvalEnum::STATUS_EXISTS));
+				item->AppendElement(new ItemEntity("version",  installed_version, OvalEnum::DATATYPE_STRING, false, OvalEnum::STATUS_EXISTS));
+				item->AppendElement(new ItemEntity("evr",  installed_evr, OvalEnum::DATATYPE_STRING, false, OvalEnum::STATUS_EXISTS));
+
+			    /* add the new item to the vector. */
+			    items->push_back(item);
+		  }
+	  }
+  }
+}
+
+string DPKGInfoProbe::readHeaderString(pkgTagSection Section, char* sectionName) {
+	string value;
+
+	value = Section.FindS(sectionName);
+
+	return (value);
+}

Modified: trunk/Interpreters/src/probes/linux/DPKGInfoProbe.h
===================================================================
--- trunk/Interpreters/src/probes/linux/DPKGInfoProbe.h	2007-07-10 14:11:41 UTC (rev 64)
+++ trunk/Interpreters/src/probes/linux/DPKGInfoProbe.h	2007-07-10 17:37:50 UTC (rev 65)
@@ -37,6 +37,8 @@
 #include <apt-pkg/progress.h> 	//OpTextProgress
 #include <apt-pkg/cachefile.h> 	//pkgCacheFile
 #include <apt-pkg/configuration.h> //_config
+#include <apt-pkg/tagfile.h>	//pkgTagFile, pkgTagSection 
+#include <apt-pkg/error.h> 	//_error
 
 #include <unistd.h>
 #include <sys/types.h>
@@ -64,6 +66,8 @@
 	static AbsProbe* Instance();
 
 private:
+	string StatusFile;
+
 	DPKGInfoProbe();
 
 	/**
@@ -96,7 +100,7 @@
 	*/
 	void GetDPKGInfo(string name, ItemVector* items);
 
-	char *readHeaderString(Header header, int_32 tag_id);
+	string readHeaderString(pkgTagSection section, char* sectionName);
 
 	static DPKGInfoProbe *instance;
 };




More information about the Oval-commits mailing list