user/py3-xmlsec: drop for in aports community

This commit is contained in:
Antoine Martin 2024-04-22 13:00:22 -04:00
parent 97356cba4f
commit b2496b6e09
4 changed files with 0 additions and 1121 deletions

View file

@ -1,925 +0,0 @@
From a7f95d55cd660d1a212fa76a527063b3b7dbe8bb Mon Sep 17 00:00:00 2001
From: Dan Vella <dan.vella@invicti.com>
Date: Fri, 17 Mar 2023 13:58:25 +0100
Subject: [PATCH 1/7] Added changes to enable 3.11 builds
---
.appveyor.yml | 4 ++++
.github/workflows/macosx.yml | 2 +-
.github/workflows/manylinux.yml | 6 +++---
.github/workflows/opensuse-tumbleweed.yml | 2 +-
.github/workflows/sdist.yml | 4 ++--
.travis.yml | 3 +++
setup.py | 1 +
7 files changed, 15 insertions(+), 7 deletions(-)
diff --git a/setup.py b/setup.py
index 9a3c927..5c7e0da 100644
--- a/setup.py
+++ b/setup.py
@@ -533,6 +533,7 @@ def prepare_static_build_linux(self):
'Programming Language :: Python :: 3.7',
'Programming Language :: Python :: 3.8',
'Programming Language :: Python :: 3.9',
+ 'Programming Language :: Python :: 3.11',
'Topic :: Text Processing :: Markup :: XML',
'Typing :: Typed',
],
From b7683774f747c7aed6a0b30e6045da679bc68760 Mon Sep 17 00:00:00 2001
From: Dan Vella <dan.vella@invicti.com>
Date: Fri, 17 Mar 2023 14:00:32 +0100
Subject: [PATCH 2/7] Added changes to enable 3.11 builds
---
.appveyor.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
From bddf28e68a2509a287f9889aaeadc3adab80ccbc Mon Sep 17 00:00:00 2001
From: Dan Vella <dan.vella@invicti.com>
Date: Fri, 17 Mar 2023 14:52:40 +0100
Subject: [PATCH 3/7] bumped isort to 5.11.5
---
.pre-commit-config.yaml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
From 2c58d43eedf72590e3e201252f5fc5ddae36f8c6 Mon Sep 17 00:00:00 2001
From: Tomas Divis <tomas.divis@nic.cz>
Date: Wed, 22 Mar 2023 20:36:45 +0100
Subject: [PATCH 4/7] Fix #244 - Fix failing test with libxmlsec-1.2.36, also
make libxmlsec version available from Python.
---
src/main.c | 13 ++++
tests/data/sign5-out-xmlsec_1_2_36_to_37.xml | 67 ++++++++++++++++++++
tests/test_ds.py | 6 +-
3 files changed, 85 insertions(+), 1 deletion(-)
create mode 100644 tests/data/sign5-out-xmlsec_1_2_36_to_37.xml
diff --git a/src/main.c b/src/main.c
index ffcae14..5773db3 100644
--- a/src/main.c
+++ b/src/main.c
@@ -119,6 +119,13 @@ static PyObject* PyXmlSec_PyShutdown(PyObject* self) {
Py_RETURN_NONE;
}
+static char PyXmlSec_GetLibXmlSecVersion__doc__[] = \
+ "get_libxmlsec_version() -> tuple\n"
+ "Returns Version tuple of wrapped libxml library.";
+static PyObject* PyXmlSec_GetLibXmlSecVersion() {
+ return Py_BuildValue("(iii)", XMLSEC_VERSION_MAJOR, XMLSEC_VERSION_MINOR, XMLSEC_VERSION_SUBMINOR);
+}
+
static char PyXmlSec_PyEnableDebugOutput__doc__[] = \
"enable_debug_trace(enabled) -> None\n"
"Enables or disables calling LibXML2 callback from the default errors callback.\n\n"
@@ -386,6 +393,12 @@ static PyMethodDef PyXmlSec_MainMethods[] = {
METH_NOARGS,
PyXmlSec_PyShutdown__doc__
},
+ {
+ "get_libxmlsec_version",
+ (PyCFunction)PyXmlSec_GetLibXmlSecVersion,
+ METH_NOARGS,
+ PyXmlSec_GetLibXmlSecVersion__doc__
+ },
{
"enable_debug_trace",
(PyCFunction)PyXmlSec_PyEnableDebugOutput,
diff --git a/tests/data/sign5-out-xmlsec_1_2_36_to_37.xml b/tests/data/sign5-out-xmlsec_1_2_36_to_37.xml
new file mode 100644
index 0000000..f359b13
--- /dev/null
+++ b/tests/data/sign5-out-xmlsec_1_2_36_to_37.xml
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+XML Security Library example: Signed XML doc file (sign5 example).
+-->
+<Envelope xmlns="urn:envelope">
+ <Data>
+ Hello, World!
+ </Data>
+<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
+<SignedInfo>
+<CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
+<SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
+<Reference>
+<Transforms>
+<Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
+</Transforms>
+<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
+<DigestValue>HjY8ilZAIEM2tBbPn5mYO1ieIX4=</DigestValue>
+</Reference>
+</SignedInfo>
+<SignatureValue>SIaj/6KY3C1SmDXU2++Gm31U1xTadFp04WhBgfsJFbxrL+q7GKSKN9kfQ+UpN9+i
+D5fWmuavXEHe4Gw6RMaMEkq2URQo7F68+d5J/ajq8/l4n+xE6/reGScVwT6L4dEP
+XXVJcAi2ZnQ3O7GTNvNGCPibL9mUcyCWBFZ92Uemtc/vJFCQ7ZyKMdMfACgxOwyN
+T/9971oog241/2doudhonc0I/3mgPYWkZdX6yvr62mEjnG+oUZkhWYJ4ewZJ4hM4
+JjbFqZO+OEzDRSbw3DkmuBA/mtlx+3t13SESfEub5hqoMdVmtth/eTb64dsPdl9r
+3k1ACVX9f8aHfQQdJOmLFQ==</SignatureValue>
+<KeyInfo>
+<X509Data>
+
+
+
+<X509IssuerSerial>
+<X509IssuerName>Test Issuer</X509IssuerName>
+<X509SerialNumber>1</X509SerialNumber>
+</X509IssuerSerial>
+<X509Certificate>MIIE3zCCBEigAwIBAgIBBTANBgkqhkiG9w0BAQQFADCByzELMAkGA1UEBhMCVVMx
+EzARBgNVBAgTCkNhbGlmb3JuaWExEjAQBgNVBAcTCVN1bm55dmFsZTE9MDsGA1UE
+ChM0WE1MIFNlY3VyaXR5IExpYnJhcnkgKGh0dHA6Ly93d3cuYWxla3NleS5jb20v
+eG1sc2VjKTEZMBcGA1UECxMQUm9vdCBDZXJ0aWZpY2F0ZTEWMBQGA1UEAxMNQWxl
+a3NleSBTYW5pbjEhMB8GCSqGSIb3DQEJARYSeG1sc2VjQGFsZWtzZXkuY29tMB4X
+DTAzMDMzMTA0MDIyMloXDTEzMDMyODA0MDIyMlowgb8xCzAJBgNVBAYTAlVTMRMw
+EQYDVQQIEwpDYWxpZm9ybmlhMT0wOwYDVQQKEzRYTUwgU2VjdXJpdHkgTGlicmFy
+eSAoaHR0cDovL3d3dy5hbGVrc2V5LmNvbS94bWxzZWMpMSEwHwYDVQQLExhFeGFt
+cGxlcyBSU0EgQ2VydGlmaWNhdGUxFjAUBgNVBAMTDUFsZWtzZXkgU2FuaW4xITAf
+BgkqhkiG9w0BCQEWEnhtbHNlY0BhbGVrc2V5LmNvbTCCASIwDQYJKoZIhvcNAQEB
+BQADggEPADCCAQoCggEBAJe4/rQ/gzV4FokE7CthjL/EXwCBSkXm2c3p4jyXO0Wt
+quaNC3dxBwFPfPl94hmq3ZFZ9PHPPbp4RpYRnLZbRjlzVSOq954AXOXpSew7nD+E
+mTqQrd9+ZIbGJnLOMQh5fhMVuOW/1lYCjWAhTCcYZPv7VXD2M70vVXDVXn6ZrqTg
+qkVHE6gw1aCKncwg7OSOUclUxX8+Zi10v6N6+PPslFc5tKwAdWJhVLTQ4FKG+F53
+7FBDnNK6p4xiWryy/vPMYn4jYGvHUUk3eH4lFTCr+rSuJY8i/KNIf/IKim7g/o3w
+Ae3GM8xrof2mgO8GjK/2QDqOQhQgYRIf4/wFsQXVZcMCAwEAAaOCAVcwggFTMAkG
+A1UdEwQCMAAwLAYJYIZIAYb4QgENBB8WHU9wZW5TU0wgR2VuZXJhdGVkIENlcnRp
+ZmljYXRlMB0GA1UdDgQWBBQkhCzy1FkgYosuXIaQo6owuicanDCB+AYDVR0jBIHw
+MIHtgBS0ue+a5pcOaGUemM76VQ2JBttMfKGB0aSBzjCByzELMAkGA1UEBhMCVVMx
+EzARBgNVBAgTCkNhbGlmb3JuaWExEjAQBgNVBAcTCVN1bm55dmFsZTE9MDsGA1UE
+ChM0WE1MIFNlY3VyaXR5IExpYnJhcnkgKGh0dHA6Ly93d3cuYWxla3NleS5jb20v
+eG1sc2VjKTEZMBcGA1UECxMQUm9vdCBDZXJ0aWZpY2F0ZTEWMBQGA1UEAxMNQWxl
+a3NleSBTYW5pbjEhMB8GCSqGSIb3DQEJARYSeG1sc2VjQGFsZWtzZXkuY29tggEA
+MA0GCSqGSIb3DQEBBAUAA4GBALU/mzIxSv8vhDuomxFcplzwdlLZbvSQrfoNkMGY
+1UoS3YJrN+jZLWKSyWE3mIaPpElqXiXQGGkwD5iPQ1iJMbI7BeLvx6ZxX/f+c8Wn
+ss0uc1NxfahMaBoyG15IL4+beqO182fosaKJTrJNG3mc//ANGU9OsQM9mfBEt4oL
+NJ2D</X509Certificate>
+<X509SubjectName/>
+<X509SKI/>
+</X509Data>
+</KeyInfo>
+</Signature></Envelope>
diff --git a/tests/test_ds.py b/tests/test_ds.py
index 694ad43..38f0b25 100644
--- a/tests/test_ds.py
+++ b/tests/test_ds.py
@@ -182,7 +182,11 @@ def test_sign_case5(self):
self.assertEqual("rsakey.pem", ctx.key.name)
ctx.sign(sign)
- self.assertEqual(self.load_xml("sign5-out.xml"), root)
+ if (1, 2, 36) <= xmlsec.get_libxmlsec_version() <= (1, 2, 37):
+ expected_xml_file = 'sign5-out-xmlsec_1_2_36_to_37.xml'
+ else:
+ expected_xml_file = 'sign5-out.xml'
+ self.assertEqual(self.load_xml(expected_xml_file), root)
def test_sign_binary_bad_args(self):
ctx = xmlsec.SignatureContext()
From 1cf6785b3e06c2b8f6cac1266cf8f1934650bc4b Mon Sep 17 00:00:00 2001
From: Tomas Divis <tomas.divis@nic.cz>
Date: Wed, 21 Dec 2022 14:01:14 +0100
Subject: [PATCH 5/7] Fix #164 - Add support for loading keys from engine (e.g.
pkcs11).
---
README.rst | 2 +-
src/keys.c | 47 +++++++++++++++++++++++++++++++++++++++++
src/xmlsec/__init__.pyi | 2 ++
3 files changed, 50 insertions(+), 1 deletion(-)
diff --git a/README.rst b/README.rst
index 34bdd37..e192465 100644
--- a/README.rst
+++ b/README.rst
@@ -37,7 +37,7 @@ Check the `examples <https://xmlsec.readthedocs.io/en/latest/examples.html>`_ se
Requirements
************
- ``libxml2 >= 2.9.1``
-- ``libxmlsec1 >= 1.2.18``
+- ``libxmlsec1 >= 1.2.33``
Install
*******
diff --git a/src/keys.c b/src/keys.c
index 1362b12..1440331 100644
--- a/src/keys.c
+++ b/src/keys.c
@@ -185,6 +185,47 @@ static PyObject* PyXmlSec_KeyFromFile(PyObject* self, PyObject* args, PyObject*
return NULL;
}
+static const char PyXmlSec_KeyFromEngine__doc__[] = \
+ "from_engine(engine_and_key_id) -> xmlsec.Key\n"
+ "Loads PKI key from an engine.\n\n"
+ ":param engine_and_key_id: engine and key id, i.e. 'pkcs11;pkcs11:token=XmlsecToken;object=XmlsecKey;pin-value=password'\n"
+ ":type engine_and_key_id: :class:`str`, "
+ ":return: pointer to newly created key\n"
+ ":rtype: :class:`~xmlsec.Key`";
+static PyObject* PyXmlSec_KeyFromEngine(PyObject* self, PyObject* args, PyObject* kwargs) {
+ static char *kwlist[] = {"engine_and_key_id", NULL};
+
+ const char* engine_and_key_id = NULL;
+ PyXmlSec_Key* key = NULL;
+
+ PYXMLSEC_DEBUG("load key from engine - start");
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s:from_engine", kwlist, &engine_and_key_id)) {
+ goto ON_FAIL;
+ }
+
+ if ((key = PyXmlSec_NewKey1((PyTypeObject*)self)) == NULL) goto ON_FAIL;
+
+ Py_BEGIN_ALLOW_THREADS;
+ key->handle = xmlSecCryptoAppKeyLoad(engine_and_key_id, xmlSecKeyDataFormatEngine, NULL, xmlSecCryptoAppGetDefaultPwdCallback(),
+ (void*)engine_and_key_id);
+ Py_END_ALLOW_THREADS;
+
+ if (key->handle == NULL) {
+ PyXmlSec_SetLastError("cannot read key");
+ goto ON_FAIL;
+ }
+
+ key->is_own = 1;
+
+ PYXMLSEC_DEBUG("load key from engine - ok");
+ return (PyObject*)key;
+
+ON_FAIL:
+ PYXMLSEC_DEBUG("load key from engine - fail");
+ Py_XDECREF(key);
+ return NULL;
+}
+
static const char PyXmlSec_KeyGenerate__doc__[] = \
"generate(klass, size, type) -> xmlsec.Key\n"
"Generates key of kind ``klass`` with ``size`` and ``type``.\n\n"
@@ -494,6 +535,12 @@ static PyMethodDef PyXmlSec_KeyMethods[] = {
METH_CLASS|METH_VARARGS|METH_KEYWORDS,
PyXmlSec_KeyFromFile__doc__
},
+ {
+ "from_engine",
+ (PyCFunction)PyXmlSec_KeyFromEngine,
+ METH_CLASS|METH_VARARGS|METH_KEYWORDS,
+ PyXmlSec_KeyFromEngine__doc__
+ },
{
"generate",
(PyCFunction)PyXmlSec_KeyGenerate,
diff --git a/src/xmlsec/__init__.pyi b/src/xmlsec/__init__.pyi
index 56356e5..6c326f5 100644
--- a/src/xmlsec/__init__.pyi
+++ b/src/xmlsec/__init__.pyi
@@ -49,6 +49,8 @@ class Key:
@classmethod
def from_file(cls: type[Self], file: GenericPath[AnyStr] | IO[AnyStr], format: int, password: str | None = ...) -> Self: ...
@classmethod
+ def from_engine(cls: type[Self], engine_and_key_id: AnyStr) -> Self: ...
+ @classmethod
def from_memory(cls: type[Self], data: AnyStr, format: int, password: str | None = ...) -> Self: ...
@classmethod
def generate(cls: type[Self], klass: KeyData, size: int, type: int) -> Self: ...
From 0b5939fc65e98cebb669d311b4fb58844bf887e5 Mon Sep 17 00:00:00 2001
From: Tomas Divis <tomas.divis@nic.cz>
Date: Thu, 13 Apr 2023 14:28:02 +0200
Subject: [PATCH 6/7] Fix #164 - Add tests for pkcs11 (softhsm) key.
---
.github/workflows/sdist.yml | 3 +-
tests/softhsm_setup.py | 265 ++++++++++++++++++++++++++++++++++++
tests/test_pkcs11.py | 57 ++++++++
3 files changed, 323 insertions(+), 2 deletions(-)
create mode 100644 tests/softhsm_setup.py
create mode 100644 tests/test_pkcs11.py
diff --git a/tests/softhsm_setup.py b/tests/softhsm_setup.py
new file mode 100644
index 0000000..0a7c37d
--- /dev/null
+++ b/tests/softhsm_setup.py
@@ -0,0 +1,265 @@
+"""
+Testing the PKCS#11 shim layer.
+Heavily inspired by from https://github.com/IdentityPython/pyXMLSecurity by leifj
+under licence "As is", see https://github.com/IdentityPython/pyXMLSecurity/blob/master/LICENSE.txt
+"""
+
+import logging
+import os
+import shutil
+import subprocess
+import tempfile
+import traceback
+import unittest
+from typing import Dict, List, Optional, Tuple
+
+DATA_DIR = os.path.join(os.path.dirname(__file__), "data")
+
+
+def paths_for_component(component: str, default_paths: List[str]):
+ env_path = os.environ.get(component)
+ return [env_path] if env_path else default_paths
+
+
+def find_alts(component_name, alts: List[str]) -> str:
+ for a in alts:
+ if os.path.exists(a):
+ return a
+ raise unittest.SkipTest("Required component is missing: {}".format(component_name))
+
+
+def run_cmd(args, softhsm_conf=None) -> Tuple[bytes, bytes]:
+ env = {}
+ if softhsm_conf is not None:
+ env['SOFTHSM_CONF'] = softhsm_conf
+ env['SOFTHSM2_CONF'] = softhsm_conf
+ proc = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=env)
+ out, err = proc.communicate()
+ if err is not None and len(err) > 0:
+ logging.error(err)
+ if out is not None and len(out) > 0:
+ logging.debug(out)
+ rv = proc.wait()
+ if rv:
+ with open(softhsm_conf) as f:
+ conf = f.read()
+ msg = '[cmd: {cmd}] [code: {code}] [stdout: {out}] [stderr: {err}] [config: {conf}]'
+ msg = msg.format(
+ cmd=" ".join(args), code=rv, out=out.strip(), err=err.strip(), conf=conf,
+ )
+ raise RuntimeError(msg)
+ return out, err
+
+
+component_default_paths: Dict[str, List[str]] = {
+ 'P11_MODULE': [
+ '/usr/lib/softhsm/libsofthsm2.so',
+ '/usr/lib/x86_64-linux-gnu/softhsm/libsofthsm2.so',
+ '/usr/lib/softhsm/libsofthsm.so',
+ '/usr/lib64/softhsm/libsofthsm2.so',
+ ],
+ 'P11_ENGINE': [
+ '/usr/lib/ssl/engines/libpkcs11.so',
+ '/usr/lib/engines/engine_pkcs11.so',
+ '/usr/lib/x86_64-linux-gnu/engines-1.1/pkcs11.so',
+ '/usr/lib64/engines-1.1/pkcs11.so',
+ '/usr/lib64/engines-1.1/libpkcs11.so',
+ '/usr/lib64/engines-3/pkcs11.so',
+ '/usr/lib64/engines-3/libpkcs11.so',
+ '/usr/lib/x86_64-linux-gnu/engines-3/pkcs11.so',
+ '/usr/lib/x86_64-linux-gnu/engines-3/libpkcs11.so',
+ ],
+ 'PKCS11_TOOL': [
+ '/usr/bin/pkcs11-tool',
+ ],
+ 'SOFTHSM': [
+ '/usr/bin/softhsm2-util',
+ '/usr/bin/softhsm',
+ ],
+ 'OPENSSL': [
+ '/usr/bin/openssl',
+ ],
+}
+
+component_path: Dict[str, str] = {
+ component_name: find_alts(component_name, paths_for_component(component_name, default_paths))
+ for component_name, default_paths in component_default_paths.items()
+}
+
+softhsm_version = 1
+if component_path['SOFTHSM'].endswith('softhsm2-util'):
+ softhsm_version = 2
+
+openssl_version = subprocess.check_output([component_path['OPENSSL'],
+ 'version']
+ )[8:11].decode()
+
+p11_test_files: List[str] = []
+softhsm_conf: Optional[str] = None
+softhsm_db: Optional[str] = None
+
+
+def _temp_file() -> str:
+ f = tempfile.NamedTemporaryFile(delete=False)
+ p11_test_files.append(f.name)
+ return f.name
+
+
+def _temp_dir() -> str:
+ d = tempfile.mkdtemp()
+ p11_test_files.append(d)
+ return d
+
+
+@unittest.skipIf(component_path['P11_MODULE'] is None, "SoftHSM PKCS11 module not installed")
+def setup() -> None:
+ logging.debug("Creating test pkcs11 token using softhsm")
+ try:
+ global softhsm_conf
+ softhsm_conf = _temp_file()
+ logging.debug("Generating softhsm.conf")
+ with open(softhsm_conf, "w") as f:
+ if softhsm_version == 2:
+ softhsm_db = _temp_dir()
+ f.write("""
+# Generated by test
+directories.tokendir = %s
+objectstore.backend = file
+log.level = DEBUG
+""" % softhsm_db)
+ else:
+ softhsm_db = _temp_file()
+ f.write("""
+# Generated by test
+0:%s
+""" % softhsm_db)
+
+ logging.debug("Initializing the token")
+ out, err = run_cmd([component_path['SOFTHSM'],
+ '--slot', '0',
+ '--label', 'test',
+ '--init-token',
+ '--pin', 'secret1',
+ '--so-pin', 'secret2'],
+ softhsm_conf=softhsm_conf)
+
+ # logging.debug("Generating 1024 bit RSA key in token")
+ # run_cmd([component_path['PKCS11_TOOL'],
+ # '--module', component_path['P11_MODULE'],
+ # '-l',
+ # '-k',
+ # '--key-type', 'rsa:1024',
+ # '--id', 'a1b2',
+ # '--label', 'test',
+ # '--pin', 'secret1'], softhsm_conf=softhsm_conf)
+
+ hash_priv_key = _temp_file()
+ logging.debug("Converting test private key to format for softhsm")
+ run_cmd([component_path['OPENSSL'], 'pkcs8',
+ '-topk8',
+ '-inform', 'PEM',
+ '-outform', 'PEM',
+ '-nocrypt',
+ '-in', os.path.join(DATA_DIR, 'rsakey.pem'),
+ '-out', hash_priv_key], softhsm_conf=softhsm_conf)
+
+ logging.debug("Importing the test key to softhsm")
+ run_cmd([component_path['SOFTHSM'],
+ '--import', hash_priv_key,
+ '--token', 'test',
+ '--id', 'a1b2',
+ '--label', 'test',
+ '--pin', 'secret1'],
+ softhsm_conf=softhsm_conf)
+ run_cmd([component_path['PKCS11_TOOL'],
+ '--module', component_path['P11_MODULE'],
+ '-l',
+ '--pin', 'secret1', '-O'], softhsm_conf=softhsm_conf)
+ signer_cert_pem = _temp_file()
+ openssl_conf = _temp_file()
+ logging.debug("Generating OpenSSL config for version {}".format(openssl_version))
+ with open(openssl_conf, "w") as f:
+ # Might be needed with some versions of openssl, but in more recent versions dynamic_path breaks it.
+ # dynamic_path = (
+ # "dynamic_path = %s" % component_path['P11_ENGINE']
+ # if openssl_version.startswith(b'1.')
+ # else ""
+ # )
+ f.write("\n".join([
+ "openssl_conf = openssl_def",
+ "[openssl_def]",
+ "engines = engine_section",
+ "[engine_section]",
+ "pkcs11 = pkcs11_section",
+ "[req]",
+ "distinguished_name = req_distinguished_name",
+ "[req_distinguished_name]",
+ "[pkcs11_section]",
+ "engine_id = pkcs11",
+ # dynamic_path,
+ "MODULE_PATH = %s" % component_path['P11_MODULE'],
+ "init = 0",
+ ]))
+
+ with open(openssl_conf, "r") as f:
+ logging.debug('-------- START DEBUG openssl_conf --------')
+ logging.debug(f.readlines())
+ logging.debug('-------- END DEBUG openssl_conf --------')
+ logging.debug('-------- START DEBUG paths --------')
+ logging.debug(run_cmd(['ls', '-ld', component_path['P11_ENGINE']]))
+ logging.debug(run_cmd(['ls', '-ld', component_path['P11_MODULE']]))
+ logging.debug('-------- END DEBUG paths --------')
+
+ signer_cert_der = _temp_file()
+
+ logging.debug("Generating self-signed certificate")
+ run_cmd([component_path['OPENSSL'], 'req',
+ '-new',
+ '-x509',
+ '-subj', "/CN=Test Signer",
+ '-engine', 'pkcs11',
+ '-config', openssl_conf,
+ '-keyform', 'engine',
+ '-key', 'label_test',
+ '-passin', 'pass:secret1',
+ '-out', signer_cert_pem], softhsm_conf=softhsm_conf)
+
+ run_cmd([component_path['OPENSSL'], 'x509',
+ '-inform', 'PEM',
+ '-outform', 'DER',
+ '-in', signer_cert_pem,
+ '-out', signer_cert_der], softhsm_conf=softhsm_conf)
+
+ logging.debug("Importing certificate into token")
+
+ run_cmd([component_path['PKCS11_TOOL'],
+ '--module', component_path['P11_MODULE'],
+ '-l',
+ '--slot-index', '0',
+ '--id', 'a1b2',
+ '--label', 'test',
+ '-y', 'cert',
+ '-w', signer_cert_der,
+ '--pin', 'secret1'], softhsm_conf=softhsm_conf)
+
+ # TODO: Should be teardowned in teardown:
+ os.environ['SOFTHSM_CONF'] = softhsm_conf
+ os.environ['SOFTHSM2_CONF'] = softhsm_conf
+
+ except Exception as ex:
+ print("-" * 64)
+ traceback.print_exc()
+ print("-" * 64)
+ logging.error("PKCS11 tests disabled: unable to initialize test token: %s" % ex)
+ raise ex
+
+
+def teardown() -> None:
+ global p11_test_files
+ for o in p11_test_files:
+ if os.path.exists(o):
+ if os.path.isdir(o):
+ shutil.rmtree(o)
+ else:
+ os.unlink(o)
+ p11_test_files = []
diff --git a/tests/test_pkcs11.py b/tests/test_pkcs11.py
new file mode 100644
index 0000000..accd29a
--- /dev/null
+++ b/tests/test_pkcs11.py
@@ -0,0 +1,57 @@
+import xmlsec
+from tests import base
+from xmlsec import constants as consts
+
+KEY_URL = "pkcs11;pkcs11:token=test;object=test;pin-value=secret1"
+
+
+def setUpModule():
+ from tests import softhsm_setup
+
+ softhsm_setup.setup()
+
+
+def tearDownModule():
+ from tests import softhsm_setup
+
+ softhsm_setup.teardown()
+
+
+class TestKeys(base.TestMemoryLeaks):
+ def test_del_key(self):
+ ctx = xmlsec.SignatureContext(manager=xmlsec.KeysManager())
+ ctx.key = xmlsec.Key.from_engine(KEY_URL)
+ del ctx.key
+ self.assertIsNone(ctx.key)
+
+ def test_set_key(self):
+ ctx = xmlsec.SignatureContext(manager=xmlsec.KeysManager())
+ ctx.key = xmlsec.Key.from_engine(KEY_URL)
+ self.assertIsNotNone(ctx.key)
+
+ def test_sign_bad_args(self):
+ ctx = xmlsec.SignatureContext()
+ ctx.key = xmlsec.Key.from_engine(KEY_URL)
+ with self.assertRaises(TypeError):
+ ctx.sign('')
+
+ def test_sign_fail(self):
+ ctx = xmlsec.SignatureContext()
+ ctx.key = xmlsec.Key.from_engine(KEY_URL)
+ with self.assertRaisesRegex(xmlsec.Error, 'failed to sign'):
+ ctx.sign(self.load_xml('sign1-in.xml'))
+
+ def test_sign_case1(self):
+ """Should sign a pre-constructed template file using a key from a pkcs11 engine."""
+ root = self.load_xml("sign1-in.xml")
+ sign = xmlsec.tree.find_node(root, consts.NodeSignature)
+ self.assertIsNotNone(sign)
+
+ ctx = xmlsec.SignatureContext()
+ ctx.key = xmlsec.Key.from_engine(KEY_URL)
+ self.assertIsNotNone(ctx.key)
+ ctx.key.name = 'rsakey.pem'
+ self.assertEqual("rsakey.pem", ctx.key.name)
+
+ ctx.sign(sign)
+ self.assertEqual(self.load_xml("sign1-out.xml"), root)
From 4f5daea286df89c64fbfc615f422be62b2cdf114 Mon Sep 17 00:00:00 2001
From: "pre-commit-ci[bot]"
<66853113+pre-commit-ci[bot]@users.noreply.github.com>
Date: Mon, 17 Apr 2023 11:55:28 +0000
Subject: [PATCH 7/7] [pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci
---
tests/softhsm_setup.py | 220 +++++++++++++++++++++++++++--------------
1 file changed, 147 insertions(+), 73 deletions(-)
diff --git a/tests/softhsm_setup.py b/tests/softhsm_setup.py
index 0a7c37d..432d4b1 100644
--- a/tests/softhsm_setup.py
+++ b/tests/softhsm_setup.py
@@ -45,7 +45,11 @@ def run_cmd(args, softhsm_conf=None) -> Tuple[bytes, bytes]:
conf = f.read()
msg = '[cmd: {cmd}] [code: {code}] [stdout: {out}] [stderr: {err}] [config: {conf}]'
msg = msg.format(
- cmd=" ".join(args), code=rv, out=out.strip(), err=err.strip(), conf=conf,
+ cmd=" ".join(args),
+ code=rv,
+ out=out.strip(),
+ err=err.strip(),
+ conf=conf,
)
raise RuntimeError(msg)
return out, err
@@ -90,9 +94,7 @@ def run_cmd(args, softhsm_conf=None) -> Tuple[bytes, bytes]:
if component_path['SOFTHSM'].endswith('softhsm2-util'):
softhsm_version = 2
-openssl_version = subprocess.check_output([component_path['OPENSSL'],
- 'version']
- )[8:11].decode()
+openssl_version = subprocess.check_output([component_path['OPENSSL'], 'version'])[8:11].decode()
p11_test_files: List[str] = []
softhsm_conf: Optional[str] = None
@@ -121,27 +123,41 @@ def setup() -> None:
with open(softhsm_conf, "w") as f:
if softhsm_version == 2:
softhsm_db = _temp_dir()
- f.write("""
+ f.write(
+ """
# Generated by test
directories.tokendir = %s
objectstore.backend = file
log.level = DEBUG
-""" % softhsm_db)
+"""
+ % softhsm_db
+ )
else:
softhsm_db = _temp_file()
- f.write("""
+ f.write(
+ """
# Generated by test
0:%s
-""" % softhsm_db)
+"""
+ % softhsm_db
+ )
logging.debug("Initializing the token")
- out, err = run_cmd([component_path['SOFTHSM'],
- '--slot', '0',
- '--label', 'test',
- '--init-token',
- '--pin', 'secret1',
- '--so-pin', 'secret2'],
- softhsm_conf=softhsm_conf)
+ out, err = run_cmd(
+ [
+ component_path['SOFTHSM'],
+ '--slot',
+ '0',
+ '--label',
+ 'test',
+ '--init-token',
+ '--pin',
+ 'secret1',
+ '--so-pin',
+ 'secret2',
+ ],
+ softhsm_conf=softhsm_conf,
+ )
# logging.debug("Generating 1024 bit RSA key in token")
# run_cmd([component_path['PKCS11_TOOL'],
@@ -155,26 +171,45 @@ def setup() -> None:
hash_priv_key = _temp_file()
logging.debug("Converting test private key to format for softhsm")
- run_cmd([component_path['OPENSSL'], 'pkcs8',
- '-topk8',
- '-inform', 'PEM',
- '-outform', 'PEM',
- '-nocrypt',
- '-in', os.path.join(DATA_DIR, 'rsakey.pem'),
- '-out', hash_priv_key], softhsm_conf=softhsm_conf)
+ run_cmd(
+ [
+ component_path['OPENSSL'],
+ 'pkcs8',
+ '-topk8',
+ '-inform',
+ 'PEM',
+ '-outform',
+ 'PEM',
+ '-nocrypt',
+ '-in',
+ os.path.join(DATA_DIR, 'rsakey.pem'),
+ '-out',
+ hash_priv_key,
+ ],
+ softhsm_conf=softhsm_conf,
+ )
logging.debug("Importing the test key to softhsm")
- run_cmd([component_path['SOFTHSM'],
- '--import', hash_priv_key,
- '--token', 'test',
- '--id', 'a1b2',
- '--label', 'test',
- '--pin', 'secret1'],
- softhsm_conf=softhsm_conf)
- run_cmd([component_path['PKCS11_TOOL'],
- '--module', component_path['P11_MODULE'],
- '-l',
- '--pin', 'secret1', '-O'], softhsm_conf=softhsm_conf)
+ run_cmd(
+ [
+ component_path['SOFTHSM'],
+ '--import',
+ hash_priv_key,
+ '--token',
+ 'test',
+ '--id',
+ 'a1b2',
+ '--label',
+ 'test',
+ '--pin',
+ 'secret1',
+ ],
+ softhsm_conf=softhsm_conf,
+ )
+ run_cmd(
+ [component_path['PKCS11_TOOL'], '--module', component_path['P11_MODULE'], '-l', '--pin', 'secret1', '-O'],
+ softhsm_conf=softhsm_conf,
+ )
signer_cert_pem = _temp_file()
openssl_conf = _temp_file()
logging.debug("Generating OpenSSL config for version {}".format(openssl_version))
@@ -185,21 +220,25 @@ def setup() -> None:
# if openssl_version.startswith(b'1.')
# else ""
# )
- f.write("\n".join([
- "openssl_conf = openssl_def",
- "[openssl_def]",
- "engines = engine_section",
- "[engine_section]",
- "pkcs11 = pkcs11_section",
- "[req]",
- "distinguished_name = req_distinguished_name",
- "[req_distinguished_name]",
- "[pkcs11_section]",
- "engine_id = pkcs11",
- # dynamic_path,
- "MODULE_PATH = %s" % component_path['P11_MODULE'],
- "init = 0",
- ]))
+ f.write(
+ "\n".join(
+ [
+ "openssl_conf = openssl_def",
+ "[openssl_def]",
+ "engines = engine_section",
+ "[engine_section]",
+ "pkcs11 = pkcs11_section",
+ "[req]",
+ "distinguished_name = req_distinguished_name",
+ "[req_distinguished_name]",
+ "[pkcs11_section]",
+ "engine_id = pkcs11",
+ # dynamic_path,
+ "MODULE_PATH = %s" % component_path['P11_MODULE'],
+ "init = 0",
+ ]
+ )
+ )
with open(openssl_conf, "r") as f:
logging.debug('-------- START DEBUG openssl_conf --------')
@@ -213,34 +252,69 @@ def setup() -> None:
signer_cert_der = _temp_file()
logging.debug("Generating self-signed certificate")
- run_cmd([component_path['OPENSSL'], 'req',
- '-new',
- '-x509',
- '-subj', "/CN=Test Signer",
- '-engine', 'pkcs11',
- '-config', openssl_conf,
- '-keyform', 'engine',
- '-key', 'label_test',
- '-passin', 'pass:secret1',
- '-out', signer_cert_pem], softhsm_conf=softhsm_conf)
-
- run_cmd([component_path['OPENSSL'], 'x509',
- '-inform', 'PEM',
- '-outform', 'DER',
- '-in', signer_cert_pem,
- '-out', signer_cert_der], softhsm_conf=softhsm_conf)
+ run_cmd(
+ [
+ component_path['OPENSSL'],
+ 'req',
+ '-new',
+ '-x509',
+ '-subj',
+ "/CN=Test Signer",
+ '-engine',
+ 'pkcs11',
+ '-config',
+ openssl_conf,
+ '-keyform',
+ 'engine',
+ '-key',
+ 'label_test',
+ '-passin',
+ 'pass:secret1',
+ '-out',
+ signer_cert_pem,
+ ],
+ softhsm_conf=softhsm_conf,
+ )
+
+ run_cmd(
+ [
+ component_path['OPENSSL'],
+ 'x509',
+ '-inform',
+ 'PEM',
+ '-outform',
+ 'DER',
+ '-in',
+ signer_cert_pem,
+ '-out',
+ signer_cert_der,
+ ],
+ softhsm_conf=softhsm_conf,
+ )
logging.debug("Importing certificate into token")
- run_cmd([component_path['PKCS11_TOOL'],
- '--module', component_path['P11_MODULE'],
- '-l',
- '--slot-index', '0',
- '--id', 'a1b2',
- '--label', 'test',
- '-y', 'cert',
- '-w', signer_cert_der,
- '--pin', 'secret1'], softhsm_conf=softhsm_conf)
+ run_cmd(
+ [
+ component_path['PKCS11_TOOL'],
+ '--module',
+ component_path['P11_MODULE'],
+ '-l',
+ '--slot-index',
+ '0',
+ '--id',
+ 'a1b2',
+ '--label',
+ 'test',
+ '-y',
+ 'cert',
+ '-w',
+ signer_cert_der,
+ '--pin',
+ 'secret1',
+ ],
+ softhsm_conf=softhsm_conf,
+ )
# TODO: Should be teardowned in teardown:
os.environ['SOFTHSM_CONF'] = softhsm_conf

View file

@ -1,105 +0,0 @@
From 5f57f2eac756df213e83a2fdb452057909e2dd21 Mon Sep 17 00:00:00 2001
From: David Adamec <david.adamec@airship.com>
Date: Fri, 15 Sep 2023 17:49:15 -0700
Subject: [PATCH 1/3] Add compatibility for xmlsec 1.3
---
doc/source/modules/constants.rst | 6 ------
src/constants.c | 2 --
src/enc.c | 7 +++++++
src/xmlsec/constants.pyi | 2 --
4 files changed, 7 insertions(+), 10 deletions(-)
diff --git a/src/constants.c b/src/constants.c
index 34c81b2..72ae217 100644
--- a/src/constants.c
+++ b/src/constants.c
@@ -316,8 +316,6 @@ int PyXmlSec_ConstantsModule_Init(PyObject* package) {
PYXMLSEC_ADD_NS_CONSTANT(XPathNs, "XPATH");
PYXMLSEC_ADD_NS_CONSTANT(XPath2Ns, "XPATH2");
PYXMLSEC_ADD_NS_CONSTANT(XPointerNs, "XPOINTER");
- PYXMLSEC_ADD_NS_CONSTANT(Soap11Ns, "SOAP11");
- PYXMLSEC_ADD_NS_CONSTANT(Soap12Ns, "SOAP12");
PYXMLSEC_ADD_NS_CONSTANT(NsExcC14N, "EXC_C14N");
PYXMLSEC_ADD_NS_CONSTANT(NsExcC14NWithComments, "EXC_C14N_WITH_COMMENT");
diff --git a/src/enc.c b/src/enc.c
index aaf35ae..475cd2d 100644
--- a/src/enc.c
+++ b/src/enc.c
@@ -50,6 +50,13 @@ static int PyXmlSec_EncryptionContext__init__(PyObject* self, PyObject* args, Py
}
ctx->manager = manager;
PYXMLSEC_DEBUGF("%p: init enc context - ok, manager - %p", self, manager);
+
+ // xmlsec 1.3 changed the key search to strict mode, causing various examples
+ // in the docs to fail. For backwards compatibility, this changes it back to
+ // lax mode for now.
+ ctx->handle->keyInfoReadCtx.flags = XMLSEC_KEYINFO_FLAGS_LAX_KEY_SEARCH;
+ ctx->handle->keyInfoWriteCtx.flags = XMLSEC_KEYINFO_FLAGS_LAX_KEY_SEARCH;
+
return 0;
ON_FAIL:
PYXMLSEC_DEBUGF("%p: init enc context - failed", self);
diff --git a/src/xmlsec/constants.pyi b/src/xmlsec/constants.pyi
index 3430a02..9fd24e5 100644
--- a/src/xmlsec/constants.pyi
+++ b/src/xmlsec/constants.pyi
@@ -85,8 +85,6 @@ NodeX509Data: Final[str]
Ns: Final[str]
NsExcC14N: Final[str]
NsExcC14NWithComments: Final[str]
-Soap11Ns: Final[str]
-Soap12Ns: Final[str]
TransformAes128Cbc: Final[__Transform]
TransformAes128Gcm: Final[__Transform]
TransformAes192Cbc: Final[__Transform]
From 0e7c5e718e8d221331b0a5f851094a5b4181eeae Mon Sep 17 00:00:00 2001
From: David Adamec <david.adamec@airship.com>
Date: Fri, 15 Sep 2023 18:07:07 -0700
Subject: [PATCH 2/3] fix 1.2 compatibility
---
src/enc.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/src/enc.c b/src/enc.c
index 475cd2d..5453ef9 100644
--- a/src/enc.c
+++ b/src/enc.c
@@ -17,6 +17,11 @@
#include <xmlsec/xmlenc.h>
#include <xmlsec/xmltree.h>
+// Backwards compatibility with xmlsec 1.2
+#ifndef XMLSEC_KEYINFO_FLAGS_LAX_KEY_SEARCH
+#define XMLSEC_KEYINFO_FLAGS_LAX_KEY_SEARCH 0x00008000
+#endif
+
typedef struct {
PyObject_HEAD
xmlSecEncCtxPtr handle;
From 40c14c45a352f2812e796a071ef7d12f5a70be58 Mon Sep 17 00:00:00 2001
From: David Adamec <david.adamec@airship.com>
Date: Fri, 15 Sep 2023 19:40:04 -0700
Subject: [PATCH 3/3] update isort to fix poetry error in pre-commit
---
.pre-commit-config.yaml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 0545b12..bf877f3 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -31,7 +31,7 @@ repos:
exclude: ^setup.py$
additional_dependencies: [flake8-docstrings, flake8-bugbear, flake8-logging-format, flake8-builtins, flake8-eradicate, flake8-fixme, pep8-naming, flake8-pep3101, flake8-annotations-complexity,flake8-pyi]
- repo: https://github.com/PyCQA/isort
- rev: 5.10.1
+ rev: 5.12.0
hooks:
- id: isort
- repo: https://github.com/pre-commit/mirrors-mypy

View file

@ -1,35 +0,0 @@
diff --git a/src/constants.c.orig b/src/constants.c
index 72ae217..b12d0ad 100644
--- a/src/constants.c.orig
+++ b/src/constants.c
@@ -445,7 +445,7 @@ int PyXmlSec_ConstantsModule_Init(PyObject* package) {
#endif
#if XMLSEC_VERSION_HEX > 0x10212
// from version 1.2.19
- PYXMLSEC_ADD_KEYDATA_CONSTANT(KeyDataEcdsa, "ECDSA")
+ PYXMLSEC_ADD_KEYDATA_CONSTANT(KeyDataEc, "ECDSA")
#endif
PYXMLSEC_ADD_KEYDATA_CONSTANT(KeyDataHmac, "HMAC")
PYXMLSEC_ADD_KEYDATA_CONSTANT(KeyDataRsa, "RSA")
diff --git a/src/keys.c.orig b/src/keys.c
index 1440331..8b84c34 100644
--- a/src/keys.c.orig
+++ b/src/keys.c
@@ -163,7 +163,7 @@ static PyObject* PyXmlSec_KeyFromFile(PyObject* self, PyObject* args, PyObject*
if (is_content) {
key->handle = xmlSecCryptoAppKeyLoadMemory((const xmlSecByte*)data, (xmlSecSize)data_size, format, password, NULL, NULL);
} else {
- key->handle = xmlSecCryptoAppKeyLoad(data, format, password, NULL, NULL);
+ key->handle = xmlSecCryptoAppKeyLoadEx(data, xmlSecKeyDataTypePrivate, format, password, NULL, NULL);
}
Py_END_ALLOW_THREADS;
@@ -206,7 +206,7 @@ static PyObject* PyXmlSec_KeyFromEngine(PyObject* self, PyObject* args, PyObject
if ((key = PyXmlSec_NewKey1((PyTypeObject*)self)) == NULL) goto ON_FAIL;
Py_BEGIN_ALLOW_THREADS;
- key->handle = xmlSecCryptoAppKeyLoad(engine_and_key_id, xmlSecKeyDataFormatEngine, NULL, xmlSecCryptoAppGetDefaultPwdCallback(),
+ key->handle = xmlSecCryptoAppKeyLoadEx(engine_and_key_id, xmlSecKeyDataTypePrivate, xmlSecKeyDataFormatEngine, NULL, xmlSecCryptoAppGetDefaultPwdCallback(),
(void*)engine_and_key_id);
Py_END_ALLOW_THREADS;

View file

@ -1,56 +0,0 @@
# Contributor: Antoine Martin (ayakael) <dev@ayakael.net>
# Maintainer: Antoine Martin (ayakael) <dev@ayakael.net>
_pyname=xmlsec
pkgname="py3-$_pyname"
pkgver=1.3.13
pkgrel=6
arch="all"
pkgdesc="Python bindings for the XML Security Library"
url="https://pypi.python.org/project/$_pyname"
license="MIT"
depends="
py3-lxml
xmlsec
"
makedepends="
py3-gpep517
py3-setuptools
py3-setuptools_scm
py3-pkgconfig
py3-wheel
python3-dev
libxml2-dev
xmlsec-dev
"
checkdepends="py3-pytest"
source="
$pkgname-$pkgver.tar.gz::https://pypi.io/packages/source/${_pyname:0:1}/$_pyname/$_pyname-$pkgver.tar.gz
253_pkcs11-support.patch
264_xmlsec3-support.patch
280_fix-function-deprecation.patch
"
builddir="$srcdir"/$_pyname-$pkgver
build() {
gpep517 build-wheel \
--wheel-dir dist \
--output-fd 3 3>&1 >&2
}
check() {
pyver=$(python3 -c "import sys; print('{}.{}'.format(*sys.version_info[:2]))")
python3 setup.py install --prefix=/usr --root="$srcdir"/tmp_install --optimize=1
PYTHONPATH="$srcdir"/tmp_install/usr/lib/python$pyver/site-packages pytest || true
}
package() {
python3 setup.py install --prefix=/usr --root="$pkgdir" --optimize=1
install -Dm644 LICENSE -t "$pkgdir"/usr/share/licenses/$pkgname/
}
sha512sums="
2aa080fbc918d5d360dcb086a8c529545514dd429649d99833425f92fa06a3a094cf3139f8ed00827fed358f0fa463b74c267e593ac14e5aadc299d64206ac8e py3-xmlsec-1.3.13.tar.gz
9155a2435d832b4dcd0260616f52eec148dca1dade76a89c23e10f017e4140024ef042b6b10c5b9435fcbf52e7dc4f7e5764dc7f5bdd7595c27b3106fab942cf 253_pkcs11-support.patch
d901c09a49145250dd9325476c1356f820519b9248195240584f6de62b8084205f698501a1f48e42b63fe4c7b169dcb65540edc03724ef7e9297b45216c5b481 264_xmlsec3-support.patch
a47d4d44a518939e72ff7213c6dcd2c391ff5e1bb2be6a1b0d0ab1ef6ed0155d81c26b8f844285883db2f8954b122e48a9b1bccf343a5344af7f1723b3fdd78d 280_fix-function-deprecation.patch
"