Merge pull request #2230 from reaperhulk/encode-iap

support InhibitAnyPolicy in CertificateBuilder
diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index 5c808f3..738c055 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -58,6 +58,7 @@
   * :class:`~cryptography.x509.AuthorityKeyIdentifier`
   * :class:`~cryptography.x509.AuthorityInformationAccess`
   * :class:`~cryptography.x509.CRLDistributionPoints`
+  * :class:`~cryptography.x509.InhibitAnyPolicy`
 
 0.9.3 - 2015-07-09
 ~~~~~~~~~~~~~~~~~~
diff --git a/src/_cffi_src/openssl/asn1.py b/src/_cffi_src/openssl/asn1.py
index 9608472..bbbffd8 100644
--- a/src/_cffi_src/openssl/asn1.py
+++ b/src/_cffi_src/openssl/asn1.py
@@ -133,6 +133,7 @@
 void ASN1_BIT_STRING_free(ASN1_BIT_STRING *);
 int i2d_ASN1_BIT_STRING(ASN1_BIT_STRING *, unsigned char **);
 int i2d_ASN1_OCTET_STRING(ASN1_OCTET_STRING *, unsigned char **);
+int i2d_ASN1_INTEGER(ASN1_INTEGER *, unsigned char **);
 /* This is not a macro, but is const on some versions of OpenSSL */
 int ASN1_BIT_STRING_get_bit(ASN1_BIT_STRING *, int);
 ASN1_TIME *M_ASN1_TIME_dup(void *);
diff --git a/src/cryptography/hazmat/backends/openssl/backend.py b/src/cryptography/hazmat/backends/openssl/backend.py
index 6675f67..c583214 100644
--- a/src/cryptography/hazmat/backends/openssl/backend.py
+++ b/src/cryptography/hazmat/backends/openssl/backend.py
@@ -102,6 +102,17 @@
     return s
 
 
+def _encode_inhibit_any_policy(backend, inhibit_any_policy):
+    asn1int = _encode_asn1_int_gc(backend, inhibit_any_policy.skip_certs)
+    pp = backend._ffi.new('unsigned char **')
+    r = backend._lib.i2d_ASN1_INTEGER(asn1int, pp)
+    assert r > 0
+    pp = backend._ffi.gc(
+        pp, lambda pointer: backend._lib.OPENSSL_free(pointer[0])
+    )
+    return pp, r
+
+
 def _encode_name(backend, attributes):
     """
     The X509_NAME created will not be gc'd. Use _encode_name_gc if needed.
@@ -1274,6 +1285,8 @@
                 pp, r = _encode_authority_key_identifier(self, extension.value)
             elif isinstance(extension.value, x509.KeyUsage):
                 pp, r = _encode_key_usage(self, extension.value)
+            elif isinstance(extension.value, x509.InhibitAnyPolicy):
+                pp, r = _encode_inhibit_any_policy(self, extension.value)
             elif isinstance(extension.value, x509.ExtendedKeyUsage):
                 pp, r = _encode_extended_key_usage(self, extension.value)
             elif isinstance(extension.value, x509.SubjectAlternativeName):
diff --git a/src/cryptography/x509.py b/src/cryptography/x509.py
index 397274e..bcda721 100644
--- a/src/cryptography/x509.py
+++ b/src/cryptography/x509.py
@@ -1818,6 +1818,8 @@
             )
         elif isinstance(extension, KeyUsage):
             extension = Extension(OID_KEY_USAGE, critical, extension)
+        elif isinstance(extension, InhibitAnyPolicy):
+            extension = Extension(OID_INHIBIT_ANY_POLICY, critical, extension)
         elif isinstance(extension, ExtendedKeyUsage):
             extension = Extension(OID_EXTENDED_KEY_USAGE, critical, extension)
         elif isinstance(extension, SubjectAlternativeName):
@@ -1832,12 +1834,14 @@
             extension = Extension(
                 OID_SUBJECT_KEY_IDENTIFIER, critical, extension
             )
-        elif isinstance(extension, InhibitAnyPolicy):
-            extension = Extension(OID_INHIBIT_ANY_POLICY, critical, extension)
         elif isinstance(extension, CRLDistributionPoints):
             extension = Extension(
                 OID_CRL_DISTRIBUTION_POINTS, critical, extension
             )
+        elif isinstance(extension, IssuerAlternativeName):
+            extension = Extension(
+                OID_ISSUER_ALTERNATIVE_NAME, critical, extension
+            )
         else:
             raise NotImplementedError('Unsupported X.509 extension.')
 
diff --git a/tests/hazmat/backends/test_openssl.py b/tests/hazmat/backends/test_openssl.py
index 051827a..8f559c8 100644
--- a/tests/hazmat/backends/test_openssl.py
+++ b/tests/hazmat/backends/test_openssl.py
@@ -529,7 +529,7 @@
         ).not_valid_after(
             datetime.datetime(2020, 1, 1)
         ).add_extension(
-            x509.InhibitAnyPolicy(0), False
+            x509.IssuerAlternativeName([x509.DNSName(u"crypto.io")]), False
         )
 
         with pytest.raises(NotImplementedError):
diff --git a/tests/test_x509.py b/tests/test_x509.py
index 9ca8931..b630e33 100644
--- a/tests/test_x509.py
+++ b/tests/test_x509.py
@@ -1455,6 +1455,36 @@
 
     @pytest.mark.requires_backend_interface(interface=RSABackend)
     @pytest.mark.requires_backend_interface(interface=X509Backend)
+    def test_inhibit_any_policy(self, backend):
+        issuer_private_key = RSA_KEY_2048.private_key(backend)
+        subject_private_key = RSA_KEY_2048.private_key(backend)
+
+        not_valid_before = datetime.datetime(2002, 1, 1, 12, 1)
+        not_valid_after = datetime.datetime(2030, 12, 31, 8, 30)
+
+        cert = x509.CertificateBuilder().subject_name(
+            x509.Name([x509.NameAttribute(x509.OID_COUNTRY_NAME, u'US')])
+        ).issuer_name(
+            x509.Name([x509.NameAttribute(x509.OID_COUNTRY_NAME, u'US')])
+        ).not_valid_before(
+            not_valid_before
+        ).not_valid_after(
+            not_valid_after
+        ).public_key(
+            subject_private_key.public_key()
+        ).serial_number(
+            123
+        ).add_extension(
+            x509.InhibitAnyPolicy(3), critical=False
+        ).sign(issuer_private_key, hashes.SHA256(), backend)
+
+        ext = cert.extensions.get_extension_for_oid(
+            x509.OID_INHIBIT_ANY_POLICY
+        )
+        assert ext.value == x509.InhibitAnyPolicy(3)
+
+    @pytest.mark.requires_backend_interface(interface=RSABackend)
+    @pytest.mark.requires_backend_interface(interface=X509Backend)
     def test_key_usage(self, backend):
         issuer_private_key = RSA_KEY_2048.private_key(backend)
         subject_private_key = RSA_KEY_2048.private_key(backend)