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.

UtilityConfig.cpp 39KB

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