X-Git-Url: https://git.sesse.net/?p=cubemap;a=blobdiff_plain;f=config.cpp;h=47118b48612e18bce0966c7bb696326532cf277e;hp=15fe88e5638b0dd79a84ff594ea5117e76b58c95;hb=16a03b9858752fae9e81af261821a2a22855fde3;hpb=36b82fe4368ddf2922e24fbf79c11034e32e946f diff --git a/config.cpp b/config.cpp index 15fe88e..47118b4 100644 --- a/config.cpp +++ b/config.cpp @@ -12,6 +12,8 @@ #include #include +#include "tlse.h" + #include "acceptor.h" #include "config.h" #include "log.h" @@ -174,6 +176,104 @@ bool fetch_config_int(const vector &config, const string &keyword, i return false; } +bool load_file_to_string(const string &filename, size_t max_size, string *contents) +{ + contents->clear(); + + FILE *fp = fopen(filename.c_str(), "r"); + if (fp == NULL) { + log_perror(filename.c_str()); + return false; + } + + char buf[4096]; + while (!feof(fp)) { + size_t ret = fread(buf, 1, sizeof(buf), fp); + if (ret > 0) { + contents->append(buf, buf + ret); + } else { + if (ferror(fp)) { + log_perror(filename.c_str()); + fclose(fp); + return false; + } + assert(feof(fp)); + break; + } + + if (contents->size() > max_size) { + log(ERROR, "%s was longer than the maximum allowed %zu bytes", filename.c_str(), max_size); + fclose(fp); + return false; + } + } + fclose(fp); + return true; +} + +bool parse_tls_parameters(const map ¶meters, AcceptorConfig *acceptor) +{ + bool has_cert = false, has_key = false; + + map::const_iterator tls_cert_it = parameters.find("tls_cert"); + if (tls_cert_it != parameters.end()) { + if (!load_file_to_string(tls_cert_it->second, 1048576, &acceptor->certificate_chain)) { + return false; + } + + // Verify that the certificate is valid. + bool is_server = true; + TLSContext *server_context = tls_create_context(is_server, TLS_V12); + int num_cert = tls_load_certificates( + server_context, + reinterpret_cast(acceptor->certificate_chain.data()), + acceptor->certificate_chain.size()); + if (num_cert < 0) { + log_tls_error(tls_cert_it->second.c_str(), num_cert); + tls_destroy_context(server_context); + return false; + } else if (num_cert == 0) { + log(ERROR, "%s did not contain any certificates", tls_cert_it->second.c_str()); + return false; + } + tls_destroy_context(server_context); + has_cert = true; + } + + map::const_iterator tls_key_it = parameters.find("tls_key"); + if (tls_key_it != parameters.end()) { + if (!load_file_to_string(tls_key_it->second, 1048576, &acceptor->private_key)) { + return false; + } + + // Verify that the key is valid. + bool is_server = true; + TLSContext *server_context = tls_create_context(is_server, TLS_V12); + int num_keys = tls_load_private_key( + server_context, + reinterpret_cast(acceptor->private_key.data()), + acceptor->private_key.size()); + if (num_keys < 0) { + log_tls_error(tls_key_it->second.c_str(), num_keys); + tls_destroy_context(server_context); + return false; + } else if (num_keys == 0) { + log(ERROR, "%s did not contain any private keys", tls_key_it->second.c_str()); + return false; + } + tls_destroy_context(server_context); + has_key = true; + } + + if (has_cert != has_key) { + log(ERROR, "Only one of tls_cert= and tls_key= was given, needs zero or both"); + return false; + } + + return true; +} + + bool parse_port(const ConfigLine &line, Config *config) { if (line.arguments.size() != 1) { @@ -190,6 +290,9 @@ bool parse_port(const ConfigLine &line, Config *config) AcceptorConfig acceptor; acceptor.addr = create_any_address(port); + if (!parse_tls_parameters(line.parameters, &acceptor)) { + return false; + } config->acceptors.push_back(acceptor); return true; } @@ -205,6 +308,9 @@ bool parse_listen(const ConfigLine &line, Config *config) if (!parse_hostport(line.arguments[0], &acceptor.addr)) { return false; } + if (!parse_tls_parameters(line.parameters, &acceptor)) { + return false; + } config->acceptors.push_back(acceptor); return true; } @@ -330,18 +436,6 @@ bool parse_udpstream(const ConfigLine &line, Config *config) } } - // Parse input encoding. - map::const_iterator src_encoding_parm_it = line.parameters.find("src_encoding"); - if (src_encoding_parm_it == line.parameters.end() || - src_encoding_parm_it->second == "metacube") { - udpstream.src_encoding = StreamConfig::STREAM_ENCODING_METACUBE; - } else if (src_encoding_parm_it->second == "raw") { - udpstream.src_encoding = StreamConfig::STREAM_ENCODING_RAW; - } else { - log(ERROR, "Parameter 'src_encoding' must be either 'raw' or 'metacube' (default)"); - return false; - } - config->udpstreams.push_back(udpstream); return true; }