Ver Fonte

Merge branch '6-us08-daemon-can-react-to-simple-commands'

Resolve "US08: Daemon can react to simple commands"

Closes #6

See merge request tobias.wach/ccats!4
anon há 5 anos atrás
pai
commit
2c17f4587f
3 ficheiros alterados com 277 adições e 7 exclusões
  1. 3 1
      daemon/CMakeLists.txt
  2. 35 0
      daemon/include/Server.h
  3. 239 6
      daemon/src/Server.cpp

+ 3 - 1
daemon/CMakeLists.txt

@@ -10,10 +10,12 @@ add_executable(ccats src/main.cpp src/Sniffer.cpp src/Server.cpp)
 # use pkg-config to fix building on debian unstable
 find_package(PkgConfig REQUIRED)
 pkg_check_modules(TINS REQUIRED libtins>=4.2 libpcap)
+pkg_check_modules(JSONCPP REQUIRED jsoncpp)
+
 
 find_package(Threads REQUIRED)
 find_package(Boost 1.67 REQUIRED COMPONENTS system)
 # find_package(libtins 4.2 REQUIRED)
 
 include_directories(${Boost_INCLUDE_DIR})
-target_link_libraries(ccats PRIVATE ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES} ${TINS_LIBRARIES} ${PCAP_LIBRARIES})
+target_link_libraries(ccats PRIVATE ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES} ${TINS_LIBRARIES} ${PCAP_LIBRARIES} ${JSONCPP_LIBRARIES})

+ 35 - 0
daemon/include/Server.h

@@ -20,6 +20,8 @@ private:
   tcp::socket sock;
   const std::string message = "Hello From Server!";
 
+  const std::string protocolVersion = "0.1";
+
   /**
    * max buffer length
    */
@@ -89,6 +91,39 @@ public:
   void handle_read(const boost::system::error_code &err,
                    size_t bytes_transferred);
 
