Bug 1056934 - Part 1: TLS support in the test ICE server. r=drno
authorByron Campen [:bwc] <docfaraday@gmail.com>
Fri, 16 Dec 2016 17:04:56 -0600
changeset 374677 a9a5828b9c89324e71563b3c14d8b76df6f21a93
parent 374676 c779cd2ff47cf22837e6c8038cf598d51e9b501c
child 374678 341ba823f532f2915481e44ce673a7c9f607cfb7
push id6996
push userjlorenzo@mozilla.com
push dateMon, 06 Mar 2017 20:48:21 +0000
treeherdermozilla-beta@d89512dab048 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdrno
bugs1056934
milestone53.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1056934 - Part 1: TLS support in the test ICE server. r=drno MozReview-Commit-ID: 9Vz87jqHwGc
testing/tools/iceserver/iceserver.py
--- a/testing/tools/iceserver/iceserver.py
+++ b/testing/tools/iceserver/iceserver.py
@@ -6,17 +6,19 @@
 import ipaddr
 import socket
 import hmac
 import hashlib
 import passlib.utils # for saslprep
 import copy
 import random
 import operator
+import os
 import platform
+import string
 import time
 from string import Template
 from twisted.internet import reactor, protocol
 from twisted.internet.task import LoopingCall
 from twisted.internet.address import IPv4Address
 
 MAGIC_COOKIE = 0x2112A442
 
@@ -711,16 +713,48 @@ except:
 def prune_allocations():
     now = time.time()
     for key, allocation in allocations.items():
         if allocation.expiry < now:
             print("Allocation expired: {}".format(key))
             del allocations[key]
             allocation.close()
 
+CERT_FILE = "selfsigned.crt"
+KEY_FILE = "private.key"
+
+def create_self_signed_cert(name):
+    from OpenSSL import crypto
+    if os.path.isfile(CERT_FILE) and os.path.isfile(KEY_FILE):
+        return
+
+    # create a key pair
+    k = crypto.PKey()
+    k.generate_key(crypto.TYPE_RSA, 1024)
+
+    # create a self-signed cert
+    cert = crypto.X509()
+    cert.get_subject().C = "US"
+    cert.get_subject().ST = "TX"
+    cert.get_subject().L = "Dallas"
+    cert.get_subject().O = "Mozilla test iceserver"
+    cert.get_subject().OU = "Mozilla test iceserver"
+    cert.get_subject().CN = 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(k)
+    cert.sign(k, 'sha1')
+
+    open(CERT_FILE, "wt").write(
+        crypto.dump_certificate(crypto.FILETYPE_PEM, cert))
+    open(KEY_FILE, "wt").write(
+        crypto.dump_privatekey(crypto.FILETYPE_PEM, k))
+
 if __name__ == "__main__":
     random.seed()
 
     if platform.system() is "Windows":
       # Windows is finicky about allowing real interfaces to talk to loopback.
       interface_4 = v4_address
       interface_6 = v6_address
       hostname = socket.gethostname()
@@ -735,25 +769,53 @@ if __name__ == "__main__":
     reactor.listenTCP(3478, TcpStunHandlerFactory(), interface=interface_4)
 
     try:
         reactor.listenUDP(3478, UdpStunHandler(), interface=interface_6)
         reactor.listenTCP(3478, TcpStunHandlerFactory(), interface=interface_6)
     except:
         pass
 
+    try:
+        from twisted.internet import ssl
+        from OpenSSL import SSL
+        create_self_signed_cert(hostname)
+        tls_context_factory = ssl.DefaultOpenSSLContextFactory(KEY_FILE, CERT_FILE, SSL.TLSv1_2_METHOD)
+        reactor.listenSSL(5349, TcpStunHandlerFactory(), tls_context_factory, interface=interface_4)
+
+        try:
+            reactor.listenSSL(5349, TcpStunHandlerFactory(), tls_context_factory, interface=interface_6)
+        except:
+            pass
+
+        f = open(CERT_FILE, 'r');
+        lines = f.readlines();
+        lines.pop(0); # Remove BEGIN CERTIFICATE
+        lines.pop(); # Remove END CERTIFICATE
+        lines = map(string.strip, lines);
+        certbase64 = string.join(lines, '');
+
+        turns_url = ', "turns:' + hostname + '"'
+        cert_prop = ', "cert":"' + certbase64 + '"'
+    except:
+        turns_url = ''
+        cert_prop = ''
+        pass
+
     allocation_pruner = LoopingCall(prune_allocations)
     allocation_pruner.start(1)
 
     template = Template(
 '[\
-{"url":"stun:$hostname"}, \
-{"url":"stun:$hostname?transport=tcp"}, \
-{"username":"$user","credential":"$pwd","url":"turn:$hostname"}, \
-{"username":"$user","credential":"$pwd","url":"turn:$hostname?transport=tcp"}]'
+{"urls":["stun:$hostname", "stun:$hostname?transport=tcp"]}, \
+{"username":"$user","credential":"$pwd","urls": \
+["turn:$hostname", "turn:$hostname?transport=tcp" $turns_url] \
+$cert_prop}]' # Hack to make it easier to override cert checks
 )
 
     print(template.substitute(user=turn_user,
                               pwd=turn_pass,
-                              hostname=hostname))
+                              hostname=hostname,
+                              turns_url=turns_url,
+                              cert_prop=cert_prop))
 
     reactor.run()