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.
 
 
 
 

201 lines
5.8 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 and block.
  9. //////////////////////////////////////////////////////////////////////
  10. // TODO: put the note fields to use (dns,dns_wild)
  11. // TODO: Any purpose in wild-card selection "accepted" host names?
  12. #include <stdlib.h>
  13. #include <string>
  14. #include <stdexcept>
  15. #include <iostream>
  16. /// C++CMS/DB ///
  17. #include <cppcms/service.h>
  18. #include <cppcms/applications_pool.h>
  19. #include <cppcms/mount_point.h>
  20. #include <cppcms/url_dispatcher.h>
  21. #include <cppcms/url_mapper.h>
  22. #include <cppcms/http_request.h>
  23. #include <cppcms/http_response.h>
  24. #include <cppdb/frontend.h>
  25. /// Our app ///
  26. #include "../strutil.h"
  27. #include "data.h"
  28. #include "nametools.h"
  29. /// Build flags ///
  30. // TODO: better application of C++CMS booster logging
  31. //#define DEBUGGIN
  32. //////////////////////////////////////////////////////////////////////
  33. // C++CMS App to manage the state of all known domain names.
  34. //////////////////////////////////////////////////////////////////////
  35. const std::string filter_titles[] = { "Undecided", "Accepted", "Blocked" };
  36. const std::string actions[] = { "Reset", "Accept", "Block" };
  37. std::string root_uri = "";
  38. struct app: public cppcms::application {
  39. std::auto_ptr<cppdb::session> sql;
  40. int items_per_page;
  41. std::string numlist(const std::string &field) {
  42. std::string r;
  43. const cppcms::http::request::form_type &POST = request().post();
  44. for(
  45. cppcms::http::request::form_type::const_iterator it = POST.find(field);
  46. it!=POST.end() && it->first==field;
  47. it++
  48. ) {
  49. if(it->second!="") {
  50. if(r!="") r+=",";
  51. r+="'"+sql->escape(it->second)+"'";
  52. }
  53. }
  54. return r;
  55. }
  56. void list(Domain::STATUS sid) {
  57. int i;
  58. std::string s;
  59. DomainList c;
  60. cppdb::result r;
  61. // TODO: put this someplace else?
  62. /// Form processing ///
  63. if(request().request_method()=="POST") {
  64. c.op = request().post("op");
  65. // nothing to do without a valid "op"
  66. if(c.op=="0" || c.op=="1" || c.op=="2") {
  67. // eliminate NOP busywork
  68. if((s=numlist("id"))!="" && sid!=atoi(c.op.c_str())) {
  69. *sql << "UPDATE dns SET status="+c.op+" WHERE name IN ("+s+")"
  70. << cppdb::exec;
  71. }
  72. if(s=="*" || s=="*.") {
  73. c.error = "'*' and '*.' are not acceptable.";
  74. } else if((s=request().post("domain"))!="") {
  75. // wild card handling
  76. if(s.substr(0,2)=="*.") {
  77. s = s.substr(2);
  78. if(c.op=="0")
  79. c.error = "Wild cards have no value with \"undecided\".";
  80. else
  81. *sql << "INSERT INTO dns_wild (name,status) VALUES (?,?)"
  82. << s << c.op
  83. << cppdb::exec;
  84. }
  85. // regardless move all existing matches to the specified status.
  86. *sql << "UPDATE dns SET status=? "
  87. "WHERE status=? AND (name=? OR name LIKE ?)"
  88. << c.op << sid << s << ("%."+s)
  89. << cppdb::exec;
  90. }
  91. }
  92. }
  93. /// Produce list of names of the desired STATUS ///
  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. }