+ 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 unordered_map<string, string> ¶meters, AcceptorConfig *acceptor)
+{
+ bool has_cert = false, has_key = false;
+
+ auto 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;
+ }
+
+ auto 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");