commit e5078b49692c7a91d64cc63ee8ac19e6594ad573 Author: groche97 Date: Fri May 8 12:43:46 2020 +0200 first commit, base server diff --git a/ServidorTFG.pro b/ServidorTFG.pro new file mode 100644 index 0000000..bab0040 --- /dev/null +++ b/ServidorTFG.pro @@ -0,0 +1,29 @@ +TEMPLATE = app +CONFIG += console c++11 +CONFIG -= app_bundle +CONFIG -= qt +LIBS += -lcrypto -lssl -pthread -lcppunit -lmysqlcppconn +SOURCES += \ + main.cpp \ + conexion.cpp \ + conexion_ssl.cpp \ + thread_selector.cpp \ + config_reader.cpp \ + tests.cpp \ + data_acces.cpp \ + msql_acces.cpp \ + session_manager.cpp \ + session_manager_ssl.cpp \ + config_package.cpp + +HEADERS += \ + conexion.h \ + conexion_ssl.h \ + thread_selector.h \ + config_reader.h \ + tests.h \ + data_acces.h \ + msql_acces.h \ + session_manager.h \ + session_manager_ssl.h \ + config_package.h diff --git a/ServidorTFG.pro.user b/ServidorTFG.pro.user new file mode 100644 index 0000000..912c629 --- /dev/null +++ b/ServidorTFG.pro.user @@ -0,0 +1,292 @@ + + + + + + EnvironmentId + {6372de0b-6c3f-4b3a-9367-dde6c2574520} + + + ProjectExplorer.Project.ActiveTarget + 0 + + + ProjectExplorer.Project.EditorSettings + + true + false + true + + Cpp + + CppGlobal + + + + QmlJS + + QmlJSGlobal + + + 2 + UTF-8 + false + 4 + false + 80 + true + true + 1 + true + false + 0 + true + true + 0 + 8 + true + 1 + true + true + true + false + + + + ProjectExplorer.Project.PluginSettings + + + true + + + + ProjectExplorer.Project.Target.0 + + Desktop + Desktop + {dd182432-2a2f-4b92-8ddc-d07764586196} + 0 + 0 + 0 + + /home/roche/Cosas/C++/build-ServidorTFG-Desktop-Debug + + + true + qmake + + QtProjectManager.QMakeBuildStep + true + + false + false + false + + + true + Make + + Qt4ProjectManager.MakeStep + + false + + + false + + 2 + Build + + ProjectExplorer.BuildSteps.Build + + + + true + Make + + Qt4ProjectManager.MakeStep + + true + clean + + false + + 1 + Clean + + ProjectExplorer.BuildSteps.Clean + + 2 + false + + Debug + Debug + Qt4ProjectManager.Qt4BuildConfiguration + 2 + true + + + /home/roche/Cosas/C++/build-ServidorTFG-Desktop-Release + + + true + qmake + + QtProjectManager.QMakeBuildStep + false + + false + false + true + + + true + Make + + Qt4ProjectManager.MakeStep + + false + + + false + + 2 + Build + + ProjectExplorer.BuildSteps.Build + + + + true + Make + + Qt4ProjectManager.MakeStep + + true + clean + + false + + 1 + Clean + + ProjectExplorer.BuildSteps.Clean + + 2 + false + + Release + Release + Qt4ProjectManager.Qt4BuildConfiguration + 0 + true + + + /home/roche/Cosas/C++/build-ServidorTFG-Desktop-Profile + + + true + qmake + + QtProjectManager.QMakeBuildStep + true + + false + true + true + + + true + Make + + Qt4ProjectManager.MakeStep + + false + + + false + + 2 + Build + + ProjectExplorer.BuildSteps.Build + + + + true + Make + + Qt4ProjectManager.MakeStep + + true + clean + + false + + 1 + Clean + + ProjectExplorer.BuildSteps.Clean + + 2 + false + + Profile + Profile + Qt4ProjectManager.Qt4BuildConfiguration + 0 + true + + 3 + + + 0 + Deploy + + ProjectExplorer.BuildSteps.Deploy + + 1 + Deploy Configuration + + ProjectExplorer.DefaultDeployConfiguration + + 1 + + + false + false + 1000 + + true + 2 + + ServidorTFG + + Qt4ProjectManager.Qt4RunConfiguration:/home/roche/Cosas/C++/ServidorTFG/ServidorTFG.pro + ServidorTFG.pro + + 3768 + false + true + true + false + false + true + + /home/roche/Cosas/C++/build-ServidorTFG-Desktop-Debug + + 1 + + + + ProjectExplorer.Project.TargetCount + 1 + + + ProjectExplorer.Project.Updater.FileVersion + 20 + + + Version + 20 + + diff --git a/conexion.cpp b/conexion.cpp new file mode 100644 index 0000000..7fc9da0 --- /dev/null +++ b/conexion.cpp @@ -0,0 +1,82 @@ +#include "conexion.h" +#include "session_manager.h" +#include "msql_acces.h" + +#include +#include +#include + +void conexion_client(int client); + +conexion::conexion(config_reader &config) +{ + this->config=&config; + this->data=new msql_acces(); +} + +int conexion::create_socket(int port) +{ + int s; + struct sockaddr_in addr; + + addr.sin_family = AF_INET; + addr.sin_port = htons(port); + addr.sin_addr.s_addr = htonl(INADDR_ANY); + + s = socket(AF_INET, SOCK_STREAM, 0); + if (s < 0) { + perror("Unable to create socket"); + exit(EXIT_FAILURE); + } + + if (bind(s, (struct sockaddr*)&addr, sizeof(addr)) < 0) { + perror("Unable to bind"); + exit(EXIT_FAILURE); + } + + if (listen(s, 1) < 0) { + perror("Unable to listen"); + exit(EXIT_FAILURE); + } + + return s; +} + +void conexion::start_server(){ + int sock; + string port; + if(!this->config->get_param("port", port)){ + perror("bad port in config file"); + } + sock = this->create_socket(atoi(port.data())); + + while(1) { + struct sockaddr_in addr; + uint len = sizeof(addr); + int client = accept(sock, (struct sockaddr*)&addr, &len); + std::thread t_client(conexion_client , client); + t_client.detach(); + //cont++; + } + close(sock); +} + +bool conexion::check_pass(std::string username, std::string passwd){ + return passwd==this->data->get_passwd(username); +} + + +void conexion_client(int client){ + char buf [256]; + + if (client < 0) { + perror("Unable to accept"); + exit(EXIT_FAILURE); + }else{ + session_manager* session = new session_manager(client); + while(session->validate_pass()); + session->execute(); + delete (session); + close(client); + } +} diff --git a/conexion.h b/conexion.h new file mode 100644 index 0000000..d2ad5cf --- /dev/null +++ b/conexion.h @@ -0,0 +1,18 @@ +#ifndef CONEXION_H +#define CONEXION_H +#include +#include "config_reader.h" +#include "data_acces.h" +using namespace std; +class conexion +{ +public: + conexion(config_reader &conf); + virtual void start_server(); + bool check_pass(std::string username, std::string passwd); +protected: + data_acces* data; + int create_socket(int port); + config_reader* config; +}; +#endif // CONEXION_H diff --git a/conexion_ssl.cpp b/conexion_ssl.cpp new file mode 100644 index 0000000..aade996 --- /dev/null +++ b/conexion_ssl.cpp @@ -0,0 +1,133 @@ +#include "conexion_ssl.h" +#include "session_manager.h" +#include "session_manager_ssl.h" +#include "config_reader.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +void init_openssl(); +void cleanup_openssl(); +SSL_CTX *create_context(); +void conexion_client(SSL_CTX *ctx,int client); + +conexion_ssl::conexion_ssl(config_reader &conf):conexion(conf) +{ + +} + +void conexion_ssl::start_server(){ + int sock; + string port; + if(!this->config->get_param("port", port)){ + perror("bad port in config file"); + } + sock = this->create_socket(atoi(port.data())); + /* Handle connections */ + SSL_CTX *ctx; + + init_openssl(); + ctx = create_context(); + + this->configure_context(ctx); + + //std::thread *hilos=new thread[50]; + //int cont=0; + while(1) { + struct sockaddr_in addr; + uint len = sizeof(addr); + int client = accept(sock, (struct sockaddr*)&addr, &len); + std::thread t_client(conexion_client,ctx , client); + t_client.detach(); + //cont++; + } + close(sock); + SSL_CTX_free(ctx); + cleanup_openssl(); +} + +void init_openssl() +{ + SSL_load_error_strings(); + OpenSSL_add_ssl_algorithms(); +} + +void cleanup_openssl() +{ + EVP_cleanup(); +} + +SSL_CTX* conexion_ssl::create_context() +{ + const SSL_METHOD *method; + SSL_CTX *ctx; + + method = SSLv23_server_method(); + + ctx = SSL_CTX_new(method); + if (!ctx) { + perror("Unable to create SSL context"); + ERR_print_errors_fp(stderr); + exit(EXIT_FAILURE); + } + + return ctx; +} + +void conexion_ssl::configure_context(SSL_CTX *ctx) +{ + SSL_CTX_set_ecdh_auto(ctx, 1); + + /* Set the key and cert */ + + string cert; + if(!this->config->get_param("cert", cert)){ + perror("bad cert in config file"); + } + if (SSL_CTX_use_certificate_file(ctx, cert.data(), SSL_FILETYPE_PEM) <= 0) { + ERR_print_errors_fp(stderr); + exit(EXIT_FAILURE); + } + + string key; + if(!this->config->get_param("key", key)){ + perror("bad key in config file"); + } + if (SSL_CTX_use_PrivateKey_file(ctx, key.data(), SSL_FILETYPE_PEM) <= 0 ) { + ERR_print_errors_fp(stderr); + exit(EXIT_FAILURE); + } +} + +void conexion_client(SSL_CTX *ctx,int client){ + char buf [256]; + + if (client < 0) { + perror("Unable to accept"); + exit(EXIT_FAILURE); + }else{ + SSL *ssl; + ssl = SSL_new(ctx); + SSL_set_fd(ssl, client); + + if (SSL_accept(ssl) <= 0) { + ERR_print_errors_fp(stderr); + } + else { + session_manager* session = new session_manager_ssl(ssl); + while(!session->validate_pass()); + session->execute(); + //SSL_write(ssl,std::to_string(la->execute()).data() , sizeof (int)); + delete (session); + } + SSL_shutdown(ssl); + SSL_free(ssl); + close(client); + } +} diff --git a/conexion_ssl.h b/conexion_ssl.h new file mode 100644 index 0000000..986e8dd --- /dev/null +++ b/conexion_ssl.h @@ -0,0 +1,19 @@ +#ifndef CONEXION_SSL_H +#define CONEXION_SSL_H +#include "conexion.h" + +#include + +class conexion_ssl : public conexion +{ +public: + conexion_ssl(config_reader &conf); + void start_server(); +private: + /*void init_openssl(); + void cleanup_openssl();*/ + SSL_CTX *create_context(); + void configure_context(SSL_CTX *ctx); +}; + +#endif // CONEXION_SSL_H diff --git a/config_package.cpp b/config_package.cpp new file mode 100644 index 0000000..7784f1b --- /dev/null +++ b/config_package.cpp @@ -0,0 +1,19 @@ +#include "config_package.h" + +config_package::config_package(std::string name) : name(name){ + this->file = std::fstream("/etc/portage/package.use/"+name, std::ifstream::in); + + for(std::string line; std::getline(this->file, line);){ + this->uses+=line+"\n"; + } + this->file.close(); +} + +void config_package::change_uses(std::string remote_uses){ + if(remote_uses!=this->uses){ + this->file=std::fstream("/etc/portage/package.use/"+name, std::ofstream::out); + this->file << remote_uses; + this->file.close(); + } +} + diff --git a/config_package.h b/config_package.h new file mode 100644 index 0000000..a5bb890 --- /dev/null +++ b/config_package.h @@ -0,0 +1,17 @@ +#ifndef CONFIG_PACKAGE_H +#define CONFIG_PACKAGE_H +#include +#include + +class config_package +{ +public: + config_package(std::string name); + void change_uses(std::string remote_uses); +private: + std::string name; + std::string uses; + std::fstream file; +}; + +#endif // CONFIG_PACKAGE_H diff --git a/config_reader.cpp b/config_reader.cpp new file mode 100644 index 0000000..0201b8e --- /dev/null +++ b/config_reader.cpp @@ -0,0 +1,27 @@ +#include "config_reader.h" +#include +config_reader::config_reader(std::string dir) +{ + this->file.open(dir, std::ios::in); + std::string prueba; + std::getline(file, prueba); +} + +bool config_reader::get_param(std::string variable, std::string &value){ + this->file.clear(); + this->file.seekg(0, file.beg); + std::string line; + while(std::getline(file, line)){ + std::string no_coment=line.substr(0,line.find("#")); + std::size_t found=no_coment.find(variable); + if(found!=std::string::npos){ + no_coment=no_coment.substr(found+variable.length(), no_coment.length()); + found=no_coment.find("="); + if(found!=std::string::npos){ + value=no_coment.substr(found+1, no_coment.length()); + return true; + } + } + } + return false; +} diff --git a/config_reader.h b/config_reader.h new file mode 100644 index 0000000..ab5b8d6 --- /dev/null +++ b/config_reader.h @@ -0,0 +1,15 @@ +#ifndef CONFIG_READER_H +#define CONFIG_READER_H +#include +#include + +class config_reader +{ +public: + config_reader(std::string); + bool get_param(std::string variable, std::string &value); +private: + std::ifstream file; +}; + +#endif // CONFIG_READER_H diff --git a/data_acces.cpp b/data_acces.cpp new file mode 100644 index 0000000..a5e8533 --- /dev/null +++ b/data_acces.cpp @@ -0,0 +1,6 @@ +#include "data_acces.h" + +data_acces::data_acces() +{ + +} diff --git a/data_acces.h b/data_acces.h new file mode 100644 index 0000000..682c2a4 --- /dev/null +++ b/data_acces.h @@ -0,0 +1,13 @@ +#ifndef DATA_ACCES_H +#define DATA_ACCES_H + +#include + +class data_acces +{ +public: + data_acces(); + virtual std::string get_passwd(std::string username) = 0; +}; + +#endif // DATA_ACCES_H diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..7cb40cf --- /dev/null +++ b/main.cpp @@ -0,0 +1,41 @@ +#include +#include + +#include "conexion.h" +#include "conexion_ssl.h" +#include "config_reader.h" +#include "tests.h" + +#define file_config "config" +CPPUNIT_TEST_SUITE_REGISTRATION( test_basic ); +int main() +{ + //inicio de los tests + CPPUNIT_NS::TestResult testresult; + CPPUNIT_NS::TestResultCollector collectedresults; + testresult.addListener (&collectedresults); + CPPUNIT_NS::BriefTestProgressListener progress; + testresult.addListener (&progress); + CPPUNIT_NS::TestRunner testrunner; + testrunner.addTest (CPPUNIT_NS::TestFactoryRegistry::getRegistry().makeTest ()); + testrunner.run(testresult); + CPPUNIT_NS::CompilerOutputter compileroutputter(&collectedresults, std::cerr); + compileroutputter.write (); + + config_reader conf = config_reader(file_config); + string option; + if(conf.get_param("security",option)){ + conexion *con=nullptr; + if(option=="yes"){ + con = new conexion_ssl(conf); + }else if(option=="no"){ + con = new conexion(conf); + }else{ + perror("unknow option in security option"); + } + con->start_server(); + }else{ + perror("no define security option"); + } + return 0; +} diff --git a/msql_acces.cpp b/msql_acces.cpp new file mode 100644 index 0000000..d745bed --- /dev/null +++ b/msql_acces.cpp @@ -0,0 +1,20 @@ +#include "msql_acces.h" +#include +msql_acces::msql_acces() +{ + driver = get_driver_instance(); + con = driver->connect("tcp://127.0.0.1:3306", "root", "1234"); + con->setSchema("bin_database"); +} + + +std::string msql_acces::get_passwd(std::string username){ + sql::PreparedStatement *pstmt = con->prepareStatement("select passwd from users where username=?"); + pstmt->setString(1,username); + sql::ResultSet *res = pstmt->executeQuery(); + std::string ret; + while(res->next()) + ret = res->getString("passwd"); + delete res; + return ret; +} diff --git a/msql_acces.h b/msql_acces.h new file mode 100644 index 0000000..6dcba2b --- /dev/null +++ b/msql_acces.h @@ -0,0 +1,21 @@ +#ifndef MSQL_ACCES_H +#define MSQL_ACCES_H +#include "data_acces.h" + +#include +#include +#include +#include +#include + +class msql_acces : public data_acces +{ +public: + msql_acces(); + std::string get_passwd(std::string username); +private: + sql::Connection *con; + sql::Driver *driver; +}; + +#endif // MSQL_ACCES_H diff --git a/session_manager.cpp b/session_manager.cpp new file mode 100644 index 0000000..f2af2b4 --- /dev/null +++ b/session_manager.cpp @@ -0,0 +1,81 @@ +#include "session_manager.h" +#include "msql_acces.h" + +#include +#include +#include +#include + +session_manager::session_manager(int fd) +{ + this->fd=fd; + this->data=new msql_acces(); +} + +bool session_manager::validate_pass(){ + char* buffer = new char[256]; + this->read_data(buffer, 256); + std::string user=buffer; + this->read_data(buffer, 256); + std::string pass=buffer; + if(this->data->get_passwd(user)==pass){ + this->write_data("pass"); + return true; + }else{ + this->write_data("fail"); + return false; + } +} + +void session_manager::start_dialog(){ + char* buffer = new char[5]; + while(true){ + this->read_data(buffer,5); + if(strcmp(buffer, "exec")==0){ + this->execute(); + }else if(strcmp(buffer, "info")==0){ + this->send_information(); + }else if(strcmp(buffer,"exit")){ + break; + } + } +} + +int session_manager::execute(){ + char* n_package = new char[256]; + this->read_data(n_package, 256); + this->args=new char*[4]; + this->args[0]="emerge"; + this->args[1]="--ask"; + this->args[2]=n_package; + this->args[3]=nullptr; + int pid = fork(); + int status=-2; + if(pid==0){ + if(execvp(this->args[0],this->args)==-1){ + std::cout << "error inesperado" << std::endl; + } + exit(0); + }else { + waitpid(pid, &status, WCONTINUED); + if(status>0){ + this->write_data("ok"); + }else{ + this->write_data("bad"); + } + } + delete[] (n_package); + return status; +} + +void session_manager::send_information(){ + +} + +int session_manager::read_data(char* input, int size){ + return read(this->fd, input, size); +} + +int session_manager::write_data(std::string output){ + return write(this->fd, output.data(), output.size()); +} diff --git a/session_manager.h b/session_manager.h new file mode 100644 index 0000000..9bb4b57 --- /dev/null +++ b/session_manager.h @@ -0,0 +1,21 @@ +#ifndef LAUNCHER_H +#define LAUNCHER_H +#include +#include +class session_manager +{ +public: + session_manager(int fd); + void start_dialog(); + int execute(); + void send_information(); + bool validate_pass(); + private: + virtual int read_data(char* input, int size); + virtual int write_data(std::string output); + int fd; + data_acces* data; + char** args; +}; + +#endif // LAUNCHER_H diff --git a/session_manager_ssl.cpp b/session_manager_ssl.cpp new file mode 100644 index 0000000..67ee1b8 --- /dev/null +++ b/session_manager_ssl.cpp @@ -0,0 +1,14 @@ +#include "session_manager_ssl.h" + +session_manager_ssl::session_manager_ssl(SSL* sfd):session_manager(-1) +{ + this->sfd=sfd; +} + +int session_manager_ssl::read_data(char* input, int size){ + return SSL_read(this->sfd, input, size); +} + +int session_manager_ssl::write_data(std::string output){ + return SSL_write(this->sfd, output.data(), output.size()); +} diff --git a/session_manager_ssl.h b/session_manager_ssl.h new file mode 100644 index 0000000..0b71217 --- /dev/null +++ b/session_manager_ssl.h @@ -0,0 +1,16 @@ +#ifndef SESSION_MANAGER_SSL_H +#define SESSION_MANAGER_SSL_H +#include +#include "session_manager.h" + +class session_manager_ssl : public session_manager +{ +public: + session_manager_ssl(SSL* fd); + int read_data(char* input, int size); + int write_data(std::string output); +private: + SSL* sfd; +}; + +#endif // SESSION_MANAGER_SSL_H diff --git a/tests.cpp b/tests.cpp new file mode 100644 index 0000000..861c506 --- /dev/null +++ b/tests.cpp @@ -0,0 +1,22 @@ +#include "tests.h" + +void test_basic::setUp(){ + this->conf=new config_reader("config"); +} + +void test_basic::testInitial(){ + std::string res; + CPPUNIT_ASSERT(true==this->conf->get_param("port",res)); + CPPUNIT_ASSERT("4433"==res); +} + +void test_basic::pass_tests(){ + CPPUNIT_NS::TestResult testresult; + CPPUNIT_NS::TestResultCollector collectedresults; + testresult.addListener (&collectedresults); + CPPUNIT_NS::BriefTestProgressListener progress; + testresult.addListener (&progress); + CPPUNIT_NS::TestRunner testrunner; + testrunner.addTest (CPPUNIT_NS::TestFactoryRegistry::getRegistry().makeTest ()); + testrunner.run(testresult); +} diff --git a/tests.h b/tests.h new file mode 100644 index 0000000..0e6397b --- /dev/null +++ b/tests.h @@ -0,0 +1,28 @@ +#ifndef TESTS_H +#define TESTS_H +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "config_reader.h" +using namespace CppUnit; + +class test_basic : public CppUnit::TestFixture{ + CPPUNIT_TEST_SUITE(test_basic); + CPPUNIT_TEST(testInitial); + CPPUNIT_TEST_SUITE_END(); +public: + void setUp(void); + void pass_tests(); +private: + void testInitial(void); + config_reader *conf; +}; +#endif // TESTS_H diff --git a/thread_selector.cpp b/thread_selector.cpp new file mode 100644 index 0000000..e040f3c --- /dev/null +++ b/thread_selector.cpp @@ -0,0 +1,6 @@ +#include "thread_selector.h" + +thread_selector::thread_selector() +{ + +} diff --git a/thread_selector.h b/thread_selector.h new file mode 100644 index 0000000..5f28858 --- /dev/null +++ b/thread_selector.h @@ -0,0 +1,15 @@ +#ifndef THREAD_SELECTOR_H +#define THREAD_SELECTOR_H +#include +#include + +class thread_selector +{ +public: + thread_selector(); +private: + std::queue t_pos; + std::thread* list; +}; + +#endif // THREAD_SELECTOR_H