// 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_PATH/getRulebase.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"); /// 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="; ////////////////////////////////////////////////////////////////////////////////////////////////////////// // End of configuration. ///////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////// UtilityConfig::UtilityConfig() : LicenseIdIsSpecified(false), AuthenticationIsSpecified(false), ConfigFileExists(true) { SetExplain(false); SetVerbose(false); SetHelp(false); } void UtilityConfig::CheckAndSetConfigFileName(const std::string DefaultFile[], int NumDefaultFiles) { string ProvisionalConfigFile = ConfigFileName; if (ProvisionalConfigFile.length() == 0) { int i; vector FoundFile; for (i = 0; i < NumDefaultFiles; i++) { if (!FileExists(DefaultFile[i])) { continue; // File doesn't exist. } FoundFile.push_back(DefaultFile[i]); // Update list of found files. ProvisionalConfigFile = DefaultFile[i]; // Found configuration file. } if (0 == FoundFile.size()) { // No default file found. if (NumDefaultFiles > 0) { ProvisionalConfigFile = DefaultFile[0]; // Use the first default file. ConfigFileExists = false; } else { // No default config file was specified. ostringstream Temp; Temp << "Internal error: NumDefaultFiles <= 0 at " << __FILE__ << ":" << __LINE__; throw runtime_error(Temp.str()); } } else if (FoundFile.size() > 1) { // Multiple default files found. string Temp; Temp = "Configuration file was not specified, and more than one default configuration file was found::\n\n"; for (i = 0; i < FoundFile.size(); i++) { Temp += " "; Temp += FoundFile[i] + "\n"; } throw runtime_error(Temp); } else { ConfigFileExists = true; // Config file was found. } } else { ConfigFileExists = FileExists(ProvisionalConfigFile); } SetConfigFileName(ProvisionalConfigFile); } void UtilityConfig::CreateDefaultConfigFile(std::string SampleConfigFile) { std::string File = GetConfigFileName(); if (!ConfigFileExists) { // Create the config file. Copy(SampleConfigFile, File); } } void UtilityConfig::CreateDefaultIdentityFile(std::string SampleIdentityFile) { std::string File = GetIdentityFileName(); if (!FileExists(File)) { // Create the config file. Copy(SampleIdentityFile, File); } } 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 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 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) { return CFGData.paths_rulebase_path; } string UtilityConfig::GetLogPath(void) { return CFGData.paths_log_path; } 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"; } else if ("FreeBSD" == OperatingSystemType) { PostfixMainCfPath = "/etc/postfix/main.cf"; PostfixMasterCfPath = "/etc/postfix/master.cf"; } else if ("Ubuntu" == OperatingSystemType) { PostfixMainCfPath = "/etc/postfix/main.cf"; PostfixMasterCfPath = "/etc/postfix/master.cf"; } else if ("RedHat" == OperatingSystemType) { PostfixMainCfPath = "/etc/postfix/main.cf"; PostfixMasterCfPath = "/etc/postfix/master.cf"; } else if ("Suse" == OperatingSystemType) { PostfixMainCfPath = "/etc/postfix/main.cf"; PostfixMasterCfPath = "/etc/postfix/master.cf"; } else { ostringstream Temp; Temp << "Internal error in UtilityConfig::LoadInfo: Invalid value of OperatingSystemType: " << OperatingSystemType; throw runtime_error(Temp.str()); } } void UtilityConfig::UpdateIgnoreListFile() { string IgnoreListFile = GetIgnoreListFileName(); if (!FileExists(IgnoreListFile)) { Copy(SampleIgnoreListFile, IgnoreListFile); } SetMode(IgnoreListFile, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); // Set permissions. SetOwnerGroup(IgnoreListFile); // Set to sniffer user. } void UtilityConfig::UpdateLogDir() { string LogDir = GetLogPath(); if (!FileExists(LogDir)) { MkDir(LogDir); } SetMode(LogDir, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH); SetOwnerGroup(LogDir); } bool UtilityConfig::UpdateCredentialsSpecified() { return ( (LicenseId.length() > 0) && (Authentication.length() > 0) ); } void UtilityConfig::CreateUpdateRulebaseScript() { std::string File = GetRulebaseScriptName(); if (!FileExists(File)) { Copy(SampleRulebaseScriptFile, File); // Copy if !Explain(). } if (UpdateCredentialsSpecified()) { UpdateRulebaseScriptCredentials(); } SetMode(File, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH); // Set permissions. } 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 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 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 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 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 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 runtime_error(Temp); } if (!Explain()) { 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 runtime_error(Temp); } Output << Content; if (!Output) { string Temp; Temp = "Error writing the rulebase download script file " + File; Temp += ": "; Temp += strerror(errno); throw 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 runtime_error(Temp); } } OutputVerboseEnd(); } void UtilityConfig::DownloadRulebase() { if (!UpdateCredentialsSpecified()) { return; } 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()) { 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) << "\n"; throw runtime_error(Temp.str()); } } if (std::system(Command.c_str()) != 0) { // Download the rulebase. string Temp; Temp = "Error running the command '" + Command; Temp += "'."; throw runtime_error(Temp); } ifstream Input; Input.open(StatusFile.c_str()); // Check the status. if (!Input) { string Temp; Temp = "Error opening rulebase download scriptstatus file " + StatusFile; Temp += ": "; Temp += strerror(errno); throw 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 runtime_error(Temp); } } OutputVerboseEnd(); } void UtilityConfig::UpdateIdentityFile() { std::string File = GetIdentityFileName(); if (UpdateCredentialsSpecified()) { ofstream Output; if (Verbose()) { cout << "Create identity file " << File << "..."; } if (!Explain()) { Output.open(File.c_str()); if (!Output) { string Temp; Temp = "Error opening identity file " + File; Temp += ": "; Temp += strerror(errno); throw runtime_error(Temp); } Output << "\n" << "\n" << " \n" << "\n"; if (!Output) { string Temp; Temp = "Error writing identity file " + File; Temp += ": "; Temp += strerror(errno); throw runtime_error(Temp); } Output.close(); if (!Output) { string Temp; Temp = "Error closing identity file " + File; Temp += ": "; Temp += strerror(errno); throw runtime_error(Temp); } } OutputVerboseEnd(); } SetOwnerGroup(File); // Set the user and group. SetMode(File, S_IRUSR); // Set to readonly by owner. } 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 == ConfigFileKey) { SetConfigFileName(OneInput.substr(ConfigFileKey.length())); } 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)) { Authentication = Trim(OneInput.substr(AuthenticationKey.length())); AuthenticationIsSpecified = true; } else { ValidCommand = false; } return ValidCommand; } bool UtilityConfig::CommandLineIsOkay() { return (AuthenticationIsSpecified == LicenseIdIsSpecified); } std::string UtilityConfig::HelpCommandLine() { std::string Help; Help = "[" + ConfigFileKey + "snf-config-file] "; Help += "[" + LicenseIdKey + "licenseid " + AuthenticationKey + "authentication] "; Help += "[ " + VerboseKey + " " + ExplainKey + " ]"; return Help; } std::string UtilityConfig::HelpDescription() { std::string Desc; Desc = " -config=snf-config-file Specifies the configuration file\n"; Desc += " -id=licenseid Specifies the license ID\n"; Desc += " -auth=authentication Specifies the Authentication\n"; Desc += " -v Provide verbose output\n"; Desc += " -explain Provide an explaination of the actions\n"; Desc += " without executing any commands\n"; return Desc; }