You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502
  1. // UtilityConfig.cpp
  2. //
  3. // Copyright (C) 2011, ARM Research Labs, LLC.
  4. // See www.armresearch.com for the copyright terms.
  5. //
  6. // This file implements the common functionality for the configuration
  7. // utilities.
  8. #include <cerrno>
  9. #include <cstring>
  10. #include <unistd.h>
  11. #include <pwd.h>
  12. #include <sys/types.h>
  13. #include <sys/stat.h>
  14. #include <stdexcept>
  15. #include <sstream>
  16. #include <iostream>
  17. #include <fstream>
  18. #include <vector>
  19. #include "UtilityConfig.hpp"
  20. using namespace std;
  21. //////////////////////////////////////////////////////////////////////////////////////////////////////////
  22. // Configuration. ////////////////////////////////////////////////////////////////////////////////////////
  23. //////////////////////////////////////////////////////////////////////////////////////////////////////////
  24. // Initialize OS-dependent constants.
  25. #ifdef WIN
  26. // Windows OS.
  27. const std::string UtilityConfig::SampleIgnoreListFile("C:\\SNF\\GBUdbIgnoreList.txt.sample");
  28. const std::string UtilityConfig::RulebaseDownloadCommand("FIX THIS");
  29. const std::string UtilityConfig::RulebaseDownloadStatusFile("FIX THIS");
  30. const std::string ScriptNameKey("FIX THIS"); ///< Text to replace with script name.
  31. const std::string SnifferPathKey("FIX THIS"); ///< Text to replace with directory of the rulebase.
  32. const std::string UtilityConfig::SampleRulebaseScriptFile("C:\\SNF\\getRulebase.sample");
  33. const std::string UtilityConfig::OperatingSystemType("Windows");
  34. #else
  35. // *nix OS.
  36. // SCRIPT is replaced with the full path of the script run,
  37. // SNIFFER_PATH is replaced with the path of the rulebase.
  38. const std::string UtilityConfig::RulebaseDownloadCommand
  39. ("(cd SNIFFER_PATH; touch UpdateReady.txt; chown snfuser UpdateReady.txt; su -m snfuser -c SCRIPT)");
  40. const std::string ScriptNameKey("SCRIPT"); ///< Text to replace with script name.
  41. const std::string SnifferPathKey("SNIFFER_PATH"); ///< Text to replace with directory of the rulebase.
  42. // SNIFFER_PATH is replaced with the path of the rulebase.
  43. const std::string UtilityConfig::RulebaseDownloadStatusFile("SNIFFER_PATH/getRulebase.status");
  44. #ifdef DEFAULT_DATA_DIR
  45. // *nix, DEFAULT_DATA_DIR is specified on the compile command line.
  46. const std::string UtilityConfig::SampleIgnoreListFile(DEFAULT_DATA_DIR "/GBUdbIgnoreList.txt.sample");
  47. #else
  48. // Not Windows, and DEFAULT_DATA_DIR is not specified on the compile
  49. // command line. In this case, we don't know the path for the sample
  50. // ignore list file.
  51. #error DEFAULT_DATA_DIR must be defined by -DDEFAULT_DATA_DIR="..." when compiling.
  52. #endif
  53. #ifdef SBIN_DIR
  54. // *nix, SBIN_DIR is specified on the compile command line.
  55. const std::string UtilityConfig::SampleRulebaseScriptFile(SBIN_DIR "/getRulebase.sample");
  56. #else
  57. // Not Windows, and SBIN_DIR is not specified on the compile
  58. // command line. In this case, we don't know the path for the sample
  59. // ignore list file.
  60. #error SBIN_DIR must be defined by -DSBIN_DIR="..." when compiling.
  61. #endif
  62. #ifdef SNF_OSTYPE
  63. // *nix, SNF_OSTYPE is specified on the compile command line.
  64. const std::string UtilityConfig::OperatingSystemType(SNF_OSTYPE);
  65. #else
  66. // Not Windows, and SNF_OSTYPE is not specified on the compile command
  67. // line. In this case, we don't know the operating system.
  68. #error SNF_OSTYPE must be defined by -DSNF_OSTYPE="..." when compiling.
  69. #endif
  70. #endif
  71. /// Verbose command-line input.
  72. const string VerboseKey("-v");
  73. /// Explain command-line input.
  74. const string ExplainKey("-explain");
  75. /// Help command-line input.
  76. const string HelpKey("-h");
  77. /// Setup command-line input.
  78. const string SetupKey("-setup");
  79. /// Repair command-line input.
  80. const string RepairKey("-repair");
  81. /// Start sniffer command-line input.
  82. const string StartSnifferKey("-start");
  83. /// Stop sniffer command-line input.
  84. const string StopSnifferKey("-stop");
  85. /// Configuration file command-line input.
  86. const string ConfigFileKey("-config=");
  87. /// License ID command-line input.
  88. const string LicenseIdKey("-id=");
  89. /// Authentication command-line input.
  90. const string AuthenticationKey("-auth=");
  91. /// String that indicates a successful rulebase download.
  92. //
  93. // This string must be in the last line of the getRulebase status
  94. // file. Note: The getRulebase status file is created by the
  95. // getRulebase script, has the name getRulebase.status, and is in the
  96. // same directory as the rulebase files.
  97. const string SuccessKey("Success");
  98. const string LicenseSearchString = "LICENSE_ID=";
  99. const string AuthSearchString = "AUTHENTICATION=";
  100. const string IdentityElementName = "identity";
  101. const string LicenseAttributeName = "licenseid";
  102. const string AuthenticationAttributeName = "authentication";
  103. //////////////////////////////////////////////////////////////////////////////////////////////////////////
  104. // End of configuration. /////////////////////////////////////////////////////////////////////////////////
  105. //////////////////////////////////////////////////////////////////////////////////////////////////////////
  106. UtilityConfig::UtilityConfig() :
  107. LicenseIdIsSpecified(false), AuthenticationIsSpecified(false)
  108. {
  109. SetExplain(false);
  110. SetVerbose(false);
  111. SetHelp(false);
  112. SetSetupRepair(false);
  113. SetStartSniffer(false);
  114. SetStopSniffer(false);
  115. }
  116. void
  117. UtilityConfig::CheckAndSetConfigFileName(const std::string DefaultFile[], int NumDefaultFiles) {
  118. string ProvisionalConfigFile = ConfigFileName;
  119. if (ProvisionalConfigFile.length() == 0) {
  120. int i;
  121. vector<string> FoundFile;
  122. for (i = 0; i < NumDefaultFiles; i++) {
  123. if (!FileExists(DefaultFile[i])) {
  124. continue; // File doesn't exist.
  125. }
  126. FoundFile.push_back(DefaultFile[i]); // Update list of found files.
  127. ProvisionalConfigFile = DefaultFile[i]; // Found configuration file.
  128. }
  129. if (0 == FoundFile.size()) { // No default file found.
  130. if (NumDefaultFiles > 0) {
  131. ProvisionalConfigFile = DefaultFile[0]; // Use the first default file.
  132. } else { // No default config file was specified.
  133. ostringstream Temp;
  134. Temp << "Internal error: NumDefaultFiles <= 0 at " << __FILE__ << ":" << __LINE__;
  135. throw std::runtime_error(Temp.str());
  136. }
  137. } else if (FoundFile.size() > 1) { // Multiple default files found.
  138. string Temp;
  139. Temp = "Configuration file was not specified, and more than one default configuration file was found::\n\n";
  140. for (i = 0; i < FoundFile.size(); i++) {
  141. Temp += " ";
  142. Temp += FoundFile[i] + "\n";
  143. }
  144. throw std::runtime_error(Temp);
  145. }
  146. }
  147. SetConfigFileName(ProvisionalConfigFile);
  148. }
  149. void
  150. UtilityConfig::CreateDefaultConfigFile(std::string SampleConfigFile) {
  151. std::string File = GetConfigFileName();
  152. if (!FileExists(File)) {
  153. if (!Explain()) {
  154. SaveFile.CreateBackupFile(File);
  155. }
  156. // Create the config file.
  157. Copy(SampleConfigFile, File);
  158. }
  159. SetMode(File, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); // Set permissions.
  160. SetOwnerGroup(File); // Set to sniffer user.
  161. }
  162. void
  163. UtilityConfig::LoadConfig() {
  164. if (Verbose()) {
  165. cout << "Using configuration file " << GetConfigFileName() << ".\n";
  166. }
  167. // Load the data.
  168. try {
  169. CFGData.initializeFromFile(GetConfigFileName().c_str());
  170. } catch(...) {
  171. string Temp;
  172. Temp = "Error reading configuration file " + GetConfigFileName();
  173. Temp += ".";
  174. throw std::runtime_error(Temp);
  175. }
  176. if ( (CFGData.paths_workspace_path.length() == 0) ||
  177. (CFGData.paths_rulebase_path.length() == 0) ||
  178. (CFGData.paths_log_path.length() == 0) ||
  179. (CFGData.update_script_call.length() == 0) ||
  180. (CFGData.node_identity.length() == 0) ) {
  181. string Temp;
  182. Temp = "The configuration file " + GetConfigFileName();
  183. Temp += " did not have the necessary specification of one or more paths:\n";
  184. Temp += "\n Workspace path: " + CFGData.paths_workspace_path;
  185. Temp += "\n Rulebase path: " + CFGData.paths_rulebase_path;
  186. Temp += "\n Log path: " + CFGData.paths_log_path;
  187. Temp += "\n Update script: " + CFGData.update_script_call;
  188. Temp += "\n Identity file: " + CFGData.node_identity;
  189. throw std::runtime_error(Temp);
  190. }
  191. }
  192. string
  193. UtilityConfig::GetPlatformContents(void) {
  194. return CFGData.PlatformElementContents;
  195. }
  196. string
  197. UtilityConfig::GetConfigFileName(void) {
  198. return ConfigFileName;
  199. }
  200. void
  201. UtilityConfig::SetConfigFileName(string Name) {
  202. ConfigFileName = Name;
  203. }
  204. string
  205. UtilityConfig::GetWorkspacePath(void) {
  206. return CFGData.paths_workspace_path;
  207. }
  208. string
  209. UtilityConfig::GetRulebasePath(void) {
  210. return CFGData.paths_rulebase_path;
  211. }
  212. string
  213. UtilityConfig::GetLogPath(void) {
  214. return CFGData.paths_log_path;
  215. }
  216. std::string
  217. UtilityConfig::GetStatusSecondLogFileName(void) {
  218. std::string FileName = CFGData.paths_log_path + CFGData.node_licenseid + ".status.second.log";
  219. if (CFGData.Scan_XML_Mode) {
  220. FileName += ".xml";
  221. }
  222. return FileName;
  223. }
  224. std::string
  225. UtilityConfig::GetStatusMinuteLogFileName(void) {
  226. std::string FileName = CFGData.paths_log_path + CFGData.node_licenseid + ".status.minute.log";
  227. if (CFGData.Scan_XML_Mode) {
  228. FileName += ".xml";
  229. }
  230. return FileName;
  231. }
  232. string
  233. UtilityConfig::GetIdentityFileName(void) {
  234. return CFGData.node_identity;
  235. }
  236. string
  237. UtilityConfig::GetRulebaseScriptName(void) {
  238. return CFGData.update_script_call;
  239. }
  240. string
  241. UtilityConfig::GetIgnoreListFileName(void) {
  242. return GetWorkspacePath() + "GBUdbIgnoreList.txt";
  243. }
  244. string
  245. UtilityConfig::GetRulebaseFileName(void) {
  246. std::string Name;
  247. Name = GetRulebasePath();
  248. Name += LicenseId + ".snf";
  249. return Name;
  250. }
  251. string
  252. UtilityConfig::GetOperatingSystemType(void) {
  253. return OperatingSystemType;
  254. }
  255. void
  256. UtilityConfig::LoadInfo(){
  257. if ("OpenBSD" == OperatingSystemType) {
  258. PostfixMainCfPath = "/usr/local/etc/postfix/main.cf";
  259. PostfixMasterCfPath = "/usr/local/etc/postfix/master.cf";
  260. SnifferStartScriptDir = "/usr/local/sbin/";
  261. } else if ("FreeBSD" == OperatingSystemType) {
  262. PostfixMainCfPath = "/etc/postfix/main.cf";
  263. PostfixMasterCfPath = "/etc/postfix/master.cf";
  264. SnifferStartScriptDir = "/usr/local/etc/rc.d/";
  265. } else if ("Ubuntu" == OperatingSystemType) {
  266. PostfixMainCfPath = "/etc/postfix/main.cf";
  267. PostfixMasterCfPath = "/etc/postfix/master.cf";
  268. SnifferStartScriptDir = "/etc/init.d/";
  269. } else if ("RedHat" == OperatingSystemType) {
  270. PostfixMainCfPath = "/etc/postfix/main.cf";
  271. PostfixMasterCfPath = "/etc/postfix/master.cf";
  272. SnifferStartScriptDir = "/etc/init.d/";
  273. } else if ("Suse" == OperatingSystemType) {
  274. PostfixMainCfPath = "/etc/postfix/main.cf";
  275. PostfixMasterCfPath = "/etc/postfix/master.cf";
  276. SnifferStartScriptDir = "/etc/init.d/";
  277. } else {
  278. ostringstream Temp;
  279. Temp << "Internal error in UtilityConfig::LoadInfo: Invalid value of OperatingSystemType: "
  280. << OperatingSystemType;
  281. throw std::runtime_error(Temp.str());
  282. }
  283. }
  284. void
  285. UtilityConfig::SetupRepairIdentityFile(std::string SampleIdentityFile) {
  286. std::string File = GetIdentityFileName();
  287. if (!FileExists(File)) {
  288. if (!Explain()) {
  289. SaveFile.CreateBackupFile(File);
  290. }
  291. // Create the config file.
  292. Copy(SampleIdentityFile, File);
  293. }
  294. }
  295. void
  296. UtilityConfig::SetupRepairRulebaseScript() {
  297. std::string File = GetRulebaseScriptName();
  298. if (!FileExists(File)) {
  299. if (!Explain()) {
  300. SaveFile.CreateBackupFile(File);
  301. }
  302. Copy(SampleRulebaseScriptFile, File); // Copy if !Explain().
  303. }
  304. SetMode(File, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH); // Set permissions.
  305. }
  306. void
  307. UtilityConfig::SetupRepairIgnoreListFile() {
  308. string File = GetIgnoreListFileName();
  309. if (!FileExists(File)) {
  310. if (!Explain()) {
  311. SaveFile.CreateBackupFile(File);
  312. }
  313. Copy(SampleIgnoreListFile, File);
  314. }
  315. SetMode(File, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); // Set permissions.
  316. SetOwnerGroup(File); // Set to sniffer user.
  317. }
  318. void
  319. UtilityConfig::SetupRepairLogDir() {
  320. string LogDir = GetLogPath();
  321. if (!FileExists(LogDir)) {
  322. MkDir(LogDir);
  323. }
  324. SetMode(LogDir, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
  325. SetOwnerGroup(LogDir);
  326. }
  327. UtilityConfig::StatusCheckMethod
  328. UtilityConfig::GetPreferredStatusCheckMethod(void) {
  329. if (CFGData.XCI_OnOff) {
  330. return StatusCheckXci;
  331. }
  332. if (CFGData.Status_SecondReport_Log_OnOff) {
  333. return StatusCheckSecond;
  334. }
  335. if (CFGData.Status_MinuteReport_Log_OnOff) {
  336. return StatusCheckMinute;
  337. }
  338. return StatusCheckNotAvailable;
  339. }
  340. std::string
  341. UtilityConfig::GetSnifferStatusReport() {
  342. std::string StatusReport;
  343. switch (GetPreferredStatusCheckMethod()) {
  344. case StatusCheckXci:
  345. StatusReport = GetReportViaXci();
  346. break;
  347. case StatusCheckSecond:
  348. StatusReport = GetReportViaLogFile(GetStatusSecondLogFileName(), 5000);
  349. break;
  350. case StatusCheckMinute:
  351. std::cout << "Getting Sniffer status from status.minute log file (this takes about 70 s)...";
  352. std::cout.flush();
  353. StatusReport = GetReportViaLogFile(GetStatusMinuteLogFileName(), 70 * 1000);
  354. std::cout << "done." << std::endl;
  355. break;
  356. default:
  357. {
  358. std::string Temp;
  359. Temp = "No method for determining Sniffer status is available. ";
  360. Temp += "Tried XCI, status.second logging, and status.minute logging.";
  361. throw std::runtime_error(Temp);
  362. }
  363. }
  364. return StatusReport;
  365. }
  366. std::string
  367. UtilityConfig::GetReportViaXci() {
  368. if (Verbose()) {
  369. cout << "Getting Sniffer status report via XCI...";
  370. }
  371. bool ConnectSuccess = false;
  372. std::string ResultString;
  373. const std::string RequestString("<snf><xci><report><request><status class='second'/></request></report></xci></snf>");
  374. // Code copied from SNFClient.
  375. // Max time in this loop should be (100*50ms) = 5 seconds per try times
  376. // 10 tries = 50 seconds, plus (9*500ms) = 4.5 secs for re-tries. ~ 55 secs.
  377. const int ResultBufferSize = 4096;
  378. char ResultBuffer[ResultBufferSize+1]; // Make an oversize buffer for the answer.
  379. memset(ResultBuffer, 0, sizeof(ResultBuffer)); // Set the entire thing to nulls.
  380. const int Tries = 20; // How many times to try this.
  381. Sleeper SleepAfterAttempt(100); // How long to sleep between attempts.
  382. const int OpenTries = 90; // How many tries at opening.
  383. Sleeper WaitForOpen(10); // How long to wait for an open cycle.
  384. const int ReadTries = 900; // How many tries at reading.
  385. Sleeper SleepBeforeReading(10); // How long to pause before reading.
  386. /*
  387. ** 20 * 100ms = 2 seconds for all tries.
  388. ** 90 * 10ms = 900ms for a failed connection.
  389. ** 900 * 10ms = 9 seconds for a failed read.
  390. **
  391. ** Approximate wait for can't connect = 2.0 + (20 * 0.9) = ~ 20.0 seconds.
  392. ** Maximum impossible wait = 2.0 + (0.9 * 20) + (9.0 * 20) = 200.0 seconds.
  393. */
  394. for(int tryagain = Tries; (0<tryagain) && (!ConnectSuccess); tryagain--) { // Try a few times to get this done.
  395. try {
  396. ResultString = ""; // Clear our result string.
  397. TCPHost SNFServer(9001); // Create connection to server.
  398. SNFServer.makeNonBlocking(); // Make it non-blocking.
  399. for(int tries = OpenTries; 0 < tries; tries--) { // Wait & Watch for a good connection.
  400. try { SNFServer.open(); } catch(...) {} // Try opening the connection.
  401. if(SNFServer.isOpen()) break; // When successful, let's Go!
  402. else WaitForOpen(); // When not successful, pause.
  403. }
  404. if(SNFServer.isOpen()) { // If we have a good connection:
  405. SNFServer.transmit(
  406. RequestString.c_str(), RequestString.length()); // Send the request.
  407. for(int tries = ReadTries; 0 < tries; tries--) { // Try to read the result a few times.
  408. SleepBeforeReading(); // Provide some time for each try.
  409. memset(ResultBuffer, 0, sizeof(ResultBuffer)); // Clear the buffer.
  410. SNFServer.receive(ResultBuffer, ResultBufferSize); // Receive the answer.
  411. ResultString.append(ResultBuffer);
  412. if(string::npos ==
  413. ResultString.rfind("</snf>",ResultString.length())) { // If we don't have the end yet.
  414. continue; // Try again.
  415. } else { // If we got to end of line
  416. ConnectSuccess = true; // Success!
  417. break; // We're done.
  418. }
  419. }
  420. SNFServer.close(); // No need for our connection after that.
  421. }
  422. } catch(...) { } // Ignore errors for now.
  423. if(!ConnectSuccess) SleepAfterAttempt(); // Pause for a moment before trying again..
  424. }
  425. if(!ConnectSuccess) { // If no connection then Sniffer isn't running.
  426. if (Verbose()) {
  427. cout << "no response...";
  428. }
  429. return "";
  430. }
  431. // At this point we should have a usable result.
  432. if(Debug()) { cout << ResultString << endl; } // In debug, show the result string.
  433. snf_xci Reader(ResultString); // Interpret the data and check for
  434. if(Reader.bad()) { // a proper read. If it was bad...
  435. std::string Temp;
  436. Temp = "Bad result from Sniffer:\n" + ResultString;
  437. throw std::runtime_error(Temp);
  438. }
  439. if(0 < Reader.xci_error_message.length()) { // If the result was a general error...
  440. std::string Temp;
  441. Temp = "XCI error when determing status of Sniffer: " + Reader.xci_error_message;
  442. throw std::runtime_error(Temp);
  443. }
  444. OutputVerboseEnd();
  445. return Reader.report_response;
  446. }
  447. std::string
  448. UtilityConfig::GetReportViaLogFile(std::string LogFileName, int SleepTime_msec) {
  449. if (Verbose()) {
  450. cout << "Getting Sniffer status report via log file " << LogFileName << "...";
  451. }
  452. std::string InitialContents;
  453. InitialContents = ReadLastPartOfFile(LogFileName, LogFileReportSize); // Read last part of log file.
  454. Sleeper Sleep(SleepTime_msec); // Wait 5 s.
  455. Sleep();
  456. std::string FinalContents;
  457. FinalContents = ReadLastPartOfFile(LogFileName, LogFileReportSize); // Read again.
  458. if (InitialContents == FinalContents) { // If unchanged...
  459. if (Verbose()) {
  460. cout << "report unchanged...";
  461. }
  462. return ""; // ...there is no report.
  463. }
  464. OutputVerboseEnd();
  465. return FinalContents;
  466. }
  467. void
  468. UtilityConfig::CheckSnifferStatusReport(std::string StatusReport, std::string ApplicationName) {
  469. if (Verbose()) {
  470. cout << "Checking Sniffer status report...";
  471. }
  472. ConfigurationElement MyCFGReader("stats"); // Object to parse the XML.
  473. ConfigurationData MyCFGData(StatusReport); // Object that contains the XML.
  474. std::string PlatformContent;
  475. MyCFGReader
  476. .Element("version")
  477. .Element("platform", PlatformContent, "")
  478. .End("platform")
  479. .End("version")
  480. .End("stats");
  481. MyCFGReader.initialize();
  482. if (!MyCFGReader.interpret(MyCFGData)) {
  483. std::ostringstream Temp;
  484. Temp << "Error interpreting the Sniffer status report:\n" << StatusReport;
  485. throw std::runtime_error(Temp.str());
  486. }
  487. if (std::string::npos == PlatformContent.find(ApplicationName)) { // Verify correct application.
  488. std::ostringstream Temp;
  489. Temp << "Error--The expected Sniffer application (" << ApplicationName
  490. << ") isn't running. The running application determined from the status report is "
  491. << PlatformContent;
  492. throw std::runtime_error(Temp.str());
  493. }
  494. OutputVerboseEnd();
  495. }
  496. UtilityConfig::SnifferRunningStateEnum
  497. UtilityConfig::GetRunningState(std::string ApplicationName) {
  498. if (Verbose()) {
  499. cout << "Checking whether " << ApplicationName << " is running...";
  500. }
  501. std::string StatusReport = GetSnifferStatusReport();
  502. if (StatusReport.length() == 0) {
  503. return SnifferIsStopped;
  504. }
  505. CheckSnifferStatusReport(StatusReport, ApplicationName);
  506. OutputVerboseEnd();
  507. return SnifferIsRunning;
  508. }
  509. void
  510. UtilityConfig::SetupRepair(const std::string SampleIdentityFile) {
  511. SetupRepairIdentityFile(SampleIdentityFile);
  512. SetupRepairRulebaseScript();
  513. SetupRepairIgnoreListFile();
  514. SetupRepairLogDir();
  515. }
  516. void
  517. UtilityConfig::UpdateRulebaseScriptCredentials() {
  518. std::string File = GetRulebaseScriptName();
  519. if (Verbose()) {
  520. cout << "Update authentication and license ID in the rulebase download script file " << File << "--\n";
  521. }
  522. ifstream Input;
  523. Input.open(File.c_str()); // Read the contents.
  524. if (!Input) {
  525. string Temp;
  526. Temp = "Error opening rulebase download script file " + File;
  527. Temp += " for reading: ";
  528. Temp += strerror(errno);
  529. throw std::runtime_error(Temp);
  530. }
  531. string Content;
  532. string Line;
  533. bool FoundLicense = false;
  534. bool FoundAuth = false;
  535. while (getline(Input, Line)) {
  536. if (CheckForString(Line, LicenseSearchString)) { // Check for license line.
  537. if (FoundLicense) { // Second license line found?
  538. string Temp;
  539. Temp = "Rulebase sownload script file " + File;
  540. Temp += " has the wrong format: Found two lines beginning with " + LicenseSearchString;
  541. throw std::runtime_error(Temp);
  542. }
  543. if (Verbose()) {
  544. cout << " Modify line: '" << Line << "'...\n";
  545. }
  546. FoundLicense = true;
  547. Line = LicenseSearchString + LicenseId; // Add license line.
  548. Line += " # Added by SNFSetup";
  549. }
  550. if (CheckForString(Line, AuthSearchString)) { // Check for authentication line.
  551. if (FoundAuth) { // Second authentication line found?
  552. string Temp;
  553. Temp = "Rulebase download script file " + File;
  554. Temp += " has the wrong format: Found two lines beginning with " + AuthSearchString;
  555. throw std::runtime_error(Temp);
  556. }
  557. if (Verbose()) {
  558. cout << " Modify line: '" << Line << "'...\n";
  559. }
  560. FoundAuth = true;
  561. Line = AuthSearchString + Authentication; // Add authentication line.
  562. Line += " # Added by SNFSetup";
  563. }
  564. Content += Line + "\n";
  565. }
  566. if (!FoundLicense || !FoundAuth) {
  567. string Temp;
  568. Temp = "Rulebase download script file " + File;
  569. Temp += " has the wrong format: Missing required line beginning with '" + LicenseSearchString;
  570. Temp += "' or '" + AuthSearchString;
  571. Temp += "'";
  572. throw std::runtime_error(Temp);
  573. }
  574. if (!Input.eof()) { // Should be at end-of-file.
  575. string Temp;
  576. Temp = "Error reading the rulebase download script file " + File;
  577. Temp += ": ";
  578. Temp += strerror(errno);
  579. throw std::runtime_error(Temp);
  580. }
  581. Input.close();
  582. if (Input.bad()) {
  583. string Temp;
  584. Temp = "Error closing the rulebase download script file " + File;
  585. Temp += " after reading: ";
  586. Temp += strerror(errno);
  587. throw std::runtime_error(Temp);
  588. }
  589. if (!Explain()) {
  590. SaveFile.CreateBackupFile(File);
  591. ofstream Output; // Write the updated contents.
  592. Output.open(File.c_str(), ios::trunc);
  593. if (!Output) {
  594. string Temp;
  595. Temp = "Error opening rulebase download script file " + File;
  596. Temp += " for writing: ";
  597. Temp += strerror(errno);
  598. throw std::runtime_error(Temp);
  599. }
  600. Output << Content;
  601. if (!Output) {
  602. string Temp;
  603. Temp = "Error writing the rulebase download script file " + File;
  604. Temp += ": ";
  605. Temp += strerror(errno);
  606. throw std::runtime_error(Temp);
  607. }
  608. Output.close();
  609. if (!Output) {
  610. string Temp;
  611. Temp = "Error closing the rulebase download script file " + File;
  612. Temp += " after writing: ";
  613. Temp += strerror(errno);
  614. throw std::runtime_error(Temp);
  615. }
  616. }
  617. OutputVerboseEnd();
  618. }
  619. void
  620. UtilityConfig::DownloadRulebase() {
  621. if (Verbose()) {
  622. std::cout << "Downloading the rulebase...";
  623. std::cout.flush();
  624. }
  625. std::string Command;
  626. Command = RulebaseDownloadCommand;
  627. std::string::size_type ScriptIndex = Command.find(ScriptNameKey);
  628. if (ScriptIndex != std::string::npos) { // Insert script full path?
  629. Command.replace(ScriptIndex, ScriptNameKey.length(), GetRulebaseScriptName());
  630. }
  631. std::string::size_type SnifferPathIndex = Command.find(SnifferPathKey);
  632. if (SnifferPathIndex != std::string::npos) { // Insert rulebase location?
  633. Command.replace(SnifferPathIndex, SnifferPathKey.length(), GetRulebasePath());
  634. }
  635. std::string StatusFile; // Construct download status file name.
  636. StatusFile = RulebaseDownloadStatusFile;
  637. SnifferPathIndex = StatusFile.find(SnifferPathKey);
  638. if (SnifferPathIndex != std::string::npos) { // Insert rulebase location?
  639. StatusFile.replace(SnifferPathIndex, SnifferPathKey.length(), GetRulebasePath());
  640. }
  641. if (!Explain()) {
  642. SaveFile.CreateBackupFile(GetRulebaseFileName()); // Save the current rulebase file.
  643. if (0 != remove(StatusFile.c_str())) { // Delete the status file.
  644. if (ENOENT != errno) { // No error if the file doesn't exist.
  645. std::ostringstream Temp;
  646. Temp << "Unable to remove rulebase download status file " << StatusFile
  647. << ": " << strerror(errno);
  648. throw std::runtime_error(Temp.str());
  649. }
  650. }
  651. if (std::system(Command.c_str()) != 0) { // Download the rulebase.
  652. string Temp;
  653. Temp = "Error running the command '" + Command;
  654. Temp += "'.";
  655. throw std::runtime_error(Temp);
  656. }
  657. ifstream Input;
  658. Input.open(StatusFile.c_str()); // Check the status.
  659. if (!Input) {
  660. string Temp;
  661. Temp = "Error opening rulebase download scriptstatus file " + StatusFile;
  662. Temp += ": ";
  663. Temp += strerror(errno);
  664. throw std::runtime_error(Temp);
  665. }
  666. string Line;
  667. string PrevLine;
  668. string Content;
  669. while (getline(Input, Line)) { // Read the last line.
  670. PrevLine = Line;
  671. Content += Line + "\n";
  672. }
  673. if (PrevLine.find(SuccessKey) == std::string::npos) { // Check the status.
  674. string Temp;
  675. Temp = "Error downloading the rulebase. Rulebase download status:\n\n" + Content;
  676. throw std::runtime_error(Temp);
  677. }
  678. }
  679. OutputVerboseEnd();
  680. }
  681. void
  682. UtilityConfig::UpdateIdentityFile() {
  683. std::string File = GetIdentityFileName();
  684. if (Verbose()) {
  685. cout << "Update authentication and license ID in the identity file " << File << "--\n";
  686. }
  687. ifstream Input;
  688. Input.open(File.c_str()); // Read the contents.
  689. if (!Input) {
  690. string Temp;
  691. Temp = "Error opening identity file " + File;
  692. Temp += " for reading: ";
  693. Temp += strerror(errno);
  694. throw std::runtime_error(Temp);
  695. }
  696. ostringstream InputContents;
  697. if (!Input.eof()) { // Copy if there are characters.
  698. // Copying an empty file causes
  699. InputContents << Input.rdbuf(); // failbit to be set.
  700. }
  701. if (InputContents.bad() || InputContents.fail()) {
  702. std::string Temp;
  703. Temp = "Error reading identity file " + File;
  704. throw std::runtime_error(Temp);
  705. }
  706. Input.close();
  707. if (Input.bad()) {
  708. string Temp;
  709. Temp = "Error closing the identity file " + File;
  710. Temp += " after reading: ";
  711. Temp += strerror(errno);
  712. throw std::runtime_error(Temp);
  713. }
  714. string Content = InputContents.str();
  715. try {
  716. ReplaceXmlAttribute(&Content, IdentityElementName, LicenseAttributeName, LicenseId);
  717. ReplaceXmlAttribute(&Content, IdentityElementName, AuthenticationAttributeName, Authentication);
  718. } catch (std::exception &e) {
  719. std::string Temp;
  720. Temp = "Error updating credentials for identity file " + File;
  721. Temp += ": ";
  722. Temp += e.what();
  723. throw std::runtime_error(Temp);
  724. }
  725. if (!Explain()) {
  726. SaveFile.CreateBackupFile(File);
  727. ofstream Output;
  728. Output.open(File.c_str(), ios::trunc);
  729. if (!Output) {
  730. string Temp;
  731. Temp = "Error opening identity file " + File;
  732. Temp += " for writing: ";
  733. Temp += strerror(errno);
  734. throw std::runtime_error(Temp);
  735. }
  736. Output << Content;
  737. if (!Output) {
  738. string Temp;
  739. Temp = "Error writing the identity file " + File;
  740. Temp += ": ";
  741. Temp += strerror(errno);
  742. throw std::runtime_error(Temp);
  743. }
  744. Output.close();
  745. if (!Output) {
  746. string Temp;
  747. Temp = "Error closing the identity file " + File;
  748. Temp += " after writing: ";
  749. Temp += strerror(errno);
  750. throw std::runtime_error(Temp);
  751. }
  752. }
  753. OutputVerboseEnd();
  754. }
  755. #if 0
  756. void
  757. UtilityConfig::UpdateIdentityFileOld() {
  758. std::string File = GetIdentityFileName();
  759. ofstream Output;
  760. if (Verbose()) {
  761. cout << "Create identity file " << File << "...";
  762. }
  763. if (!Explain()) {
  764. SaveFile.CreateBackupFile(File);
  765. Output.open(File.c_str());
  766. if (!Output) {
  767. string Temp;
  768. Temp = "Error opening identity file " + File;
  769. Temp += ": ";
  770. Temp += strerror(errno);
  771. throw std::runtime_error(Temp);
  772. }
  773. Output << "<!-- License file created by SNFIdentity-->\n"
  774. << "<snf>\n"
  775. << " <identity licenseid='" << LicenseId << "' authentication='"
  776. << Authentication << "'/>\n"
  777. << "</snf>\n";
  778. if (!Output) {
  779. string Temp;
  780. Temp = "Error writing identity file " + File;
  781. Temp += ": ";
  782. Temp += strerror(errno);
  783. throw std::runtime_error(Temp);
  784. }
  785. Output.close();
  786. if (!Output) {
  787. string Temp;
  788. Temp = "Error closing identity file " + File;
  789. Temp += ": ";
  790. Temp += strerror(errno);
  791. throw std::runtime_error(Temp);
  792. }
  793. }
  794. OutputVerboseEnd();
  795. SetOwnerGroup(File); // Set the user and group.
  796. SetMode(File, S_IRUSR); // Set to readonly by owner.
  797. }
  798. #endif
  799. void
  800. UtilityConfig::StartSniffer(std::string ScriptAndArgs, std::string ApplicationName) {
  801. std::string Command;
  802. Command = SnifferStartScriptDir + ScriptAndArgs;
  803. if (Verbose()) {
  804. cout << "Starting Sniffer with the command '" << Command << "'...";
  805. }
  806. if (SnifferIsRunning == GetRunningState(ApplicationName)) {
  807. std::cout << ApplicationName << " is already running.\n";
  808. OutputVerboseEnd();
  809. return;
  810. }
  811. if (!Explain()) {
  812. if (std::system(Command.c_str()) == -1) { // Start the sniffer.
  813. string Temp;
  814. Temp = "Error running the command '" + Command;
  815. Temp += "' to start the Sniffer: ";
  816. Temp += strerror(errno);
  817. throw std::runtime_error(Temp);
  818. }
  819. }
  820. if (SnifferIsRunning != GetRunningState(ApplicationName)) {
  821. std::string Temp;
  822. Temp = "Unable to start " + ApplicationName;
  823. throw std::runtime_error(Temp);
  824. }
  825. OutputVerboseEnd();
  826. }
  827. void
  828. UtilityConfig::StopSniffer(std::string ScriptAndArgs, std::string ApplicationName) {
  829. std::string Command;
  830. Command = SnifferStartScriptDir + ScriptAndArgs;
  831. if (Verbose()) {
  832. cout << "Stopping Sniffer with the command '" << Command << "'...";
  833. }
  834. if (SnifferIsStopped == GetRunningState(ApplicationName)) {
  835. std::cout << ApplicationName << " is already not running.\n";
  836. OutputVerboseEnd();
  837. return;
  838. }
  839. if (!Explain()) {
  840. if (std::system(Command.c_str()) == -1) { // Start the sniffer.
  841. string Temp;
  842. Temp = "Error running the command '" + Command;
  843. Temp += "' to stop the Sniffer: ";
  844. Temp += strerror(errno);
  845. throw std::runtime_error(Temp);
  846. }
  847. }
  848. if (SnifferIsStopped != GetRunningState(ApplicationName)) {
  849. std::string Temp;
  850. Temp = "Unable to sto " + ApplicationName;
  851. throw std::runtime_error(Temp);
  852. }
  853. OutputVerboseEnd();
  854. }
  855. bool
  856. UtilityConfig::ProcessCommandLineItem(std::string OneInput) {
  857. bool ValidCommand = true;
  858. std::string TempString;
  859. if (OneInput == VerboseKey) {
  860. SetVerbose(true);
  861. } else if (OneInput == ExplainKey) {
  862. SetExplain(true);
  863. } else if (OneInput == HelpKey) {
  864. SetHelp(true);
  865. } else if (OneInput == SetupKey) {
  866. SetSetupRepair(true);
  867. } else if (OneInput == RepairKey) {
  868. SetSetupRepair(true);
  869. } else if (OneInput == StartSnifferKey) {
  870. SetStartSniffer(true);
  871. } else if (OneInput == StopSnifferKey) {
  872. SetStopSniffer(true);
  873. } else if (OneInput == ConfigFileKey) {
  874. SetConfigFileName(OneInput.substr(ConfigFileKey.length()));
  875. } else if (0 == OneInput.find(LicenseIdKey)) {
  876. TempString = Trim(OneInput.substr(LicenseIdKey.length())); // Copy only if not null after trimming.
  877. if (!TempString.empty()) {
  878. LicenseId = TempString;
  879. LicenseIdIsSpecified = true;
  880. } else {
  881. ValidCommand = false;
  882. }
  883. } else if (0 == OneInput.find(AuthenticationKey)) {
  884. Authentication = Trim(OneInput.substr(AuthenticationKey.length()));
  885. AuthenticationIsSpecified = true;
  886. } else {
  887. ValidCommand = false;
  888. }
  889. return ValidCommand;
  890. }
  891. bool
  892. UtilityConfig::CommandLineIsOkay() {
  893. return (AuthenticationIsSpecified == LicenseIdIsSpecified);
  894. }
  895. std::string
  896. UtilityConfig::HelpCommandLine(std::string ExclusiveCommandsHelp) {
  897. std::string Help;
  898. Help = SetupKey + " | ";
  899. Help += RepairKey + " | ";
  900. Help += ExclusiveCommandsHelp + " | ";
  901. Help += LicenseIdKey + "licenseid " + AuthenticationKey + "authentication | ";
  902. Help += StartSnifferKey + " | ";
  903. Help += StopSnifferKey + " ";
  904. Help += "[" + ConfigFileKey + "snf-config-file] ";
  905. Help += "[ " + VerboseKey + " " + ExplainKey + " ]";
  906. return Help;
  907. }
  908. std::string
  909. UtilityConfig::HelpDescription(std::string ExclusiveCommandsHelp) {
  910. std::string Desc;
  911. Desc = "creates and updates the configuration files (snf-config-file and\n";
  912. Desc += "the ignore list file), the rulebase download script (default: getRulebase),\n";
  913. Desc += "and the identity file if they don't exist.\n\n";
  914. Desc += " -setup Perform initial setup/replace missing files\n";
  915. Desc += " -repair Perform initial setup/replace missing files\n";
  916. Desc += ExclusiveCommandsHelp;
  917. Desc += " -id=licenseid Specifies the license ID\n";
  918. Desc += " -auth=authentication Specifies the Authentication\n";
  919. Desc += " -start Start the sniffer\n";
  920. Desc += " -stop Stop the sniffer\n";
  921. Desc += " -config=snf-config-file Specifies the configuration file\n";
  922. Desc += " -v Provide verbose output\n";
  923. Desc += " -explain Provide an explaination of the actions\n";
  924. Desc += " without executing any commands\n";
  925. return Desc;
  926. }
  927. void
  928. UtilityConfig::SetSetupRepair(bool Specified) {
  929. SetupRepairRequested = Specified;
  930. }
  931. bool
  932. UtilityConfig::SetupRepairSpecified() {
  933. return SetupRepairRequested;
  934. }
  935. bool
  936. UtilityConfig::UpdateCredentialsSpecified() {
  937. return ( (LicenseId.length() > 0) && (Authentication.length() > 0) );
  938. }
  939. void
  940. UtilityConfig::SetStartSniffer(bool Specified) {
  941. StartSnifferRequested = Specified;
  942. }
  943. bool
  944. UtilityConfig::StartSnifferSpecified() {
  945. return StartSnifferRequested;
  946. }
  947. void
  948. UtilityConfig::SetStopSniffer(bool Specified) {
  949. StopSnifferRequested = Specified;
  950. }
  951. bool
  952. UtilityConfig::StopSnifferSpecified() {
  953. return StopSnifferRequested;
  954. }