basicConstraints support for OpenSSL X509 backend
diff --git a/docs/x509.rst b/docs/x509.rst
index 44d53a4..f17c3da 100644
--- a/docs/x509.rst
+++ b/docs/x509.rst
@@ -205,6 +205,12 @@
         :raises cryptography.x509.DuplicateExtension: If more than one
             extension of the same type is found within the certificate.
 
+        .. doctest::
+
+            >>> for ext in cert.extensions:
+            ...     print(ext)
+            <Extension(oid=<ObjectIdentifier(oid=2.5.29.19, name=basicConstraints)>, critical=True, value=<BasicConstraints(ca=True, path_length=None)>)>
+
 .. class:: Name
 
     .. versionadded:: 0.8
@@ -292,6 +298,23 @@
     An X.509 Extensions instance is an ordered list of extensions.  The object
     is iterable to get every extension.
 
+    .. method:: get_extension_for_oid(oid)
+
+        :param oid: An :class:`ObjectIdentifier` instance.
+
+        :returns: An instance of the extension class.
+
+        :raises cryptography.x509.ExtensionNotFound: If the certificate does
+            not have the extension requested.
+
+        :raises cryptography.x509.UnsupportedExtension: If the certificate
+            contains an extension that is not supported.
+
+        .. doctest::
+
+            >>> cert.extensions.get_extension_for_oid(x509.OID_BASIC_CONSTRAINTS)
+            <Extension(oid=<ObjectIdentifier(oid=2.5.29.19, name=basicConstraints)>, critical=True, value=<BasicConstraints(ca=True, path_length=None)>)>
+
 .. class:: Extension
 
     .. versionadded:: 0.9
@@ -546,6 +569,17 @@
 
         Returns the OID.
 
+.. class:: ExtensionNotFound
+
+    This is raised when calling :meth:`Extensions.get_extension_for_oid` with
+    an extension OID that is not present in the certificate.
+
+    .. attribute:: oid
+
+        :type: :class:`ObjectIdentifier`
+
+        Returns the OID.
+
 
 .. _`public key infrastructure`: https://en.wikipedia.org/wiki/Public_key_infrastructure
 .. _`TLS`: https://en.wikipedia.org/wiki/Transport_Layer_Security
diff --git a/src/cryptography/hazmat/backends/openssl/x509.py b/src/cryptography/hazmat/backends/openssl/x509.py
index 3502d12..1c9cf5c 100644
--- a/src/cryptography/hazmat/backends/openssl/x509.py
+++ b/src/cryptography/hazmat/backends/openssl/x509.py
@@ -168,13 +168,16 @@
                 raise x509.DuplicateExtension(
                     "Duplicate {0} extension found".format(oid), oid
                 )
-            elif oid == x509.OID_BASIC_CONSTRAINTS and critical:
+            elif oid == x509.OID_BASIC_CONSTRAINTS:
+                value = self._build_basic_constraints(ext)
+            elif oid == x509.OID_KEY_USAGE and critical:
                 # TODO: remove this obviously.
                 warnings.warn(
-                    "Extension support is not fully implemented. A basic "
-                    "constraints extension with the critical flag was seen and"
-                    " IGNORED."
+                    "Extension support is not fully implemented. A key usage "
+                    "extension with the critical flag was seen and IGNORED."
                 )