+  /**
+   * Read handler
+   *
+   * Will be called if the server expected a version and received something.
+   *
+   * @param err error
+   * @param bytes_transferred amount of transferred bytes
+   */
+  void handle_read_version(const boost::system::error_code &err,
+                           size_t bytes_transferred);
+
+  /**
+   * Read handler
+   *
+   * Will be called after the version was verifyed. Checks login data.
+   *
+   * @param err error
+   * @param bytes_transferred amount of transferred bytes
+   */
+  void handle_read_login(const boost::system::error_code &err,
+                         size_t bytes_transferred);
+
+  /**
+   * Read handler
+   *
+   * Will be called after the version and login was verifyed. Executes commands.
+   *
+   * @param err error
+   * @param bytes_transferred amount of transferred bytes
+   */
+  void handle_read_command(const boost::system::error_code &err,
+                           size_t bytes_transferred);
+
   /**
    * Write handler
    *

+ 239 - 6
daemon/src/Server.cpp

@@ -1,5 +1,6 @@
 #include "../include/Server.h"
 #include <iostream>
+#include <jsoncpp/json/json.h>
 
 using namespace boost::asio;
 using ip::tcp;
@@ -22,15 +23,11 @@ con_handler::create(basic_socket_acceptor<ip::tcp>::executor_type &io_service) {
 tcp::socket &con_handler::socket() { return sock; }
 
 void con_handler::start() {
+
   sock.async_read_some(buffer(data, max_length),
-                       boost::bind(&con_handler::handle_read,
+                       boost::bind(&con_handler::handle_read_version,
                                    shared_from_this(), placeholders::error,
                                    placeholders::bytes_transferred));
-
-  sock.async_write_some(buffer(message, max_length),
-                        boost::bind(&con_handler::handle_write,
-                                    shared_from_this(), placeholders::error,
-                                    placeholders::bytes_transferred));
 }
 
 void con_handler::handle_read(const boost::system::error_code &err,
@@ -43,6 +40,242 @@ void con_handler::handle_read(const boost::system::error_code &err,
   }
 }
 
+void con_handler::handle_read_version(const boost::system::error_code &err,
+                                      size_t bytes_transferred) {
+  if (!err) {
+    // set up json stuff
+    JSONCPP_STRING err;
+    Json::Value root;
+    Json::CharReaderBuilder builder;
+    const std::unique_ptr<Json::CharReader> reader(builder.newCharReader());
+
+    // parse data
+    if (!reader->parse(this->data, this->data + bytes_transferred, &root,
+                       &err)) {
+      std::cerr << "Json error: " << err << std::endl << "data: " << this->data;
+      sock.close();
+    }
+
+    // create answer
+    Json::Value answer;
+    Json::StreamWriterBuilder stringBuilder;
+
+    answer["version"] = this->protocolVersion;
+
+    // check version string
+    if (root["version"].compare(this->protocolVersion) == 0) {
+      answer["accept"] = true;
+      const std::string answerString = Json::writeString(stringBuilder, answer);
+
+      // send answer
+      sock.async_write_some(buffer(answerString, max_length),
+                            boost::bind(&con_handler::handle_write,
+                                        shared_from_this(), placeholders::error,
+                                        placeholders::bytes_transferred));
+
+      // read next data
+      sock.async_read_some(buffer(data, max_length),
+                           boost::bind(&con_handler::handle_read_login,
+                                       shared_from_this(), placeholders::error,
+                                       placeholders::bytes_transferred));
+    } else {
+      answer["accept"] = false;
+      const std::string answerString = Json::writeString(stringBuilder, answer);
+
+      // send answer
+      sock.async_write_some(buffer(answerString, max_length),
+                            boost::bind(&con_handler::handle_write,
+                                        shared_from_this(), placeholders::error,
+                                        placeholders::bytes_transferred));
+      // close connection
+      sock.close();
+    }
+
+  } else {
+    std::cerr << "error: " << err.message() << std::endl;
+    sock.close();
+  }
+}
+
+void con_handler::handle_read_login(const boost::system::error_code &err,
+                                    size_t bytes_transferred) {
+  if (!err) {
+    // set up json stuff
+    JSONCPP_STRING err;
+    Json::Value root;
+    Json::CharReaderBuilder builder;
+    const std::unique_ptr<Json::CharReader> reader(builder.newCharReader());
+
+    // parse data
+    if (!reader->parse(this->data, this->data + bytes_transferred, &root,
+                       &err)) {
+      std::cerr << "Json error: " << err << std::endl << "data: " << this->data;
+      sock.close();
+    }
+
+    Json::Value answer;
+    Json::StreamWriterBuilder stringBuilder;
+
+    // user credentials
+    // TODO check user credentials!!!
+    if (root["user"].compare("user") == 0 &&
+        root["pass"].compare("pass") == 0) {
+      answer["accept"] = true;
+      const std::string answerString = Json::writeString(stringBuilder, answer);
+
+      // send answer
+      sock.async_write_some(buffer(answerString, max_length),
+                            boost::bind(&con_handler::handle_write,
+                                        shared_from_this(), placeholders::error,
+                                        placeholders::bytes_transferred));
+
+      // read next data
+      sock.async_read_some(buffer(data, max_length),
+                           boost::bind(&con_handler::handle_read_command,
+                                       shared_from_this(), placeholders::error,
+                                       placeholders::bytes_transferred));
+    } else {
+      answer["accept"] = false;
+      const std::string answerString = Json::writeString(stringBuilder, answer);
+
+      // send answer
+      sock.async_write_some(buffer(answerString, max_length),
+                            boost::bind(&con_handler::handle_write,
+                                        shared_from_this(), placeholders::error,
+                                        placeholders::bytes_transferred));
+      // close connection
+      sock.close();
+    }
+
+  } else {
+    std::cerr << "error: " << err.message() << std::endl;
+    sock.close();
+  }
+}
+
+void con_handler::handle_read_command(const boost::system::error_code &err,
+                                      size_t bytes_transferred) {
+  if (!err) {
+    // set up json stuff
+    JSONCPP_STRING err;
+    Json::Value root;
+    Json::CharReaderBuilder builder;
+    const std::unique_ptr<Json::CharReader> reader(builder.newCharReader());
+
+    // parse data
+    if (!reader->parse(this->data, this->data + bytes_transferred, &root,
+                       &err)) {
+      std::cerr << "Json error: " << err << std::endl << "data: " << this->data;
+      sock.close();
+    }
+
+    Json::Value answer;
+    Json::StreamWriterBuilder stringBuilder;
+
+    // check command
+    if (root["command"].compare("status") == 0) {
+      answer["command"] = "status";
+
+      // TODO answer a real status message
+      answer["response"] = "This is a status message :)";
+      const std::string answerString = Json::writeString(stringBuilder, answer);
+
+      // send answer
+      sock.async_write_some(buffer(answerString, max_length),
+                            boost::bind(&con_handler::handle_write,
+                                        shared_from_this(), placeholders::error,
+                                        placeholders::bytes_transferred));
+
+      // read next data
+      sock.async_read_some(buffer(data, max_length),
+                           boost::bind(&con_handler::handle_read_command,
+                                       shared_from_this(), placeholders::error,
+                                       placeholders::bytes_transferred));
+    } else if (root["command"].compare("list") == 0) {
+      answer["command"] = "list";
+
+      // TODO look for real data
+      Json::Value array;
+      array.append("some");
+      array.append("important");
+      array.append("data");
+      answer["names"] = array;
+      answer["remaining"] = 0;
+
+      const std::string answerString = Json::writeString(stringBuilder, answer);
+      // send answer
+      sock.async_write_some(buffer(answerString, max_length),
+                            boost::bind(&con_handler::handle_write,
+                                        shared_from_this(), placeholders::error,
+                                        placeholders::bytes_transferred));
+
+      // read next data
+      sock.async_read_some(buffer(data, max_length),
+                           boost::bind(&con_handler::handle_read_command,
+                                       shared_from_this(), placeholders::error,
+                                       placeholders::bytes_transferred));
+    } else if (root["command"].compare("put") == 0) {
+      answer["command"] = "put";
+
+      // TODO establish real connection and receive file
+      answer["accept"] = false;
+
+      const std::string answerString = Json::writeString(stringBuilder, answer);
+      // send answer
+      sock.async_write_some(buffer(answerString, max_length),
+                            boost::bind(&con_handler::handle_write,
+                                        shared_from_this(), placeholders::error,
+                                        placeholders::bytes_transferred));
+
+      // read next data
+      sock.async_read_some(buffer(data, max_length),
+                           boost::bind(&con_handler::handle_read_command,
+                                       shared_from_this(), placeholders::error,
+                                       placeholders::bytes_transferred));
+    } else if (root["command"].compare("get") == 0) {
+      answer["command"] = "get";
+
+      // TODO establish real connection and send file
+      answer["accept"] = false;
+
+      const std::string answerString = Json::writeString(stringBuilder, answer);
+      // send answer
+      sock.async_write_some(buffer(answerString, max_length),
+                            boost::bind(&con_handler::handle_write,
+                                        shared_from_this(), placeholders::error,
+                                        placeholders::bytes_transferred));
+
+      // read next data
+      sock.async_read_some(buffer(data, max_length),
+                           boost::bind(&con_handler::handle_read_command,
+                                       shared_from_this(), placeholders::error,
+                                       placeholders::bytes_transferred));
+    } else if (root["command"].compare("close") == 0) {
+      answer["command"] = "close";
+      answer["response"] = "bye";
+      const std::string answerString = Json::writeString(stringBuilder, answer);
+
+      // send answer
+      sock.async_write_some(buffer(answerString, max_length),
+                            boost::bind(&con_handler::handle_write,
+                                        shared_from_this(), placeholders::error,
+                                        placeholders::bytes_transferred));
+
+      // close connection
+      sock.close();
+    } else {
+      // TODO handle error
+
+      // close connection
+      sock.close();
+    }
+
+  } else {
+    std::cerr << "error: " << err.message() << std::endl;
+    sock.close();
+  }
+}
+
 void con_handler::handle_write(const boost::system::error_code &err,
                                size_t bytes_transferred) {
   if (!err) {