121 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			121 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| //
 | |
| // Created by WolverinDEV on 28/04/2020.
 | |
| //
 | |
| 
 | |
| #include <netinet/in.h>
 | |
| #include "LocalFileProvider.h"
 | |
| 
 | |
| using namespace ts::server;
 | |
| using LocalFileServer = file::LocalFileProvider;
 | |
| 
 | |
| EVP_PKEY* ssl_generate_key() {
 | |
|     auto key = std::unique_ptr<EVP_PKEY, decltype(&EVP_PKEY_free)>(EVP_PKEY_new(), ::EVP_PKEY_free);
 | |
| 
 | |
|     auto rsa = RSA_new();
 | |
|     auto e = std::unique_ptr<BIGNUM, decltype(&BN_free)>(BN_new(), ::BN_free);
 | |
|     BN_set_word(e.get(), RSA_F4);
 | |
|     if(!RSA_generate_key_ex(rsa, 2048, e.get(), nullptr)) return nullptr;
 | |
|     EVP_PKEY_assign_RSA(key.get(), rsa);
 | |
|     return key.release();
 | |
| }
 | |
| 
 | |
| X509* ssl_generate_certificate(EVP_PKEY* key) {
 | |
|     auto cert = X509_new();
 | |
|     X509_set_pubkey(cert, key);
 | |
| 
 | |
|     ASN1_INTEGER_set(X509_get_serialNumber(cert), 3);
 | |
|     X509_gmtime_adj(X509_get_notBefore(cert), 0);
 | |
|     X509_gmtime_adj(X509_get_notAfter(cert), 31536000L);
 | |
| 
 | |
|     X509_NAME* name = nullptr;
 | |
|     name = X509_get_subject_name(cert);
 | |
|     //for(const auto& subject : this->subjects)
 | |
|     //    X509_NAME_add_entry_by_txt(name, subject.first.c_str(),  MBSTRING_ASC, (unsigned char *) subject.second.c_str(), subject.second.length(), -1, 0);
 | |
|     X509_set_subject_name(cert, name);
 | |
| 
 | |
|     name = X509_get_issuer_name(cert);
 | |
|     //for(const auto& subject : this->issues)
 | |
|     //    X509_NAME_add_entry_by_txt(name, subject.first.c_str(),  MBSTRING_ASC, (unsigned char *) subject.second.c_str(), subject.second.length(), -1, 0);
 | |
| 
 | |
|     X509_set_issuer_name(cert, name);
 | |
| 
 | |
|     X509_sign(cert, key, EVP_sha512());
 | |
|     return cert;
 | |
| }
 | |
| 
 | |
| std::shared_ptr<LocalFileServer> server_instance{};
 | |
| bool file::initialize(std::string &error) {
 | |
|     server_instance = std::make_shared<LocalFileProvider>();
 | |
| 
 | |
|     auto options = std::make_shared<pipes::SSL::Options>();
 | |
|     options->verbose_io = true;
 | |
|     options->context_method = SSLv23_method();
 | |
|     options->free_unused_keypairs = false;
 | |
| 
 | |
|     {
 | |
|         std::shared_ptr<EVP_PKEY> pkey{ssl_generate_key(), ::EVP_PKEY_free};
 | |
|         std::shared_ptr<X509> cert{ssl_generate_certificate(&*pkey), ::X509_free};
 | |
| 
 | |
|         options->default_keypair({pkey, cert});
 | |
|     }
 | |
| 
 | |
|     if(!server_instance->initialize(error, options)) {
 | |
|         server_instance = nullptr;
 | |
|         return false;
 | |
|     }
 | |
|     return true;
 | |
| }
 | |
| 
 | |
| void file::finalize() {
 | |
|     auto server = std::exchange(server_instance, nullptr);
 | |
|     if(!server) return;
 | |
| 
 | |
|     server->finalize();
 | |
| }
 | |
| 
 | |
| std::shared_ptr<file::AbstractFileServer> file::server() {
 | |
|     return server_instance;
 | |
| }
 | |
| 
 | |
| LocalFileServer::LocalFileProvider() : file_system_{}, file_transfer_{this->file_system_} {}
 | |
| LocalFileServer::~LocalFileProvider() {}
 | |
| 
 | |
| bool LocalFileServer::initialize(std::string &error, const std::shared_ptr<pipes::SSL::Options>& ssl_options) {
 | |
|     if(!this->file_system_.initialize(error, "file-root/"))
 | |
|         return false;
 | |
| 
 | |
| 
 | |
|     std::deque<std::shared_ptr<transfer::NetworkBinding>> bindings{};
 | |
|     {
 | |
|         auto binding = std::make_shared<transfer::NetworkBinding>();
 | |
| 
 | |
|         binding->hostname = "localhost";
 | |
| 
 | |
|         auto& iaddr = *(sockaddr_in*) &binding->address;
 | |
|         iaddr.sin_family = AF_INET;
 | |
|         iaddr.sin_port = htons(1112);
 | |
|         iaddr.sin_addr.s_addr = INADDR_ANY;
 | |
| 
 | |
|         bindings.push_back(std::move(binding));
 | |
|     }
 | |
| 
 | |
|     if(!this->file_transfer_.start(bindings, ssl_options)) {
 | |
|         error = "transfer server startup failed";
 | |
|         this->file_system_.finalize();
 | |
|         return false;
 | |
|     }
 | |
|     return true;
 | |
| }
 | |
| 
 | |
| void LocalFileServer::finalize() {
 | |
|     this->file_transfer_.stop();
 | |
|     this->file_system_.finalize();
 | |
| }
 | |
| 
 | |
| file::filesystem::AbstractProvider &LocalFileServer::file_system() {
 | |
|     return this->file_system_;
 | |
| }
 | |
| 
 | |
| file::transfer::AbstractProvider & LocalFileServer::file_transfer() {
 | |
|     return this->file_transfer_;
 | |
| } |