The Poor Man's (or Woman's) Intrusion Detection System
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.
 
 
 
 

204 lines
5.6 KiB

  1. //////////////////////////////////////////////////////////////////////
  2. // Traffic Montor Control HTTP server
  3. // Written by Jonathan A. Foster <jon@jfpossibilities.com>
  4. // Started August 13th, 2021
  5. // Copyright JF Possibilities, Inc. All rights reserved.
  6. //
  7. // Provide a control panel to manage which domains we want to watch,
  8. // ignore anc block.
  9. //////////////////////////////////////////////////////////////////////
  10. #include <stdlib.h>
  11. #include <string>
  12. #include <stdexcept>
  13. #include <iostream>
  14. /// C++CMS/DB ///
  15. #include <cppcms/service.h>
  16. #include <cppcms/applications_pool.h>
  17. #include <cppcms/mount_point.h>
  18. #include <cppcms/url_dispatcher.h>
  19. #include <cppcms/url_mapper.h>
  20. #include <cppcms/http_request.h>
  21. #include <cppcms/http_response.h>
  22. #include <cppdb/frontend.h>
  23. /// Our app ///
  24. #include "../strutil.h"
  25. #include "data.h"
  26. /// Build flags ///
  27. // TODO: better application of C++CMS booster logging
  28. //#define DEBUGGIN
  29. //////////////////////////////////////////////////////////////////////
  30. // C++CMS App to manage the state of all known domain names.
  31. //////////////////////////////////////////////////////////////////////
  32. const std::string filter_titles[] = { "Undecided", "Accepted", "Blocked" };
  33. const std::string actions[] = { "Reset", "Accept", "Block" };
  34. std::string root_uri = "";
  35. struct app: public cppcms::application {
  36. std::auto_ptr<cppdb::session> sql;
  37. int items_per_page;
  38. std::string numlist(const std::string &field) {
  39. std::string r;
  40. const cppcms::http::request::form_type &POST = request().post();
  41. for(
  42. cppcms::http::request::form_type::const_iterator it = POST.find(field);
  43. it!=POST.end() && it->first==field;
  44. it++
  45. ) {
  46. if(it->second!="") {
  47. if(r!="") r+=",";
  48. r+="'"+sql->escape(it->second)+"'";
  49. }
  50. }
  51. return r;
  52. }
  53. void list(Domain::STATUS sid) {
  54. int i;
  55. std::string s;
  56. StringList list;
  57. DomainList c;
  58. // TODO: put this someplace else?
  59. /// Form processing ///
  60. if(request().request_method()=="POST") {
  61. std::string op = request().post("op");
  62. // nothing to do without a valid "op"
  63. if(op=="0" || op=="1" || op=="2") {
  64. // eliminate NOP busywork
  65. if((s=numlist("id"))!="" && sid!=atoi(op.c_str())) {
  66. *sql << "UPDATE dns SET status="+op+" WHERE name IN ("+s+")"
  67. << cppdb::exec;
  68. }
  69. if((s=request().post("domain"))!="") {
  70. *sql << "UPDATE dns SET status=? WHERE name=? OR name LIKE ?"
  71. << op << s << ("%."+s)
  72. << cppdb::exec;
  73. }
  74. }
  75. }
  76. /// Auto add unknown domains to DNS list ///
  77. cppdb::result r = *sql <<
  78. "SELECT c.them_name "
  79. "FROM connections c LEFT OUTER JOIN dns ON c.them_name=dns.name "
  80. "WHERE c.them_name<>'' AND dns.name IS NULL "
  81. "GROUP BY c.them_name";
  82. while(r.next()) {
  83. r >> s;
  84. list.push_back(s);
  85. }
  86. if(!list.empty()) {
  87. cppdb::statement q = *sql << "INSERT INTO dns (name) VALUES (?)";
  88. for(StringList::iterator i=list.begin(); i!=list.end(); i++) {
  89. q.reset();
  90. q << *i << cppdb::exec;
  91. }
  92. }
  93. /// Produce list of unknowns ///
  94. c.filter = filter_titles[sid];
  95. s = request().get("pg");
  96. if(s=="")
  97. c.page = 1;
  98. else
  99. c.page = atoi(s.c_str());
  100. if(c.page < 1 || c.page > 999999) c.page = 1;
  101. r = *sql << "SELECT name, decided, status FROM dns WHERE status=? "
  102. "LIMIT "+str((c.page-1)*items_per_page)+","+str(items_per_page)
  103. << sid;
  104. for(i = c.list.size(); r.next(); i++) {
  105. c.list.resize(i+1);
  106. r >> c.list[i].name >> c.list[i].decided >> c.list[i].status;
  107. }
  108. r = *sql << "SELECT count(*) FROM dns WHERE status=?" << sid << cppdb::row;
  109. r >> c.count;
  110. c.page_size = items_per_page;
  111. c.pages = (c.count+items_per_page-1)/items_per_page;
  112. render("mainskin", "domain_list", c);
  113. }
  114. void undecided() { list(Domain::undecided); }
  115. void accepted() { list(Domain::accepted ); }
  116. void blocked() { list(Domain::blocked ); }
  117. app(cppcms::service &s): cppcms::application(s), items_per_page(50) {
  118. #ifdef DEBUGGIN
  119. std::cerr << "spawning app object" << std::endl;
  120. #endif
  121. sql.reset(new cppdb::session());
  122. sql->open(settings().get<std::string>("trafficctrl.db"));
  123. mapper().root(root_uri);
  124. mapper().assign("blocked", "/blocked");
  125. dispatcher().assign("/blocked/?", &app::blocked, this);
  126. mapper().assign("accepted", "/accepted");
  127. dispatcher().assign("/accepted/?", &app::accepted, this);
  128. mapper().assign("");
  129. dispatcher().assign("/?", &app::undecided, this);
  130. }
  131. // logging
  132. void main(const std::string url) {
  133. #ifdef DEBUGGIN
  134. std::cerr << "request: " << url << '\n'
  135. << " INFO: " << request().path_info() << '\n'
  136. << " SCRIPT: " << request().script_name() << '\n'
  137. << std::endl;
  138. #endif
  139. cppcms::application::main(url);
  140. }
  141. };
  142. //////////////////////////////////////////////////////////////////////
  143. // main() - Launch C++CMS with my test app on "/"
  144. //////////////////////////////////////////////////////////////////////
  145. int main(int argc, char **args) {
  146. // create server object
  147. cppcms::service srv(argc, args);
  148. // Get root URI from configuration file.
  149. root_uri = srv.settings().get("trafficctrl.root_uri", "");
  150. // Mount our app in the server
  151. srv.applications_pool().mount(
  152. cppcms::create_pool<app>(),
  153. cppcms::mount_point(root_uri)
  154. );
  155. // Serve it!
  156. // TODO: log crashes.
  157. #ifdef DEBUGGIN
  158. std::cerr << "Launching" << std::endl;
  159. #endif
  160. srv.run();
  161. return 0;
  162. }