summary refs log tree commit diff
path: root/synapse/crypto/config.py
diff options
context:
space:
mode:
Diffstat (limited to 'synapse/crypto/config.py')
-rw-r--r--synapse/crypto/config.py159
1 files changed, 159 insertions, 0 deletions
diff --git a/synapse/crypto/config.py b/synapse/crypto/config.py
new file mode 100644
index 0000000000..801dfd8656
--- /dev/null
+++ b/synapse/crypto/config.py
@@ -0,0 +1,159 @@
+# -*- coding: utf-8 -*-
+# Copyright 2014 matrix.org
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import ConfigParser as configparser
+import argparse
+import socket
+import sys
+import os
+from OpenSSL import crypto
+import nacl.signing
+from syutil.base64util import encode_base64
+import subprocess
+
+
+def load_config(description, argv):
+    config_parser = argparse.ArgumentParser(add_help=False)
+    config_parser.add_argument("-c", "--config-path", metavar="CONFIG_FILE",
+                               help="Specify config file")
+    config_args, remaining_args = config_parser.parse_known_args(argv)
+    if config_args.config_path:
+        config = configparser.SafeConfigParser()
+        config.read([config_args.config_path])
+        defaults = dict(config.items("KeyServer"))
+    else:
+        defaults = {}
+    parser = argparse.ArgumentParser(
+        parents=[config_parser],
+        description=description,
+        formatter_class=argparse.RawDescriptionHelpFormatter,
+    )
+    parser.set_defaults(**defaults)
+    parser.add_argument("--server-name", default=socket.getfqdn(),
+                        help="The name of the server")
+    parser.add_argument("--signing-key-path",
+                        help="The signing key to sign responses with")
+    parser.add_argument("--tls-certificate-path",
+                        help="PEM encoded X509 certificate for TLS")
+    parser.add_argument("--tls-private-key-path",
+                        help="PEM encoded private key for TLS")
+    parser.add_argument("--tls-dh-params-path",
+                        help="PEM encoded dh parameters for ephemeral keys")
+    parser.add_argument("--bind-port", type=int,
+                        help="TCP port to listen on")
+    parser.add_argument("--bind-host", default="",
+                        help="Local interface to listen on")
+
+    args = parser.parse_args(remaining_args)
+
+    server_config = vars(args)
+    del server_config["config_path"]
+    return server_config
+
+
+def generate_config(argv):
+    parser = argparse.ArgumentParser()
+    parser.add_argument("-c", "--config-path", help="Specify config file",
+                        metavar="CONFIG_FILE", required=True)
+    parser.add_argument("--server-name", default=socket.getfqdn(),
+                        help="The name of the server")
+    parser.add_argument("--signing-key-path",
+                        help="The signing key to sign responses with")
+    parser.add_argument("--tls-certificate-path",
+                        help="PEM encoded X509 certificate for TLS")
+    parser.add_argument("--tls-private-key-path",
+                        help="PEM encoded private key for TLS")
+    parser.add_argument("--tls-dh-params-path",
+                        help="PEM encoded dh parameters for ephemeral keys")
+    parser.add_argument("--bind-port", type=int, required=True,
+                        help="TCP port to listen on")
+    parser.add_argument("--bind-host", default="",
+                        help="Local interface to listen on")
+
+    args = parser.parse_args(argv)
+
+    dir_name = os.path.dirname(args.config_path)
+    base_key_name = os.path.join(dir_name, args.server_name)
+
+    if args.signing_key_path is None:
+        args.signing_key_path = base_key_name + ".signing.key"
+
+    if args.tls_certificate_path is None:
+        args.tls_certificate_path = base_key_name + ".tls.crt"
+
+    if args.tls_private_key_path is None:
+        args.tls_private_key_path = base_key_name + ".tls.key"
+
+    if args.tls_dh_params_path is None:
+        args.tls_dh_params_path = base_key_name + ".tls.dh"
+
+    if not os.path.exists(args.signing_key_path):
+        with open(args.signing_key_path, "w") as signing_key_file:
+            key = nacl.signing.SigningKey.generate()
+            signing_key_file.write(encode_base64(key.encode()))
+
+    if not os.path.exists(args.tls_private_key_path):
+        with open(args.tls_private_key_path, "w") as private_key_file:
+            tls_private_key = crypto.PKey()
+            tls_private_key.generate_key(crypto.TYPE_RSA, 2048)
+            private_key_pem = crypto.dump_privatekey(
+                crypto.FILETYPE_PEM, tls_private_key
+            )
+            private_key_file.write(private_key_pem)
+    else:
+        with open(args.tls_private_key_path) as private_key_file:
+            private_key_pem = private_key_file.read()
+            tls_private_key = crypto.load_privatekey(
+                crypto.FILETYPE_PEM, private_key_pem
+            )
+
+    if not os.path.exists(args.tls_certificate_path):
+        with open(args.tls_certificate_path, "w") as certifcate_file:
+            cert = crypto.X509()
+            subject = cert.get_subject()
+            subject.CN = args.server_name
+
+            cert.set_serial_number(1000)
+            cert.gmtime_adj_notBefore(0)
+            cert.gmtime_adj_notAfter(10 * 365 * 24 * 60 * 60)
+            cert.set_issuer(cert.get_subject())
+            cert.set_pubkey(tls_private_key)
+
+            cert.sign(tls_private_key, 'sha256')
+
+            cert_pem = crypto.dump_certificate(crypto.FILETYPE_PEM, cert)
+
+            certifcate_file.write(cert_pem)
+
+    if not os.path.exists(args.tls_dh_params_path):
+        subprocess.check_call([
+            "openssl", "dhparam",
+            "-outform", "PEM",
+            "-out", args.tls_dh_params_path,
+            "2048"
+        ])
+
+    config = configparser.SafeConfigParser()
+    config.add_section("KeyServer")
+    for key, value in vars(args).items():
+        if key != "config_path":
+            config.set("KeyServer", key, str(value))
+
+    with open(args.config_path, "w") as config_file:
+        config.write(config_file)
+
+
+if __name__ == "__main__":
+    generate_config(sys.argv[1:])