#include <utility>
#include <vector>
+#include "tlse.h"
+
#include "acceptor.h"
#include "config.h"
#include "log.h"
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<string, string> ¶meters, AcceptorConfig *acceptor)
+{
+ bool has_cert = false, has_key = false;
+
+ map<string, string>::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<const unsigned char *>(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<string, string>::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<const unsigned char *>(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) {
AcceptorConfig acceptor;
acceptor.addr = create_any_address(port);
+ if (!parse_tls_parameters(line.parameters, &acceptor)) {
+ return false;
+ }
config->acceptors.push_back(acceptor);
return true;
}
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;
}
}
}
- // Parse input encoding.
- map<string, string>::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;
}