+                seen_oids.add(oid)
+                continue
             elif critical:
                 raise x509.UnsupportedExtension(
                     "{0} is not currently supported".format(oid), oid
@@ -185,5 +188,31 @@
                 continue
 
             seen_oids.add(oid)
+            extensions.append(x509.Extension(oid, critical, value))
 
         return x509.Extensions(extensions)
+
+    def _build_basic_constraints(self, ext):
+        bc_st = self._backend._lib.X509V3_EXT_d2i(ext)
+        assert bc_st != self._backend._ffi.NULL
+        basic_constraints = self._backend._ffi.cast(
+            "BASIC_CONSTRAINTS *", bc_st
+        )
+        basic_constraints = self._backend._ffi.gc(
+            basic_constraints, self._backend._lib.BASIC_CONSTRAINTS_free
+        )
+        # The byte representation of an ASN.1 boolean true is \xff. OpenSSL
+        # chooses to just map this to its ordinal value, so true is 255 and
+        # false is 0.
+        ca = basic_constraints.ca == 255
+        if basic_constraints.pathlen == self._backend._ffi.NULL:
+            path_length = None
+        else:
+            bn = self._backend._lib.ASN1_INTEGER_to_BN(
+                basic_constraints.pathlen, self._backend._ffi.NULL
+            )
+            assert bn != self._backend._ffi.NULL
+            bn = self._backend._ffi.gc(bn, self._backend._lib.BN_free)
+            path_length = self._backend._bn_to_int(bn)
+
+        return x509.BasicConstraints(ca, path_length)
diff --git a/src/cryptography/x509.py b/src/cryptography/x509.py
index 29602b3..864736e 100644
--- a/src/cryptography/x509.py
+++ b/src/cryptography/x509.py
@@ -78,6 +78,12 @@
         self.oid = oid
 
 
+class ExtensionNotFound(Exception):
+    def __init__(self, msg, oid):
+        super(ExtensionNotFound, self).__init__(msg)
+        self.oid = oid
+
+
 class NameAttribute(object):
     def __init__(self, oid, value):
         if not isinstance(oid, ObjectIdentifier):
@@ -163,6 +169,13 @@
     def __init__(self, extensions):
         self._extensions = extensions
 
+    def get_extension_for_oid(self, oid):
+        for ext in self:
+            if ext.oid == oid:
+                return ext
+
+        raise ExtensionNotFound("No {0} extension was found".format(oid), oid)
+
     def __iter__(self):
         return iter(self._extensions)
 
diff --git a/tests/test_x509_ext.py b/tests/test_x509_ext.py
index d828152..324864d 100644
--- a/tests/test_x509_ext.py
+++ b/tests/test_x509_ext.py
@@ -74,6 +74,23 @@
         ext = cert.extensions
         assert len(ext) == 0
         assert list(ext) == []
+        with pytest.raises(x509.ExtensionNotFound) as exc:
+            ext.get_extension_for_oid(x509.OID_BASIC_CONSTRAINTS)
+
+        assert exc.value.oid == x509.OID_BASIC_CONSTRAINTS
+
+    def test_one_extension(self, backend):
+        cert = _load_cert(
+            os.path.join(
+                "x509", "custom", "basic_constraints_not_critical.pem"
+            ),
+            x509.load_pem_x509_certificate,
+            backend
+        )
+        extensions = cert.extensions
+        ext = extensions.get_extension_for_oid(x509.OID_BASIC_CONSTRAINTS)
+        assert ext is not None
+        assert ext.value.ca is False
 
     def test_duplicate_extension(self, backend):
         cert = _load_cert(
@@ -112,3 +129,94 @@
         )
         extensions = cert.extensions
         assert len(extensions) == 0
+
+
+@pytest.mark.requires_backend_interface(interface=RSABackend)
+@pytest.mark.requires_backend_interface(interface=X509Backend)
+class TestRSABasicConstraintsExtension(object):
+    def test_ca_true_pathlen_6(self, backend):
+        cert = _load_cert(
+            os.path.join(
+                "x509", "PKITS_data", "certs", "pathLenConstraint6CACert.crt"
+            ),
+            x509.load_der_x509_certificate,
+            backend
+        )
+        ext = cert.extensions.get_extension_for_oid(
+            x509.OID_BASIC_CONSTRAINTS
+        )
+        assert ext is not None
+        assert ext.critical is True
+        assert ext.value.ca is True
+        assert ext.value.path_length == 6
+
+    def test_path_length_zero(self, backend):
+        cert = _load_cert(
+            os.path.join("x509", "custom", "bc_path_length_zero.pem"),
+            x509.load_pem_x509_certificate,
+            backend
+        )
+        ext = cert.extensions.get_extension_for_oid(
+            x509.OID_BASIC_CONSTRAINTS
+        )
+        assert ext is not None
+        assert ext.critical is True
+        assert ext.value.ca is True
+        assert ext.value.path_length == 0
+
+    def test_ca_true_no_pathlen(self, backend):
+        cert = _load_cert(
+            os.path.join("x509", "PKITS_data", "certs", "GoodCACert.crt"),
+            x509.load_der_x509_certificate,
+            backend
+        )
+        ext = cert.extensions.get_extension_for_oid(
+            x509.OID_BASIC_CONSTRAINTS
+        )
+        assert ext is not None
+        assert ext.critical is True
+        assert ext.value.ca is True
+        assert ext.value.path_length is None
+
+    def test_ca_false(self, backend):
+        cert = _load_cert(
+            os.path.join("x509", "cryptography.io.pem"),
+            x509.load_pem_x509_certificate,
+            backend
+        )
+        ext = cert.extensions.get_extension_for_oid(
+            x509.OID_BASIC_CONSTRAINTS
+        )
+        assert ext is not None
+        assert ext.critical is True
+        assert ext.value.ca is False
+        assert ext.value.path_length is None
+
+    def test_no_basic_constraints(self, backend):
+        cert = _load_cert(
+            os.path.join(
+                "x509",
+                "PKITS_data",
+                "certs",
+                "ValidCertificatePathTest1EE.crt"
+            ),
+            x509.load_der_x509_certificate,
+            backend
+        )
+        with pytest.raises(x509.ExtensionNotFound):
+            cert.extensions.get_extension_for_oid(x509.OID_BASIC_CONSTRAINTS)
+
+    def test_basic_constraint_not_critical(self, backend):
+        cert = _load_cert(
+            os.path.join(
+                "x509", "custom", "basic_constraints_not_critical.pem"
+            ),
+            x509.load_pem_x509_certificate,
+            backend
+        )
+        ext = cert.extensions.get_extension_for_oid(
+            x509.OID_BASIC_CONSTRAINTS
+        )
+        assert ext is not None
+        assert ext.critical is False
+        assert ext.value.ca is False