// UtilityConfig.cpp // // Copyright (C) 2011, ARM Research Labs, LLC. // See www.armresearch.com for the copyright terms. // // This file implements the common functionality for the configuration // utilities. #include #include #include #include #include #include #include #include #include #include #include #include "UtilityConfig.hpp" using namespace std; ////////////////////////////////////////////////////////////////////////////////////////////////////////// // Configuration. //////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////// // Initialize OS-dependent constants. #ifdef WIN // Windows OS. const std::string UtilityConfig::SampleIgnoreListFile("C:\\SNF\\GBUdbIgnoreList.txt.sample"); const std::string UtilityConfig::RulebaseDownloadCommand("FIX THIS"); const std::string UtilityConfig::RulebaseDownloadStatusFile("FIX THIS"); const std::string ScriptNameKey("FIX THIS"); ///< Text to replace with script name. const std::string SnifferPathKey("FIX THIS"); ///< Text to replace with directory of the rulebase. const std::string UtilityConfig::SampleRulebaseScriptFile("C:\\SNF\\getRulebase.sample"); const std::string UtilityConfig::OperatingSystemType("Windows"); #else // *nix OS. // SCRIPT is replaced with the full path of the script run, // SNIFFER_PATH is replaced with the path of the rulebase. const std::string UtilityConfig::RulebaseDownloadCommand ("(cd SNIFFER_PATH; touch UpdateReady.txt; chown snfuser UpdateReady.txt; su -m snfuser -c SCRIPT)"); const std::string ScriptNameKey("SCRIPT"); ///< Text to replace with script name. const std::string SnifferPathKey("SNIFFER_PATH"); ///< Text to replace with directory of the rulebase. // SNIFFER_PATH is replaced with the path of the rulebase. const std::string UtilityConfig::RulebaseDownloadStatusFile("SNIFFER_PATHgetRulebase.status"); #ifdef DEFAULT_DATA_DIR // *nix, DEFAULT_DATA_DIR is specified on the compile command line. const std::string UtilityConfig::SampleIgnoreListFile(DEFAULT_DATA_DIR "/GBUdbIgnoreList.txt.sample"); #else // Not Windows, and DEFAULT_DATA_DIR is not specified on the compile // command line. In this case, we don't know the path for the sample // ignore list file. #error DEFAULT_DATA_DIR must be defined by -DDEFAULT_DATA_DIR="..." when compiling. #endif #ifdef SBIN_DIR // *nix, SBIN_DIR is specified on the compile command line. const std::string UtilityConfig::SampleRulebaseScriptFile(SBIN_DIR "/getRulebase.sample"); #else // Not Windows, and SBIN_DIR is not specified on the compile // command line. In this case, we don't know the path for the sample // ignore list file. #error SBIN_DIR must be defined by -DSBIN_DIR="..." when compiling. #endif #ifdef SNF_OSTYPE // *nix, SNF_OSTYPE is specified on the compile command line. const std::string UtilityConfig::OperatingSystemType(SNF_OSTYPE); #else // Not Windows, and SNF_OSTYPE is not specified on the compile command // line. In this case, we don't know the operating system. #error SNF_OSTYPE must be defined by -DSNF_OSTYPE="..." when compiling. #endif #endif /// Verbose command-line input. const string VerboseKey("-v"); /// Explain command-line input. const string ExplainKey("-explain"); /// Help command-line input. const string HelpKey("-h"); /// Setup command-line input. const string SetupKey("-setup"); /// Repair command-line input. const string RepairKey("-repair"); /// Start sniffer command-line input. const string StartSnifferKey("-start"); /// Stop sniffer command-line input. const string StopSnifferKey("-stop"); /// Configuration file command-line input. const string ConfigFileKey("-config="); /// License ID command-line input. const string LicenseIdKey("-id="); /// Authentication command-line input. const string AuthenticationKey("-auth="); /// String that indicates a successful rulebase download. // // This string must be in the last line of the getRulebase status // file. Note: The getRulebase status file is created by the // getRulebase script, has the name getRulebase.status, and is in the // same directory as the rulebase files. const string SuccessKey("Success"); const string LicenseSearchString = "LICENSE_ID="; const string AuthSearchString = "AUTHENTICATION="; const string IdentityElementName = "identity"; const string LicenseAttributeName = "licenseid"; const string AuthenticationAttributeName = "authentication"; ////////////////////////////////////////////////////////////////////////////////////////////////////////// // End of configuration. ///////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////// UtilityConfig::UtilityConfig() : LicenseIdIsSpecified(false), AuthenticationIsSpecified(false) { SetExplain(false); SetVerbose(false); SetHelp(false); SetSetupRepair(false); SetStartSniffer(false); SetStopSniffer(false); } void UtilityConfig::CreateDefaultConfigFile(std::string SampleConfigFile) { std::string File = GetConfigFileName(); if (!FileExists(File)) { if (!Explain()) { SaveFile.CreateBackupFile(File); } // Create the config file. Copy(SampleConfigFile, File); } SetMode(File, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); // Set permissions. SetOwnerGroup(File); // Set to sniffer user. } void UtilityConfig::LoadConfig() { if (Verbose()) { cout << "Using configuration file " << GetConfigFileName() << ".\n"; } // Load the data. try { CFGData.initializeFromFile(GetConfigFileName().c_str()); } catch(...) { string Temp; Temp = "Error reading configuration file " + GetConfigFileName(); Temp += "."; throw std::runtime_error(Temp); } if ( (CFGData.paths_workspace_path.length() == 0) || (CFGData.paths_rulebase_path.length() == 0) || (CFGData.paths_log_path.length() == 0) || (CFGData.update_script_call.length() == 0) || (CFGData.node_identity.length() == 0) ) { string Temp; Temp = "The configuration file " + GetConfigFileName(); Temp += " did not have the necessary specification of one or more paths:\n"; Temp += "\n Workspace path: " + CFGData.paths_workspace_path; Temp += "\n Rulebase path: " + CFGData.paths_rulebase_path; Temp += "\n Log path: " + CFGData.paths_log_path; Temp += "\n Update script: " + CFGData.update_script_call; Temp += "\n Identity file: " + CFGData.node_identity; throw std::runtime_error(Temp); } } string UtilityConfig::GetPlatformContents(void) { return CFGData.PlatformElementContents; } string UtilityConfig::GetConfigFileName(void) { return ConfigFileName; } void UtilityConfig::SetConfigFileName(string Name) { ConfigFileName = Name; } string UtilityConfig::GetWorkspacePath(void) { return CFGData.paths_workspace_path; } string UtilityConfig::GetRulebasePath(void) { if (CFGData.paths_rulebase_path.empty()) return ""; // Ensure that there's a trailing "/". if (CFGData.paths_rulebase_path[CFGData.paths_rulebase_path.length() - 1] == '/') return CFGData.paths_rulebase_path; return CFGData.paths_rulebase_path + "/"; } string UtilityConfig::GetLogPath(void) { return CFGData.paths_log_path; } std::string UtilityConfig::GetStatusSecondLogFileName(void) { std::string FileName = CFGData.paths_log_path + CFGData.node_licenseid + ".status.second"; if (CFGData.Status_SecondReport_Append_OnOff) { AppendDatestampToLogFileName(&FileName); } FileName += ".log.xml"; return FileName; } std::string UtilityConfig::GetStatusMinuteLogFileName(void) { std::string FileName = CFGData.paths_log_path + CFGData.node_licenseid + ".status.minute"; if (CFGData.Status_MinuteReport_Append_OnOff) { AppendDatestampToLogFileName(&FileName); } FileName += ".log.xml"; return FileName; } void UtilityConfig::AppendDatestampToLogFileName(std::string *FileBaseName) { char TimestampBuffer[20]; tm *BrokenDownTime; time_t Timestamp; time(&Timestamp); if (CFGData.Logs_Rotation_LocalTime_OnOff) { BrokenDownTime = localtime(&Timestamp); } else { BrokenDownTime = gmtime(&Timestamp); } snprintf(TimestampBuffer, sizeof TimestampBuffer, "%04d%02d%02d", BrokenDownTime->tm_year+1900, BrokenDownTime->tm_mon+1, BrokenDownTime->tm_mday); *FileBaseName += "."; *FileBaseName += TimestampBuffer; } string UtilityConfig::GetIdentityFileName(void) { return CFGData.node_identity; } string UtilityConfig::GetRulebaseScriptName(void) { return CFGData.update_script_call; } string UtilityConfig::GetIgnoreListFileName(void) { return GetWorkspacePath() + "GBUdbIgnoreList.txt"; } string UtilityConfig::GetRulebaseFileName(void) { std::string Name; Name = GetRulebasePath(); Name += LicenseId + ".snf"; return Name; } string UtilityConfig::GetOperatingSystemType(void) { return OperatingSystemType; } void UtilityConfig::LoadInfo(){ if ("OpenBSD" == OperatingSystemType) { PostfixMainCfPath = "/usr/local/etc/postfix/main.cf"; PostfixMasterCfPath = "/usr/local/etc/postfix/master.cf"; SnifferStartScriptDir = "/usr/local/sbin/"; } else if ("FreeBSD" == OperatingSystemType) { PostfixMainCfPath = "/etc/postfix/main.cf"; PostfixMasterCfPath = "/etc/postfix/master.cf"; SnifferStartScriptDir = "/usr/local/etc/rc.d/"; } else if ("Ubuntu" == OperatingSystemType) { PostfixMainCfPath = "/etc/postfix/main.cf"; PostfixMasterCfPath = "/etc/postfix/master.cf"; SnifferStartScriptDir = "/etc/init.d/"; } else if ("RedHat" == OperatingSystemType) { PostfixMainCfPath = "/etc/postfix/main.cf"; PostfixMasterCfPath = "/etc/postfix/master.cf"; SnifferStartScriptDir = "/etc/init.d/"; } else if ("Suse" == OperatingSystemType) { PostfixMainCfPath = "/etc/postfix/main.cf"; PostfixMasterCfPath = "/etc/postfix/master.cf"; SnifferStartScriptDir = "/etc/init.d/"; } else { ostringstream Temp; Temp << "Internal error in UtilityConfig::LoadInfo: Invalid value of OperatingSystemType: " << OperatingSystemType; throw std::runtime_error(Temp.str()); } } void UtilityConfig::LoadCredentials(void) { if(0 < CFGData.node_identity.length()) { // If an identity path was provided ConfigurationData Identity(CFGData.node_identity.c_str()); // then get the data from that file. ConfigurationElement IdentityReader("snf"); // Create an Identity reader and IdentityReader // configure it. .Element("identity") .Attribute("licenseid", CFGData.node_licenseid) .Attribute("authentication", CFGData.node_authentication) .End("identity") .End("snf"); IdentityReader.interpret(Identity); // Then read the data. } } UtilityConfig::StatusCheckMethod UtilityConfig::GetPreferredStatusCheckMethod(void) { if (CFGData.XCI_OnOff) { return StatusCheckXci; } if (CFGData.Status_SecondReport_Log_OnOff) { return StatusCheckSecond; } if (CFGData.Status_MinuteReport_Log_OnOff) { return StatusCheckMinute; } return StatusCheckNotAvailable; } std::string UtilityConfig::GetSnifferStatusReport() { std::string StatusReport; int SleepTime_msec; int TimeoutTime_msec; switch (GetPreferredStatusCheckMethod()) { case StatusCheckXci: StatusReport = GetReportViaXci(); break; case StatusCheckSecond: SleepTime_msec = 1000; TimeoutTime_msec = 7000; StatusReport = GetReportViaLogFile(&UtilityConfig::GetStatusSecondLogFileName, SleepTime_msec, TimeoutTime_msec); break; case StatusCheckMinute: SleepTime_msec = 10 * 1000; TimeoutTime_msec = 70 * 1000; std::cout << "Getting Sniffer status from status.minute log file (this takes about " << TimeoutTime_msec / 1000 << " s)..."; std::cout.flush(); StatusReport = GetReportViaLogFile(&UtilityConfig::GetStatusMinuteLogFileName, SleepTime_msec, TimeoutTime_msec); std::cout << "done." << std::endl; break; default: { std::string Temp; Temp = "No method for determining Sniffer status is available. "; Temp += "Tried XCI, status.second logging, and status.minute logging."; throw std::runtime_error(Temp); } } return StatusReport; } std::string UtilityConfig::GetReportViaXci() { if (Verbose()) { std::cout << "Getting Sniffer status report via XCI..."; std::cout.flush(); } bool ConnectSuccess = false; std::string ResultString; const std::string RequestString(""); // Code copied from SNFClient. // Max time in this loop should be (100*50ms) = 5 seconds per try times // 10 tries = 50 seconds, plus (9*500ms) = 4.5 secs for re-tries. ~ 55 secs. const int ResultBufferSize = 4096; char ResultBuffer[ResultBufferSize+1]; // Make an oversize buffer for the answer. memset(ResultBuffer, 0, sizeof(ResultBuffer)); // Set the entire thing to nulls. const int Tries = 20; // How many times to try this. Sleeper SleepAfterAttempt(100); // How long to sleep between attempts. const int OpenTries = 90; // How many tries at opening. Sleeper WaitForOpen(10); // How long to wait for an open cycle. const int ReadTries = 900; // How many tries at reading. Sleeper SleepBeforeReading(10); // How long to pause before reading. /* ** 20 * 100ms = 2 seconds for all tries. ** 90 * 10ms = 900ms for a failed connection. ** 900 * 10ms = 9 seconds for a failed read. ** ** Approximate wait for can't connect = 2.0 + (20 * 0.9) = ~ 20.0 seconds. ** Maximum impossible wait = 2.0 + (0.9 * 20) + (9.0 * 20) = 200.0 seconds. */ for(int tryagain = Tries; (0",ResultString.length())) { // If we don't have the end yet. continue; // Try again. } else { // If we got to end of line ConnectSuccess = true; // Success! break; // We're done. } } SNFServer.close(); // No need for our connection after that. } } catch(...) { } // Ignore errors for now. if(!ConnectSuccess) SleepAfterAttempt(); // Pause for a moment before trying again.. } if(!ConnectSuccess) { // If no connection then Sniffer isn't running. if (Verbose()) { std::cout << "no response..."; } return ""; } // At this point we should have a usable result. if(Debug()) { cout << ResultString << endl; } // In debug, show the result string. snf_xci Reader(ResultString); // Interpret the data and check for if(Reader.bad()) { // a proper read. If it was bad... std::string Temp; Temp = "Bad result from Sniffer:\n" + ResultString; throw std::runtime_error(Temp); } if(0 < Reader.xci_error_message.length()) { // If the result was a general error... std::string Temp; Temp = "XCI error when determing status of Sniffer: " + Reader.xci_error_message; throw std::runtime_error(Temp); } if (Verbose()) { std::cout << "response received..."; } return Reader.report_response; } std::string UtilityConfig::GetReportViaLogFile(GetLogFileName GetLogFileNamePtr, int SleepTime_msec, int TimeoutTime_msec) { std::string LogFileName; LogFileName = (this->*GetLogFileNamePtr)(); if (Verbose()) { cout << "\nGetting Sniffer status report via log file " << LogFileName << "..."; std::cout.flush(); } std::string InitialContents; InitialContents = ReadLastPartOfFile(LogFileName, LogFileReportSize); // Read last part of log file. int ElapsedTime_msec = 0; while (ElapsedTime_msec < TimeoutTime_msec) { bool IncreasedTimeoutTime = false; // TimeoutTime_msec can be increased // only once if the log file name changes. std::string NewLogFileName; Sleeper Sleep(SleepTime_msec); std::string FinalContents; Sleep(); NewLogFileName = (this->*GetLogFileNamePtr)(); if (!IncreasedTimeoutTime && (NewLogFileName != LogFileName)) { // Filename changes if it contains a // date stemp and the time is close // to midnight. TimeoutTime_msec *= 2; IncreasedTimeoutTime = true; if (Verbose()) { cout << "reading from " << NewLogFileName << "..."; std::cout.flush(); } } LogFileName = NewLogFileName; FinalContents = ReadLastPartOfFile(LogFileName, LogFileReportSize); // Read again. if ( (FinalContents.length() != 0) && // There is a report, and (InitialContents != FinalContents) ) { // the contents have changed. if (Verbose()) { cout << "report changed..."; } OutputVerboseEnd(); std::string::size_type StatsStartPos; // Index of start of element. std::string::size_type StatsEndPos; // Index of end of element. StatsEndPos = FinalContents.rfind(""); if (std::string::npos == StatsEndPos) { throw std::runtime_error("Unable to interpret the status report: No '' closing tag found."); } StatsStartPos = FinalContents.rfind("' tag found."); } return FinalContents.substr(StatsStartPos); // Return the last element. } ElapsedTime_msec += SleepTime_msec; } if (Verbose()) { cout << "report unchanged..."; } OutputVerboseEnd(); return ""; } void UtilityConfig::CheckSnifferStatusReport(std::string StatusReport, std::string ApplicationName) { if (Verbose()) { cout << "Checking Sniffer status report..."; } ConfigurationElement MyCFGReader("stats"); // Object to parse the XML. ConfigurationData MyCFGData(StatusReport.c_str(), StatusReport.length()); // Object that contains the XML. std::string PlatformContent; MyCFGReader .Element("version") .Element("platform", PlatformContent, "") .End("platform") .End("version") .End("stats"); MyCFGReader.initialize(); if (!MyCFGReader.interpret(MyCFGData)) { std::ostringstream Temp; Temp << "Error interpreting the Sniffer status report:\n" << StatusReport; throw std::runtime_error(Temp.str()); } if (std::string::npos == PlatformContent.find(ApplicationName)) { // Verify correct application. std::ostringstream Temp; Temp << "Error--The expected Sniffer application (" << ApplicationName << ") isn't running. The running application determined from the status report is " << PlatformContent; throw std::runtime_error(Temp.str()); } OutputVerboseEnd(); } UtilityConfig::SnifferRunningStateEnum UtilityConfig::GetRunningState(std::string ApplicationName) { if (Verbose()) { cout << "Checking whether " << ApplicationName << " is running..."; cout.flush(); } std::string StatusReport = GetSnifferStatusReport(); OutputVerboseEnd(); if (StatusReport.length() == 0) { return SnifferIsStopped; } CheckSnifferStatusReport(StatusReport, ApplicationName); return SnifferIsRunning; } void UtilityConfig::SetupRepair(const std::string SampleIdentityFile) { RestoreMissingConfigFiles(SampleIdentityFile); SetOwnerPermissionsOfConfigFiles(); } void UtilityConfig::RestoreMissingConfigFiles(std::string SampleIdentityFile) { std::string File; File = GetIdentityFileName(); if (!FileExists(File)) { if (!Explain()) { SaveFile.CreateBackupFile(File); } // Create the config file. Copy(SampleIdentityFile, File); } File = GetRulebaseScriptName(); if (!FileExists(File)) { if (!Explain()) { SaveFile.CreateBackupFile(File); } Copy(SampleRulebaseScriptFile, File); // Copy if !Explain(). } File = GetIgnoreListFileName(); if (!FileExists(File)) { if (!Explain()) { SaveFile.CreateBackupFile(File); } Copy(SampleIgnoreListFile, File); } std::string LogDir = GetLogPath(); if (!FileExists(LogDir)) { MkDir(LogDir); } } void UtilityConfig::SetOwnerPermissionsOfConfigFiles() { std::string File; File = GetIdentityFileName(); if (FileExists(File)) { SetMode(File, S_IRUSR | S_IWUSR | S_IRGRP); SetOwnerGroup(File); } File = GetRulebaseScriptName(); if (FileExists(File)) { SetMode(File, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH); } File = GetIgnoreListFileName(); if (FileExists(File)) { SetMode(File, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); SetOwnerGroup(File); } File = DEFAULT_DATA_DIR; if (FileExists(File)) { SetMode(File, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH); SetOwnerGroup(File); } std::string LogDir = GetLogPath(); if (FileExists(LogDir)) { SetMode(LogDir, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH); SetOwnerGroup(LogDir); } } void UtilityConfig::UpdateRulebaseScriptCredentials() { std::string File = GetRulebaseScriptName(); if (Verbose()) { cout << "Update authentication and license ID in the rulebase download script file " << File << "--\n"; } ifstream Input; Input.open(File.c_str()); // Read the contents. if (!Input) { string Temp; Temp = "Error opening rulebase download script file " + File; Temp += " for reading: "; Temp += strerror(errno); throw std::runtime_error(Temp); } string Content; string Line; bool FoundLicense = false; bool FoundAuth = false; while (getline(Input, Line)) { if (CheckForString(Line, LicenseSearchString)) { // Check for license line. if (FoundLicense) { // Second license line found? string Temp; Temp = "Rulebase sownload script file " + File; Temp += " has the wrong format: Found two lines beginning with " + LicenseSearchString; throw std::runtime_error(Temp); } if (Verbose()) { cout << " Modify line: '" << Line << "'...\n"; } FoundLicense = true; Line = LicenseSearchString + LicenseId; // Add license line. Line += " # Added by SNFSetup"; } if (CheckForString(Line, AuthSearchString)) { // Check for authentication line. if (FoundAuth) { // Second authentication line found? string Temp; Temp = "Rulebase download script file " + File; Temp += " has the wrong format: Found two lines beginning with " + AuthSearchString; throw std::runtime_error(Temp); } if (Verbose()) { cout << " Modify line: '" << Line << "'...\n"; } FoundAuth = true; Line = AuthSearchString + Authentication; // Add authentication line. Line += " # Added by SNFSetup"; } Content += Line + "\n"; } if (!FoundLicense || !FoundAuth) { string Temp; Temp = "Rulebase download script file " + File; Temp += " has the wrong format: Missing required line beginning with '" + LicenseSearchString; Temp += "' or '" + AuthSearchString; Temp += "'"; throw std::runtime_error(Temp); } if (!Input.eof()) { // Should be at end-of-file. string Temp; Temp = "Error reading the rulebase download script file " + File; Temp += ": "; Temp += strerror(errno); throw std::runtime_error(Temp); } Input.close(); if (Input.bad()) { string Temp; Temp = "Error closing the rulebase download script file " + File; Temp += " after reading: "; Temp += strerror(errno); throw std::runtime_error(Temp); } if (!Explain()) { SaveFile.CreateBackupFile(File); ofstream Output; // Write the updated contents. Output.open(File.c_str(), ios::trunc); if (!Output) { string Temp; Temp = "Error opening rulebase download script file " + File; Temp += " for writing: "; Temp += strerror(errno); throw std::runtime_error(Temp); } Output << Content; if (!Output) { string Temp; Temp = "Error writing the rulebase download script file " + File; Temp += ": "; Temp += strerror(errno); throw std::runtime_error(Temp); } Output.close(); if (!Output) { string Temp; Temp = "Error closing the rulebase download script file " + File; Temp += " after writing: "; Temp += strerror(errno); throw std::runtime_error(Temp); } } OutputVerboseEnd(); } void UtilityConfig::DownloadRulebase() { if (Verbose()) { std::cout << "Downloading the rulebase..."; std::cout.flush(); } std::string Command; Command = RulebaseDownloadCommand; std::string::size_type ScriptIndex = Command.find(ScriptNameKey); if (ScriptIndex != std::string::npos) { // Insert script full path? Command.replace(ScriptIndex, ScriptNameKey.length(), GetRulebaseScriptName()); } std::string::size_type SnifferPathIndex = Command.find(SnifferPathKey); if (SnifferPathIndex != std::string::npos) { // Insert rulebase location? Command.replace(SnifferPathIndex, SnifferPathKey.length(), GetRulebasePath()); } std::string StatusFile; // Construct download status file name. StatusFile = RulebaseDownloadStatusFile; SnifferPathIndex = StatusFile.find(SnifferPathKey); if (SnifferPathIndex != std::string::npos) { // Insert rulebase location? StatusFile.replace(SnifferPathIndex, SnifferPathKey.length(), GetRulebasePath()); } if (!Explain()) { SaveFile.CreateBackupFile(GetRulebaseFileName()); // Save the current rulebase file. if (0 != remove(StatusFile.c_str())) { // Delete the status file. if (ENOENT != errno) { // No error if the file doesn't exist. std::ostringstream Temp; Temp << "Unable to remove rulebase download status file " << StatusFile << ": " << strerror(errno); throw std::runtime_error(Temp.str()); } } if (std::system(Command.c_str()) != 0) { // Download the rulebase. string Temp; Temp = "Error running the command '" + Command; Temp += "'."; throw std::runtime_error(Temp); } ifstream Input; Input.open(StatusFile.c_str()); // Check the status. if (!Input) { string Temp; Temp = "Error opening rulebase download script status file " + StatusFile; Temp += ": "; Temp += strerror(errno); throw std::runtime_error(Temp); } string Line; string PrevLine; string Content; while (getline(Input, Line)) { // Read the last line. PrevLine = Line; Content += Line + "\n"; } if (PrevLine.find(SuccessKey) == std::string::npos) { // Check the status. string Temp; Temp = "Error downloading the rulebase. Rulebase download status:\n\n" + Content; throw std::runtime_error(Temp); } } OutputVerboseEnd(); } void UtilityConfig::UpdateIdentityFile() { std::string File = GetIdentityFileName(); if (Verbose()) { cout << "Update authentication and license ID in the identity file " << File << "--\n"; } ifstream Input; Input.open(File.c_str()); // Read the contents. if (!Input) { string Temp; Temp = "Error opening identity file " + File; Temp += " for reading: "; Temp += strerror(errno); throw std::runtime_error(Temp); } ostringstream InputContents; if (!Input.eof()) { // Copy if there are characters. // Copying an empty file causes InputContents << Input.rdbuf(); // failbit to be set. } if (InputContents.bad() || InputContents.fail()) { std::string Temp; Temp = "Error reading identity file " + File; throw std::runtime_error(Temp); } Input.close(); if (Input.bad()) { string Temp; Temp = "Error closing the identity file " + File; Temp += " after reading: "; Temp += strerror(errno); throw std::runtime_error(Temp); } string Content = InputContents.str(); try { ReplaceXmlAttribute(&Content, IdentityElementName, LicenseAttributeName, LicenseId); ReplaceXmlAttribute(&Content, IdentityElementName, AuthenticationAttributeName, Authentication); } catch (std::exception &e) { std::string Temp; Temp = "Error updating credentials for identity file " + File; Temp += ": "; Temp += e.what(); throw std::runtime_error(Temp); } if (!Explain()) { SaveFile.CreateBackupFile(File); ofstream Output; Output.open(File.c_str(), ios::trunc); if (!Output) { string Temp; Temp = "Error opening identity file " + File; Temp += " for writing: "; Temp += strerror(errno); throw std::runtime_error(Temp); } Output << Content; if (!Output) { string Temp; Temp = "Error writing the identity file " + File; Temp += ": "; Temp += strerror(errno); throw std::runtime_error(Temp); } Output.close(); if (!Output) { string Temp; Temp = "Error closing the identity file " + File; Temp += " after writing: "; Temp += strerror(errno); throw std::runtime_error(Temp); } } OutputVerboseEnd(); } #if 0 void UtilityConfig::UpdateIdentityFileOld() { std::string File = GetIdentityFileName(); ofstream Output; if (Verbose()) { cout << "Create identity file " << File << "..."; } if (!Explain()) { SaveFile.CreateBackupFile(File); Output.open(File.c_str()); if (!Output) { string Temp; Temp = "Error opening identity file " + File; Temp += ": "; Temp += strerror(errno); throw std::runtime_error(Temp); } Output << "\n" << "\n" << " \n" << "\n"; if (!Output) { string Temp; Temp = "Error writing identity file " + File; Temp += ": "; Temp += strerror(errno); throw std::runtime_error(Temp); } Output.close(); if (!Output) { string Temp; Temp = "Error closing identity file " + File; Temp += ": "; Temp += strerror(errno); throw std::runtime_error(Temp); } } OutputVerboseEnd(); SetOwnerGroup(File); // Set the user and group. SetMode(File, S_IRUSR); // Set to readonly by owner. } #endif void UtilityConfig::StartSniffer(std::string ScriptAndArgs, std::string ApplicationName) { if (SnifferIsRunning == GetRunningState(ApplicationName)) { std::cout << ApplicationName << " is already running.\n"; return; } std::string Command; Command = SnifferStartScriptDir + ScriptAndArgs; if (Verbose()) { cout << "Starting Sniffer with the command '" << Command << "'..."; cout.flush(); } if (!Explain()) { if (std::system(Command.c_str()) == -1) { // Start the sniffer. string Temp; Temp = "Error running the command '" + Command; Temp += "' to start the Sniffer: "; Temp += strerror(errno); throw std::runtime_error(Temp); } OutputVerboseEnd(); if (SnifferIsRunning != GetRunningState(ApplicationName)) { std::string Temp; Temp = "Unable to start " + ApplicationName; throw std::runtime_error(Temp); } } else { OutputVerboseEnd(); } } void UtilityConfig::StopSniffer(std::string ScriptAndArgs, std::string ApplicationName) { if (SnifferIsStopped == GetRunningState(ApplicationName)) { std::cout << ApplicationName << " was not running.\n"; return; } std::string Command; Command = SnifferStartScriptDir + ScriptAndArgs; if (Verbose()) { cout << "Stopping Sniffer with the command '" << Command << "'..."; cout.flush(); } if (!Explain()) { if (std::system(Command.c_str()) == -1) { // Start the sniffer. string Temp; Temp = "Error running the command '" + Command; Temp += "' to stop the Sniffer: "; Temp += strerror(errno); throw std::runtime_error(Temp); } OutputVerboseEnd(); if (SnifferIsStopped != GetRunningState(ApplicationName)) { std::string Temp; Temp = "Unable to stop " + ApplicationName; throw std::runtime_error(Temp); } } else { OutputVerboseEnd(); } } bool UtilityConfig::ProcessCommandLineItem(std::string OneInput) { bool ValidCommand = true; std::string TempString; if (OneInput == VerboseKey) { SetVerbose(true); } else if (OneInput == ExplainKey) { SetExplain(true); } else if (OneInput == HelpKey) { SetHelp(true); } else if (OneInput == SetupKey) { SetSetupRepair(true); } else if (OneInput == RepairKey) { SetSetupRepair(true); } else if (OneInput == StartSnifferKey) { SetStartSniffer(true); } else if (OneInput == StopSnifferKey) { SetStopSniffer(true); } else if (0 == OneInput.find(ConfigFileKey)) { TempString = Trim(OneInput.substr(ConfigFileKey.length())); // Copy only if not null after trimming. SetConfigFileName(TempString); } else if (0 == OneInput.find(LicenseIdKey)) { TempString = Trim(OneInput.substr(LicenseIdKey.length())); // Copy only if not null after trimming. if (!TempString.empty()) { LicenseId = TempString; LicenseIdIsSpecified = true; } else { ValidCommand = false; } } else if (0 == OneInput.find(AuthenticationKey)) { TempString = Trim(OneInput.substr(AuthenticationKey.length())); // Copy only if not null after trimming. if (!TempString.empty()) { Authentication = TempString; AuthenticationIsSpecified = true; } else { ValidCommand = false; } } else { ValidCommand = false; } return ValidCommand; } bool UtilityConfig::CommandLineIsOkay() { return (AuthenticationIsSpecified == LicenseIdIsSpecified); } std::string UtilityConfig::HelpCommandLine(std::string ExclusiveCommandsHelp) { std::string Help; Help = SetupKey + " | "; Help += RepairKey + " | "; Help += ExclusiveCommandsHelp + " | "; Help += LicenseIdKey + "licenseid " + AuthenticationKey + "authentication | "; Help += StartSnifferKey + " | "; Help += StopSnifferKey + " "; Help += "[" + ConfigFileKey + "snf-config-file] "; Help += "[ " + VerboseKey + " " + ExplainKey + " ]"; return Help; } std::string UtilityConfig::HelpDescription(std::string ExclusiveCommandsHelp) { std::string Desc; Desc = "creates and updates the configuration files (snf-config-file and\n"; Desc += "the ignore list file), the rulebase download script (default: getRulebase),\n"; Desc += "and the identity file if they don't exist.\n\n"; Desc += " -setup Perform initial setup/replace missing files\n"; Desc += " -repair Perform initial setup/replace missing files\n"; Desc += ExclusiveCommandsHelp; Desc += " -id=licenseid Specifies the license ID\n"; Desc += " -auth=authentication Specifies the Authentication\n"; Desc += " -start Start the sniffer\n"; Desc += " -stop Stop the sniffer\n"; Desc += " -v Provide verbose output\n"; Desc += " -explain Provide an explaination of the actions\n"; Desc += " without executing any commands\n"; return Desc; } void UtilityConfig::SetSetupRepair(bool Specified) { SetupRepairRequested = Specified; } bool UtilityConfig::SetupRepairSpecified() { return SetupRepairRequested; } bool UtilityConfig::UpdateCredentialsSpecified() { return ( (LicenseId.length() > 0) && (Authentication.length() > 0) ); } void UtilityConfig::SetStartSniffer(bool Specified) { StartSnifferRequested = Specified; } bool UtilityConfig::StartSnifferSpecified() { return StartSnifferRequested; } void UtilityConfig::SetStopSniffer(bool Specified) { StopSnifferRequested = Specified; } bool UtilityConfig::StopSnifferSpecified() { return StopSnifferRequested; }