Merge pull request #2150 from reaperhulk/encode-uri

support URI general name encoding
diff --git a/src/cryptography/hazmat/backends/openssl/backend.py b/src/cryptography/hazmat/backends/openssl/backend.py
index bba407d..7ccb39a 100644
--- a/src/cryptography/hazmat/backends/openssl/backend.py
+++ b/src/cryptography/hazmat/backends/openssl/backend.py
@@ -230,9 +230,17 @@
             )
             gn.type = backend._lib.GEN_EMAIL
             gn.d.rfc822Name = asn1_str
+        elif isinstance(alt_name, x509.UniformResourceIdentifier):
+            gn = backend._lib.GENERAL_NAME_new()
+            assert gn != backend._ffi.NULL
+            asn1_str = _encode_asn1_str(
+                backend, alt_name._encoded, len(alt_name._encoded)
+            )
+            gn.type = backend._lib.GEN_URI
+            gn.d.uniformResourceIdentifier = asn1_str
         else:
-            raise NotImplementedError(
-                "Only DNSName and RegisteredID supported right now"
+            raise ValueError(
+                "{0} is an unknown GeneralName type".format(alt_name)
             )
 
         res = backend._lib.sk_GENERAL_NAME_push(general_names, gn)
diff --git a/tests/test_x509.py b/tests/test_x509.py
index 2539be4..94eeab2 100644
--- a/tests/test_x509.py
+++ b/tests/test_x509.py
@@ -13,7 +13,7 @@
 
 import six
 
-from cryptography import x509
+from cryptography import utils, x509
 from cryptography.exceptions import UnsupportedAlgorithm
 from cryptography.hazmat.backends.interfaces import (
     DSABackend, EllipticCurveBackend, RSABackend, X509Backend
@@ -27,6 +27,14 @@
 from .utils import load_vectors_from_file
 
 
+@utils.register_interface(x509.GeneralName)
+class FakeGeneralName(object):
+    def __init__(self, value):
+        self._value = value
+
+    value = utils.read_only_property("_value")
+
+
 def _load_cert(filename, loader, backend):
     cert = load_vectors_from_file(
         filename=filename,
@@ -1011,6 +1019,12 @@
                 x509.RFC822Name(u"test@example.com"),
                 x509.RFC822Name(u"email"),
                 x509.RFC822Name(u"email@em\xe5\xefl.com"),
+                x509.UniformResourceIdentifier(
+                    u"https://\u043f\u044b\u043a\u0430.cryptography"
+                ),
+                x509.UniformResourceIdentifier(
+                    u"gopher://cryptography:70/some/path"
+                ),
             ]),
             critical=False,
         ).sign(private_key, hashes.SHA256(), backend)
@@ -1040,6 +1054,12 @@
             x509.RFC822Name(u"test@example.com"),
             x509.RFC822Name(u"email"),
             x509.RFC822Name(u"email@em\xe5\xefl.com"),
+            x509.UniformResourceIdentifier(
+                u"https://\u043f\u044b\u043a\u0430.cryptography"
+            ),
+            x509.UniformResourceIdentifier(
+                u"gopher://cryptography:70/some/path"
+            ),
         ]
 
     def test_invalid_asn1_othername(self, backend):
@@ -1069,13 +1089,11 @@
                 x509.NameAttribute(x509.OID_COMMON_NAME, u"SAN"),
             ])
         ).add_extension(
-            x509.SubjectAlternativeName([
-                x509.UniformResourceIdentifier(u"http://test.com"),
-            ]),
+            x509.SubjectAlternativeName([FakeGeneralName("")]),
             critical=False,
         )
 
-        with pytest.raises(NotImplementedError):
+        with pytest.raises(ValueError):
             builder.sign(private_key, hashes.SHA256(), backend)