parent
0138452a0c
commit
6de2ef7cbc
@ -1 +1,2 @@
|
||||
DIST M2Crypto-0.22.3.tar.gz 74795 SHA256 6071bfc817d94723e9b458a010d565365104f84aa73f7fe11919871f7562ff72 SHA512 c179d3cf03ced77aed24285ca3f1527d5e05bbfe091a1522bff94a940fd390213fbb9b83d7ccd43ceae49626b427ae8790782cf93ead85be1e063bc4121c62e0 WHIRLPOOL 66a9a6e7c9b195814048a1bcecf6ef71a269bebb9dbda73801c88b3ba27330b555a46d05c53bbd0778f9c1e1bb5f9c6e7e860de443bf16baffc2072ee5996e31
|
||||
DIST M2Crypto-0.24.0.tar.gz 184457 SHA256 80a56441a1d2c0cf27e725be7554c92598b938fc8767ee2c71fdbc2fdc055ee8 SHA512 c23ae0f8ac790d4ef108a217a44e994341f6bbe4e12a7fef2518d8def82331246a145e19a2504b82b790a3ad4b467d2facc8a73bb7f1190b56441d8482c66aca WHIRLPOOL 47a437ee1207b4cca8d67aa4bdec95b9194030e3fc7146ace8d071caa9be829f3e9516ff9399e695615acdf930a90040deb0f1175d81994465ed0853688e3b37
|
||||
|
@ -0,0 +1,245 @@
|
||||
diff --git M2Crypto/X509.py M2Crypto/X509.py
|
||||
index 62096f3..500f740 100644
|
||||
--- M2Crypto/X509.py
|
||||
+++ M2Crypto/X509.py
|
||||
@@ -29,9 +29,11 @@ def new_extension(name, value, critical=0, _pyfree=1):
|
||||
"""
|
||||
Create new X509_Extension instance.
|
||||
"""
|
||||
- if name == 'subjectKeyIdentifier' and \
|
||||
- value.strip('0123456789abcdefABCDEF:') is not '':
|
||||
- raise ValueError('value must be precomputed hash')
|
||||
+ if X509_Extension_Proxy.must_proxy(name, value):
|
||||
+ # Maybe all extensions should be proxies?
|
||||
+ # XXX Either all proxies (might solve other problems too), or at
|
||||
+ # XXX least at least need to refactor to avoid code duplication
|
||||
+ return X509_Extension_Proxy(name, value, critical, _pyfree)
|
||||
lhash = m2.x509v3_lhash()
|
||||
ctx = m2.x509v3_set_conf_lhash(lhash)
|
||||
x509_ext_ptr = m2.x509v3_ext_conf(lhash, ctx, name, value)
|
||||
@@ -40,6 +42,96 @@ def new_extension(name, value, critical=0, _pyfree=1):
|
||||
return x509_ext
|
||||
|
||||
|
||||
+class X509_Extension_Proxy:
|
||||
+ """
|
||||
+ A holder object for X509 Extensions that need to be created with
|
||||
+ certificate based calculated values.
|
||||
+ """
|
||||
+ def __init__ (self, name, value, critical=0, _pyfree=1):
|
||||
+ self.name = name
|
||||
+ self.value = value
|
||||
+ self.critical = critical
|
||||
+ self._pyfree = _pyfree
|
||||
+
|
||||
+ @staticmethod
|
||||
+ def must_proxy (name, value):
|
||||
+ """
|
||||
+ Checks if this extension name and value define a calculated extension,
|
||||
+ i.e. one that needs the certificate to render a valid value.
|
||||
+ """
|
||||
+ # XXX Are these the only cases where we must proxy?
|
||||
+ # XXX Even if they are now, it does not seem this is future proof...
|
||||
+ # XXX any other way around this?
|
||||
+ return (name == 'subjectKeyIdentifier' and value == 'hash') or \
|
||||
+ (name == 'authorityKeyIdentifier')
|
||||
+
|
||||
+ def set_critical(self, critical=1):
|
||||
+ """
|
||||
+ Mark this extension critical or noncritical. By default an
|
||||
+ extension is not critical.
|
||||
+
|
||||
+ @type critical: int
|
||||
+ @param critical: Nonzero sets this extension as critical.
|
||||
+ Calling this method without arguments will
|
||||
+ set this extension to critical.
|
||||
+ """
|
||||
+ self.critical = critical
|
||||
+ return self.critical
|
||||
+
|
||||
+ def get_critical(self):
|
||||
+ """
|
||||
+ Return whether or not this is a critical extension.
|
||||
+
|
||||
+ @rtype: int
|
||||
+ @return: Nonzero if this is a critical extension.
|
||||
+ """
|
||||
+ return self.critical
|
||||
+
|
||||
+ def get_name(self):
|
||||
+ """
|
||||
+ Get the extension name, for example 'subjectAltName'.
|
||||
+ """
|
||||
+ return self.name
|
||||
+
|
||||
+ def get_value(self, flag=0, indent=0):
|
||||
+ """
|
||||
+ Get the extension value, for example 'DNS:www.example.com'.
|
||||
+
|
||||
+ @param flag: Flag to control what and how to print.
|
||||
+ Ignored in this proxy.
|
||||
+ @param indent: How many spaces to print before actual value.
|
||||
+ """
|
||||
+ # XXX It is a problem that this method can give different output
|
||||
+ # XXX compared to the real object.
|
||||
+ return (" " * indent) + self.value
|
||||
+
|
||||
+ def __call__ (self, cert=None):
|
||||
+ """
|
||||
+ Create new X509_Extension instance.
|
||||
+ """
|
||||
+ # XXX Why is this __call__, wouldn't it be clearer to have an explicit
|
||||
+ # XXX name for this? Or is there some usage I am missing...?
|
||||
+ lhash = m2.x509v3_lhash()
|
||||
+ ctx = m2.x509v3_set_conf_lhash(lhash)
|
||||
+ if cert:
|
||||
+ if isinstance(cert, X509) and m2.x509_type_check(cert.x509):
|
||||
+ m2.x509v3_set_ctx_subject(ctx, cert.x509)
|
||||
+ if cert.issuer and m2.x509_type_check(cert.issuer.x509):
|
||||
+ m2.x509v3_set_ctx_issuer(ctx, cert.issuer.x509)
|
||||
+ else:
|
||||
+ m2.x509v3_set_ctx_issuer(ctx, cert.x509)
|
||||
+ elif isinstance(cert, Request) and cert.req:
|
||||
+ m2.x509v3_set_ctx_request(ctx, cert.req)
|
||||
+ else:
|
||||
+ if self.name == 'subjectKeyIdentifier' and self.value == 'hash':
|
||||
+ raise ValueError('value must be precomputed hash if no context is given')
|
||||
+
|
||||
+ x509_ext_ptr = m2.x509v3_ext_conf(lhash, ctx, self.name, self.value)
|
||||
+ x509_ext = X509_Extension(x509_ext_ptr, self._pyfree)
|
||||
+ x509_ext.set_critical(self.critical)
|
||||
+ return x509_ext
|
||||
+
|
||||
+
|
||||
class X509_Extension: # noqa
|
||||
"""
|
||||
X509 Extension
|
||||
@@ -123,6 +215,7 @@ class X509_Extension_Stack: # noqa
|
||||
self.stack = m2.sk_x509_extension_new_null()
|
||||
self._pyfree = 1
|
||||
self.pystack = [] # This must be kept in sync with self.stack
|
||||
+ self.proxies = []
|
||||
|
||||
def __del__(self):
|
||||
if getattr(self, '_pyfree', 0):
|
||||
@@ -149,6 +242,9 @@ class X509_Extension_Stack: # noqa
|
||||
@param x509_ext: X509_Extension object to be pushed onto the stack.
|
||||
@return: The number of extensions on the stack.
|
||||
"""
|
||||
+ if isinstance(x509_ext, X509_Extension_Proxy):
|
||||
+ self.proxies.append(x509_ext)
|
||||
+ return len(self.proxies)
|
||||
self.pystack.append(x509_ext)
|
||||
ret = m2.sk_x509_extension_push(self.stack, x509_ext._ptr())
|
||||
assert ret == len(self.pystack)
|
||||
@@ -166,6 +262,14 @@ class X509_Extension_Stack: # noqa
|
||||
return None
|
||||
return self.pystack.pop()
|
||||
|
||||
+ def process_proxies(self, cert):
|
||||
+ """
|
||||
+ Create extensions from stored proxies, now that we have a context to work with.
|
||||
+ """
|
||||
+ for p in self.proxies:
|
||||
+ self.push(p(cert))
|
||||
+ self.proxies = []
|
||||
+
|
||||
|
||||
class X509_Name_Entry: # noqa
|
||||
"""
|
||||
@@ -350,6 +454,7 @@ class X509:
|
||||
else:
|
||||
self.x509 = m2.x509_new()
|
||||
self._pyfree = 1
|
||||
+ self.issuer = None
|
||||
|
||||
def __del__(self):
|
||||
if getattr(self, '_pyfree', 0):
|
||||
@@ -488,15 +593,18 @@ class X509:
|
||||
assert m2.x509_type_check(self.x509), "'x509' type error"
|
||||
return X509_Name(m2.x509_get_issuer_name(self.x509))
|
||||
|
||||
- def set_issuer(self, name):
|
||||
+ def set_issuer(self, issuer):
|
||||
"""
|
||||
- Set issuer name.
|
||||
+ Set issuer object (and set issuer name). The object will be used in extension contexts if needed.
|
||||
|
||||
- @type name: X509_Name
|
||||
- @param name: subjectName field.
|
||||
+ @type name: X509_Name or X509
|
||||
+ @param name: subjectName field or issuer object.
|
||||
"""
|
||||
assert m2.x509_type_check(self.x509), "'x509' type error"
|
||||
- return m2.x509_set_issuer_name(self.x509, name.x509_name)
|
||||
+ if isinstance(issuer, X509):
|
||||
+ self.issuer = issuer
|
||||
+ issuer = X509_Name(m2.x509_get_subject_name(issuer.x509))
|
||||
+ return m2.x509_set_issuer_name(self.x509, issuer.x509_name)
|
||||
|
||||
def get_subject(self):
|
||||
assert m2.x509_type_check(self.x509), "'x509' type error"
|
||||
@@ -519,6 +627,9 @@ class X509:
|
||||
@type ext: X509_Extension
|
||||
@param ext: Extension
|
||||
"""
|
||||
+ if isinstance(ext, X509_Extension_Proxy):
|
||||
+ ext = ext(self)
|
||||
+
|
||||
assert m2.x509_type_check(self.x509), "'x509' type error"
|
||||
return m2.x509_add_ext(self.x509, ext.x509_ext, -1)
|
||||
|
||||
@@ -1003,6 +1114,7 @@ class Request:
|
||||
@type ext_stack: X509_Extension_Stack
|
||||
@param ext_stack: Stack of extensions to add.
|
||||
"""
|
||||
+ ext_stack.process_proxies(self)
|
||||
return m2.x509_req_add_extensions(self.req, ext_stack._ptr())
|
||||
|
||||
def verify(self, pkey):
|
||||
diff --git SWIG/_x509.i SWIG/_x509.i
|
||||
index be3099a..0ab1c78 100644
|
||||
--- SWIG/_x509.i
|
||||
+++ SWIG/_x509.i
|
||||
@@ -531,6 +531,10 @@ x509v3_set_conf_lhash(LHASH * lhash) {
|
||||
PyErr_SetString(PyExc_MemoryError, "x509v3_set_conf_lhash");
|
||||
return NULL;
|
||||
}
|
||||
+ /* XXX Why is this needed? */
|
||||
+ /* Make sure the structure members are nulled */
|
||||
+ X509V3_set_ctx(ctx, NULL, NULL, NULL, NULL, 0);
|
||||
+
|
||||
X509V3_set_conf_lhash(ctx, lhash);
|
||||
return ctx;
|
||||
}
|
||||
@@ -659,6 +663,30 @@ get_der_encoding_stack(STACK_OF(X509) *stack){
|
||||
return encodedString;
|
||||
}
|
||||
|
||||
+/* XXX Are these simple pointers in the context, or should they be refcounted? */
|
||||
+
|
||||
+/* XXX Since these are really only used in one method, should these instead be
|
||||
+ * XXX made into a single function, which can be called with NULL for
|
||||
+ * XXX optional fields? Otherwise, what is there stopping calling
|
||||
+ * XXX set_ctx_subject without having set ctx first? */
|
||||
+
|
||||
+void x509v3_set_ctx_issuer(X509V3_CTX *ctx, X509 *issuer) {
|
||||
+ ctx->issuer_cert = issuer;
|
||||
+}
|
||||
+
|
||||
+void x509v3_set_ctx_subject(X509V3_CTX *ctx, X509 *subject) {
|
||||
+ ctx->subject_cert = subject;
|
||||
+}
|
||||
+
|
||||
+void x509v3_set_ctx_request(X509V3_CTX *ctx, X509_REQ *request) {
|
||||
+ ctx->subject_req = request;
|
||||
+}
|
||||
+
|
||||
+/* XXX This does not seem to be used, why is it here? */
|
||||
+void x509v3_set_ctx_crl(X509V3_CTX *ctx, X509_CRL *crl) {
|
||||
+ ctx->crl = crl;
|
||||
+}
|
||||
+
|
||||
%}
|
||||
|
||||
/* Free malloc'ed return value for x509_name_oneline */
|
@ -0,0 +1,43 @@
|
||||
# Copyright 1999-2017 Gentoo Foundation
|
||||
# Distributed under the terms of the GNU General Public License v2
|
||||
# $Id$
|
||||
|
||||
EAPI=5
|
||||
|
||||
PYTHON_COMPAT=( python2_7 )
|
||||
PYTHON_REQ_USE="threads(+)"
|
||||
|
||||
inherit distutils-r1
|
||||
|
||||
MY_PN="M2Crypto"
|
||||
|
||||
DESCRIPTION="M2Crypto: A Python crypto and SSL toolkit"
|
||||
HOMEPAGE="https://gitlab.com/m2crypto/m2crypto https://pypi.python.org/pypi/M2Crypto"
|
||||
SRC_URI="mirror://pypi/${MY_PN:0:1}/${MY_PN}/${MY_PN}-${PV}.tar.gz"
|
||||
|
||||
LICENSE="BSD"
|
||||
SLOT="0"
|
||||
KEYWORDS="alpha amd64 ~arm ~arm64 hppa ~ia64 ~mips ~ppc ppc64 ~s390 ~sh ~sparc x86 ~amd64-fbsd ~x86-fbsd ~amd64-linux ~x86-linux ~ppc-macos ~x64-macos ~x86-macos"
|
||||
IUSE="libressl"
|
||||
|
||||
RDEPEND="
|
||||
!libressl? ( >=dev-libs/openssl-0.9.8:0= )
|
||||
libressl? ( dev-libs/libressl:= )
|
||||
"
|
||||
DEPEND="${RDEPEND}
|
||||
>=dev-lang/swig-1.3.28:0
|
||||
dev-python/setuptools[${PYTHON_USEDEP}]
|
||||
"
|
||||
|
||||
S="${WORKDIR}/${MY_PN}-${PV}"
|
||||
|
||||
# Tests access network, and fail randomly. Bug #431458.
|
||||
RESTRICT=test
|
||||
|
||||
PATCHES=(
|
||||
"${FILESDIR}"/m2crypto-extension-work-0.24.0.patch
|
||||
)
|
||||
|
||||
python_test() {
|
||||
esetup.py test
|
||||
}
|
Loading…
Reference in new issue