Merge pull request #1890 from reaperhulk/add-eq-ne-eku

add eq/ne to ExtendedKeyUsage
diff --git a/.travis.yml b/.travis.yml
index 71efd8f..c7413ea 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -120,3 +120,5 @@
             - "irc.freenode.org#cryptography-dev"
         use_notice: true
         skip_join: true
+    webhooks:
+        - https://buildtimetrend.herokuapp.com/travis
diff --git a/src/cryptography/hazmat/backends/openssl/x509.py b/src/cryptography/hazmat/backends/openssl/x509.py
index 7f633c7..4ba66bb 100644
--- a/src/cryptography/hazmat/backends/openssl/x509.py
+++ b/src/cryptography/hazmat/backends/openssl/x509.py
@@ -15,6 +15,7 @@
 
 import datetime
 import ipaddress
+from email.utils import parseaddr
 
 import idna
 
@@ -107,6 +108,27 @@
         return x509.DirectoryName(
             _build_x509_name(backend, gn.d.directoryName)
         )
+    elif gn.type == backend._lib.GEN_EMAIL:
+        data = backend._ffi.buffer(
+            gn.d.rfc822Name.data, gn.d.rfc822Name.length
+        )[:].decode("ascii")
+        name, address = parseaddr(data)
+        parts = address.split(u"@")
+        if name or len(parts) > 2 or not address:
+            # parseaddr has found a name (e.g. Name <email>) or the split
+            # has found more than 2 parts (which means more than one @ sign)
+            # or the entire value is an empty string.
+            raise ValueError("Invalid rfc822name value")
+        elif len(parts) == 1:
+            # Single label email name. This is valid for local delivery. No
+            # IDNA decoding can be done since there is no domain component.
+            return x509.RFC822Name(address)
+        else:
+            # A normal email of the form user@domain.com. Let's attempt to
+            # decode the domain component and return the entire address.
+            return x509.RFC822Name(
+                parts[0] + u"@" + idna.decode(parts[1])
+            )
     else:
         # otherName, x400Address or ediPartyName
         raise x509.UnsupportedGeneralNameType(
diff --git a/src/cryptography/hazmat/bindings/openssl/ssl.py b/src/cryptography/hazmat/bindings/openssl/ssl.py
index b182180..4a824ae 100644
--- a/src/cryptography/hazmat/bindings/openssl/ssl.py
+++ b/src/cryptography/hazmat/bindings/openssl/ssl.py
@@ -211,6 +211,9 @@
 int SSL_CTX_use_PrivateKey(SSL_CTX *, EVP_PKEY *);
 int SSL_CTX_use_PrivateKey_file(SSL_CTX *, const char *, int);
 int SSL_CTX_check_private_key(const SSL_CTX *);
+void SSL_CTX_set_cert_verify_callback(SSL_CTX *,
+                                      int (*)(X509_STORE_CTX *,void *),
+                                      void *);
 
 void SSL_CTX_set_cert_store(SSL_CTX *, X509_STORE *);
 X509_STORE *SSL_CTX_get_cert_store(const SSL_CTX *);
diff --git a/tests/test_x509_ext.py b/tests/test_x509_ext.py
index c574aed..05734b4 100644
--- a/tests/test_x509_ext.py
+++ b/tests/test_x509_ext.py
@@ -871,3 +871,91 @@
                 x509.NameAttribute(x509.OID_STATE_OR_PROVINCE_NAME, 'Texas'),
             ])
         ] == dirname
+
+    def test_rfc822name(self, backend):
+        cert = _load_cert(
+            os.path.join(
+                "x509", "custom", "san_rfc822_idna.pem"
+            ),
+            x509.load_pem_x509_certificate,
+            backend
+        )
+        ext = cert.extensions.get_extension_for_oid(
+            x509.OID_SUBJECT_ALTERNATIVE_NAME
+        )
+        assert ext is not None
+        assert ext.critical is False
+
+        san = ext.value
+
+        rfc822name = san.get_values_for_type(x509.RFC822Name)
+        assert [u"email@em\xe5\xefl.com"] == rfc822name
+
+    def test_unicode_rfc822_name_dns_name_uri(self, backend):
+        cert = _load_cert(
+            os.path.join(
+                "x509", "custom", "san_idna_names.pem"
+            ),
+            x509.load_pem_x509_certificate,
+            backend
+        )
+        ext = cert.extensions.get_extension_for_oid(
+            x509.OID_SUBJECT_ALTERNATIVE_NAME
+        )
+        assert ext is not None
+        rfc822_name = ext.value.get_values_for_type(x509.RFC822Name)
+        dns_name = ext.value.get_values_for_type(x509.DNSName)
+        uri = ext.value.get_values_for_type(x509.UniformResourceIdentifier)
+        assert rfc822_name == [u"email@\u043f\u044b\u043a\u0430.cryptography"]
+        assert dns_name == [u"\u043f\u044b\u043a\u0430.cryptography"]
+        assert uri == [u"https://www.\u043f\u044b\u043a\u0430.cryptography"]
+
+    def test_rfc822name_dnsname_ipaddress_directoryname_uri(self, backend):
+        cert = _load_cert(
+            os.path.join(
+                "x509", "custom", "san_email_dns_ip_dirname_uri.pem"
+            ),
+            x509.load_pem_x509_certificate,
+            backend
+        )
+        ext = cert.extensions.get_extension_for_oid(
+            x509.OID_SUBJECT_ALTERNATIVE_NAME
+        )
+        assert ext is not None
+        assert ext.critical is False
+
+        san = ext.value
+
+        rfc822_name = san.get_values_for_type(x509.RFC822Name)
+        uri = san.get_values_for_type(x509.UniformResourceIdentifier)
+        dns = san.get_values_for_type(x509.DNSName)
+        ip = san.get_values_for_type(x509.IPAddress)
+        dirname = san.get_values_for_type(x509.DirectoryName)
+        assert [u"user@cryptography.io"] == rfc822_name
+        assert [u"https://cryptography.io"] == uri
+        assert [u"cryptography.io"] == dns
+        assert [
+            x509.Name([
+                x509.NameAttribute(x509.OID_COMMON_NAME, 'dirCN'),
+                x509.NameAttribute(
+                    x509.OID_ORGANIZATION_NAME, 'Cryptographic Authority'
+                ),
+            ])
+        ] == dirname
+        assert [
+            ipaddress.ip_address(u"127.0.0.1"),
+            ipaddress.ip_address(u"ff::")
+        ] == ip
+
+    def test_invalid_rfc822name(self, backend):
+        cert = _load_cert(
+            os.path.join(
+                "x509", "custom", "san_rfc822_names.pem"
+            ),
+            x509.load_pem_x509_certificate,
+            backend
+        )
+        with pytest.raises(ValueError) as exc:
+            cert.extensions
+
+        assert 'Invalid rfc822name value' in str(exc.value)