mirror of
https://salsa.debian.org/freeipa-team/freeipa.git
synced 2025-02-25 18:55:28 -06:00
fix-pkcs11-helper.diff: Fix ipa-dnskeysyncd setup which was broken by softhsm 2.2.
This commit is contained in:
2
debian/changelog
vendored
2
debian/changelog
vendored
@@ -14,6 +14,8 @@ freeipa (4.4.4-1) UNRELEASED; urgency=medium
|
||||
* control, ipaserver: Move adtrustinstance python files to python-
|
||||
ipaserver, and add samba-common to python-ipaserver depends so that
|
||||
uninstall works.
|
||||
* fix-pkcs11-helper.diff: Fix ipa-dnskeysyncd setup which was broken
|
||||
by softhsm 2.2.
|
||||
|
||||
-- Timo Aaltonen <tjaalton@debian.org> Fri, 17 Feb 2017 01:40:15 +0200
|
||||
|
||||
|
||||
399
debian/patches/fix-pkcs11-helper.diff
vendored
Normal file
399
debian/patches/fix-pkcs11-helper.diff
vendored
Normal file
@@ -0,0 +1,399 @@
|
||||
commit 07df61b7814db08d81e1ff92f58b24e5d852fdf8
|
||||
Author: Martin Basti <mbasti@redhat.com>
|
||||
Date: Wed Mar 29 18:53:11 2017 +0200
|
||||
|
||||
Fix PKCS11 helper
|
||||
|
||||
Slots in HSM are not assigned statically, we have to chose proper
|
||||
slot from token label.
|
||||
|
||||
Softhsm i2.2.0 changed this behavior and now slots can change over
|
||||
time (it is allowed by pkcs11 standard).
|
||||
|
||||
Changelog:
|
||||
* created method get_slot() that returns slot number from
|
||||
used label
|
||||
* replaces usage of slot in __init__ method of P11_Helper
|
||||
with label
|
||||
* slot is dynamically detected from token label before
|
||||
session is opened
|
||||
* pkcs11-util --init-token now uses '--free' instead '--slot'
|
||||
which uses first free slot (we don't care about slot numbers
|
||||
anymore)
|
||||
|
||||
https://pagure.io/freeipa/issue/6692
|
||||
|
||||
Reviewed-By: Stanislav Laznicka <slaznick@redhat.com>
|
||||
|
||||
diff --git a/daemons/dnssec/ipa-dnskeysync-replica b/daemons/dnssec/ipa-dnskeysync-replica
|
||||
index 69a3a68..3714163 100755
|
||||
--- a/daemons/dnssec/ipa-dnskeysync-replica
|
||||
+++ b/daemons/dnssec/ipa-dnskeysync-replica
|
||||
@@ -15,6 +15,7 @@ import os
|
||||
import sys
|
||||
|
||||
import ipalib
|
||||
+from ipalib.constants import SOFTHSM_DNSSEC_TOKEN_LABEL
|
||||
from ipapython.dn import DN
|
||||
from ipapython.ipa_log_manager import root_logger, standard_logging_setup
|
||||
from ipapython import ipaldap
|
||||
@@ -154,8 +155,7 @@ ldapkeydb = LdapKeyDB(log, ldap,
|
||||
DN(('cn', 'keys'), ('cn', 'sec'), ipalib.api.env.container_dns,
|
||||
ipalib.api.env.basedn))
|
||||
|
||||
-# TODO: slot number could be configurable
|
||||
-localhsm = LocalHSM(paths.LIBSOFTHSM2_SO, 0,
|
||||
+localhsm = LocalHSM(paths.LIBSOFTHSM2_SO, SOFTHSM_DNSSEC_TOKEN_LABEL,
|
||||
open(paths.DNSSEC_SOFTHSM_PIN).read())
|
||||
|
||||
ldap2replica_master_keys_sync(log, ldapkeydb, localhsm)
|
||||
diff --git a/daemons/dnssec/ipa-ods-exporter b/daemons/dnssec/ipa-ods-exporter
|
||||
index 385764a..77f8c4d 100755
|
||||
--- a/daemons/dnssec/ipa-ods-exporter
|
||||
+++ b/daemons/dnssec/ipa-ods-exporter
|
||||
@@ -32,6 +32,7 @@ import sqlite3
|
||||
import traceback
|
||||
|
||||
import ipalib
|
||||
+from ipalib.constants import SOFTHSM_DNSSEC_TOKEN_LABEL
|
||||
from ipapython.dn import DN
|
||||
from ipapython import ipaldap
|
||||
from ipapython import ipautil
|
||||
@@ -645,7 +646,7 @@ log.debug('Connected')
|
||||
ldapkeydb = LdapKeyDB(log, ldap, DN(('cn', 'keys'), ('cn', 'sec'),
|
||||
ipalib.api.env.container_dns,
|
||||
ipalib.api.env.basedn))
|
||||
-localhsm = LocalHSM(paths.LIBSOFTHSM2_SO, 0,
|
||||
+localhsm = LocalHSM(paths.LIBSOFTHSM2_SO, SOFTHSM_DNSSEC_TOKEN_LABEL,
|
||||
open(paths.DNSSEC_SOFTHSM_PIN).read())
|
||||
|
||||
ldap2master_replica_keys_sync(log, ldapkeydb, localhsm)
|
||||
diff --git a/ipalib/constants.py b/ipalib/constants.py
|
||||
index c423117..43f1f3c 100644
|
||||
--- a/ipalib/constants.py
|
||||
+++ b/ipalib/constants.py
|
||||
@@ -279,3 +279,5 @@ RENEWAL_CA_NAME = 'dogtag-ipa-ca-renew-agent'
|
||||
|
||||
# regexp definitions
|
||||
PATTERN_GROUPUSER_NAME = '^[a-zA-Z0-9_.][a-zA-Z0-9_.-]*[a-zA-Z0-9_.$-]?$'
|
||||
+
|
||||
+SOFTHSM_DNSSEC_TOKEN_LABEL = u'ipaDNSSEC'
|
||||
diff --git a/ipapython/dnssec/localhsm.py b/ipapython/dnssec/localhsm.py
|
||||
index 8f18a45..73511e9 100755
|
||||
--- a/ipapython/dnssec/localhsm.py
|
||||
+++ b/ipapython/dnssec/localhsm.py
|
||||
@@ -89,10 +89,11 @@ class Key(collections.MutableMapping):
|
||||
def __repr__(self):
|
||||
return self.__str__()
|
||||
|
||||
+
|
||||
class LocalHSM(AbstractHSM):
|
||||
- def __init__(self, library, slot, pin):
|
||||
+ def __init__(self, library, label, pin):
|
||||
self.cache_replica_pubkeys = None
|
||||
- self.p11 = _ipap11helper.P11_Helper(slot, pin, library)
|
||||
+ self.p11 = _ipap11helper.P11_Helper(label, pin, library)
|
||||
self.log = logging.getLogger()
|
||||
|
||||
def __del__(self):
|
||||
diff --git a/ipapython/p11helper.py b/ipapython/p11helper.py
|
||||
index 5ff9ccc..f193ea7 100644
|
||||
--- a/ipapython/p11helper.py
|
||||
+++ b/ipapython/p11helper.py
|
||||
@@ -30,6 +30,7 @@ struct _CK_VERSION
|
||||
};
|
||||
|
||||
typedef unsigned long CK_SLOT_ID;
|
||||
+typedef CK_SLOT_ID *CK_SLOT_ID_PTR;
|
||||
|
||||
typedef unsigned long CK_SESSION_HANDLE;
|
||||
|
||||
@@ -43,6 +44,13 @@ typedef unsigned long CK_KEY_TYPE;
|
||||
|
||||
typedef unsigned long CK_ATTRIBUTE_TYPE;
|
||||
|
||||
+typedef unsigned long ck_flags_t;
|
||||
+
|
||||
+typedef unsigned char CK_BBOOL;
|
||||
+
|
||||
+typedef unsigned long int CK_ULONG;
|
||||
+typedef CK_ULONG *CK_ULONG_PTR;
|
||||
+
|
||||
struct _CK_ATTRIBUTE
|
||||
{
|
||||
CK_ATTRIBUTE_TYPE type;
|
||||
@@ -59,6 +67,31 @@ struct _CK_MECHANISM
|
||||
unsigned long ulParameterLen;
|
||||
};
|
||||
|
||||
+struct _CK_TOKEN_INFO
|
||||
+{
|
||||
+ unsigned char label[32];
|
||||
+ unsigned char manufacturer_id[32];
|
||||
+ unsigned char model[16];
|
||||
+ unsigned char serial_number[16];
|
||||
+ ck_flags_t flags;
|
||||
+ unsigned long max_session_count;
|
||||
+ unsigned long session_count;
|
||||
+ unsigned long max_rw_session_count;
|
||||
+ unsigned long rw_session_count;
|
||||
+ unsigned long max_pin_len;
|
||||
+ unsigned long min_pin_len;
|
||||
+ unsigned long total_public_memory;
|
||||
+ unsigned long free_public_memory;
|
||||
+ unsigned long total_private_memory;
|
||||
+ unsigned long free_private_memory;
|
||||
+ struct _CK_VERSION hardware_version;
|
||||
+ struct _CK_VERSION firmware_version;
|
||||
+ unsigned char utc_time[16];
|
||||
+};
|
||||
+
|
||||
+typedef struct _CK_TOKEN_INFO CK_TOKEN_INFO;
|
||||
+typedef CK_TOKEN_INFO *CK_TOKEN_INFO_PTR;
|
||||
+
|
||||
typedef unsigned long CK_RV;
|
||||
|
||||
typedef ... *CK_NOTIFY;
|
||||
@@ -70,9 +103,12 @@ typedef CK_RV (*CK_C_Finalize) (void *pReserved);
|
||||
typedef ... *CK_C_GetInfo;
|
||||
typedef ... *CK_C_GetFunctionList;
|
||||
CK_RV C_GetFunctionList (struct _CK_FUNCTION_LIST **function_list);
|
||||
-typedef ... *CK_C_GetSlotList;
|
||||
+typedef CK_RV (*CK_C_GetSlotList) (CK_BBOOL tokenPresent,
|
||||
+ CK_SLOT_ID_PTR pSlotList,
|
||||
+ CK_ULONG_PTR pulCount);
|
||||
typedef ... *CK_C_GetSlotInfo;
|
||||
-typedef ... *CK_C_GetTokenInfo;
|
||||
+typedef CK_RV (*CK_C_GetTokenInfo) (CK_SLOT_ID slotID,
|
||||
+ CK_TOKEN_INFO_PTR pInfo);
|
||||
typedef ... *CK_C_WaitForSlotEvent;
|
||||
typedef ... *CK_C_GetMechanismList;
|
||||
typedef ... *CK_C_GetMechanismInfo;
|
||||
@@ -255,10 +291,7 @@ struct _CK_FUNCTION_LIST
|
||||
|
||||
typedef unsigned char CK_BYTE;
|
||||
typedef unsigned char CK_UTF8CHAR;
|
||||
-typedef unsigned char CK_BBOOL;
|
||||
-typedef unsigned long int CK_ULONG;
|
||||
typedef CK_BYTE *CK_BYTE_PTR;
|
||||
-typedef CK_ULONG *CK_ULONG_PTR;
|
||||
|
||||
typedef CK_OBJECT_HANDLE *CK_OBJECT_HANDLE_PTR;
|
||||
|
||||
@@ -387,6 +420,7 @@ CKM_AES_KEY_GEN = 0x1080
|
||||
CKR_OK = 0
|
||||
CKR_ATTRIBUTE_TYPE_INVALID = 0x12
|
||||
CKR_USER_NOT_LOGGED_IN = 0x101
|
||||
+CKR_BUFFER_TOO_SMALL = 0x150
|
||||
|
||||
CK_BYTE = _ffi.typeof('CK_BYTE')
|
||||
CK_BBOOL = _ffi.typeof('CK_BBOOL')
|
||||
@@ -403,6 +437,10 @@ CK_MECHANISM = _ffi.typeof('CK_MECHANISM')
|
||||
|
||||
CK_FUNCTION_LIST_PTR = _ffi.typeof('CK_FUNCTION_LIST_PTR')
|
||||
|
||||
+CK_SLOT_ID = _ffi.typeof('CK_SLOT_ID')
|
||||
+
|
||||
+CK_TOKEN_INFO = _ffi.typeof('CK_TOKEN_INFO')
|
||||
+
|
||||
NULL_PTR = NULL
|
||||
|
||||
|
||||
@@ -796,11 +834,10 @@ class P11_Helper(object):
|
||||
# Object not found
|
||||
return False
|
||||
|
||||
- def __init__(self, slot, user_pin, library_path):
|
||||
+ def __init__(self, token_label, user_pin, library_path):
|
||||
self.p11_ptr = new_ptr(CK_FUNCTION_LIST_PTR)
|
||||
self.session_ptr = new_ptr(CK_SESSION_HANDLE)
|
||||
|
||||
- self.slot = 0
|
||||
self.session_ptr[0] = 0
|
||||
self.p11_ptr[0] = NULL
|
||||
self.module_handle = None
|
||||
@@ -808,7 +845,7 @@ class P11_Helper(object):
|
||||
# Parse method args
|
||||
if isinstance(user_pin, unicode):
|
||||
user_pin = user_pin.encode()
|
||||
- self.slot = slot
|
||||
+ self.token_label = token_label
|
||||
|
||||
try:
|
||||
pGetFunctionList, module_handle = loadLibrary(library_path)
|
||||
@@ -829,9 +866,16 @@ class P11_Helper(object):
|
||||
check_return_value(rv, "initialize")
|
||||
|
||||
#
|
||||
+ # Get Slot
|
||||
+ #
|
||||
+ slot = self.get_slot()
|
||||
+ if slot is None:
|
||||
+ raise Error("No slot for label {} found".format(self.token_label))
|
||||
+
|
||||
+ #
|
||||
# Start session
|
||||
#
|
||||
- rv = self.p11.C_OpenSession(self.slot,
|
||||
+ rv = self.p11.C_OpenSession(slot,
|
||||
CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL,
|
||||
NULL, self.session_ptr)
|
||||
check_return_value(rv, "open session")
|
||||
@@ -842,6 +886,49 @@ class P11_Helper(object):
|
||||
rv = self.p11.C_Login(self.session, CKU_USER, user_pin, len(user_pin))
|
||||
check_return_value(rv, "log in")
|
||||
|
||||
+ def get_slot(self):
|
||||
+ """Get slot where then token is located
|
||||
+ :return: slot number or None when slot not found
|
||||
+ """
|
||||
+ object_count_ptr = new_ptr(CK_ULONG)
|
||||
+
|
||||
+ # get slots ID
|
||||
+ slots = None
|
||||
+ for _i in range(0, 10):
|
||||
+ # try max N times, then die to avoid infinite iteration
|
||||
+ rv = self.p11.C_GetSlotList(CK_TRUE, NULL, object_count_ptr)
|
||||
+ check_return_value(rv, "get slots IDs - prepare")
|
||||
+
|
||||
+ result_ids_ptr = new_array(CK_SLOT_ID, object_count_ptr[0])
|
||||
+
|
||||
+ rv = self.p11.C_GetSlotList(
|
||||
+ CK_TRUE, result_ids_ptr, object_count_ptr)
|
||||
+ if rv == CKR_BUFFER_TOO_SMALL:
|
||||
+ continue
|
||||
+ check_return_value(rv, "get slots IDs")
|
||||
+ slots = result_ids_ptr
|
||||
+ break # we have slots !!!
|
||||
+
|
||||
+ if slots is None:
|
||||
+ raise Error("Failed to get slots")
|
||||
+
|
||||
+ for slot in slots:
|
||||
+ token_info_ptr = new_ptr(CK_TOKEN_INFO)
|
||||
+ rv = self.p11.C_GetTokenInfo(slot, token_info_ptr)
|
||||
+ check_return_value(rv, 'get token info')
|
||||
+
|
||||
+ # softhsm always returns label 32 bytes long with padding made of
|
||||
+ # white spaces (#32), so we have to rstrip() padding and compare
|
||||
+ # Label was created by softhsm-util so it is not our fault that
|
||||
+ # there are #32 as padding (cffi initializes structures with
|
||||
+ # zeroes)
|
||||
+ # In case that this is not valid anymore, keep in mind backward
|
||||
+ # compatibility
|
||||
+
|
||||
+ if self.token_label == char_array_to_unicode(
|
||||
+ token_info_ptr[0].label, 32).rstrip():
|
||||
+ return slot
|
||||
+
|
||||
def finalize(self):
|
||||
"""
|
||||
Finalize operations with pkcs11 library
|
||||
@@ -868,7 +955,6 @@ class P11_Helper(object):
|
||||
|
||||
self.p11_ptr[0] = NULL
|
||||
self.session_ptr[0] = 0
|
||||
- self.slot = 0
|
||||
self.module_handle = None
|
||||
|
||||
#################################################################
|
||||
diff --git a/ipaserver/install/dnskeysyncinstance.py b/ipaserver/install/dnskeysyncinstance.py
|
||||
index fadaf21..d9dfda9 100644
|
||||
--- a/ipaserver/install/dnskeysyncinstance.py
|
||||
+++ b/ipaserver/install/dnskeysyncinstance.py
|
||||
@@ -26,10 +26,9 @@ from ipaplatform.constants import constants
|
||||
from ipaplatform.paths import paths
|
||||
from ipalib import errors, api
|
||||
from ipalib.constants import CACERT
|
||||
+from ipalib.constants import SOFTHSM_DNSSEC_TOKEN_LABEL
|
||||
from ipaserver.install.bindinstance import dns_container_exists
|
||||
|
||||
-softhsm_token_label = u'ipaDNSSEC'
|
||||
-softhsm_slot = 0
|
||||
replica_keylabel_template = u"dnssec-replica:%s"
|
||||
|
||||
|
||||
@@ -289,8 +288,8 @@ class DNSKeySyncInstance(service.Service):
|
||||
command = [
|
||||
paths.SOFTHSM2_UTIL,
|
||||
'--init-token',
|
||||
- '--slot', str(softhsm_slot),
|
||||
- '--label', softhsm_token_label,
|
||||
+ '--free', # use random free slot
|
||||
+ '--label', SOFTHSM_DNSSEC_TOKEN_LABEL,
|
||||
'--pin', pin,
|
||||
'--so-pin', pin_so,
|
||||
]
|
||||
@@ -309,7 +308,8 @@ class DNSKeySyncInstance(service.Service):
|
||||
pin = f.read()
|
||||
|
||||
os.environ["SOFTHSM2_CONF"] = paths.DNSSEC_SOFTHSM2_CONF
|
||||
- p11 = _ipap11helper.P11_Helper(softhsm_slot, pin, paths.LIBSOFTHSM2_SO)
|
||||
+ p11 = _ipap11helper.P11_Helper(
|
||||
+ SOFTHSM_DNSSEC_TOKEN_LABEL, pin, paths.LIBSOFTHSM2_SO)
|
||||
|
||||
try:
|
||||
# generate replica keypair
|
||||
diff --git a/ipaserver/install/opendnssecinstance.py b/ipaserver/install/opendnssecinstance.py
|
||||
index f0c512b..1aac24a 100644
|
||||
--- a/ipaserver/install/opendnssecinstance.py
|
||||
+++ b/ipaserver/install/opendnssecinstance.py
|
||||
@@ -18,10 +18,9 @@ from ipaplatform import services
|
||||
from ipaplatform.constants import constants
|
||||
from ipaplatform.paths import paths
|
||||
from ipalib import errors, api
|
||||
-from ipaserver.install import dnskeysyncinstance
|
||||
+from ipalib.constants import SOFTHSM_DNSSEC_TOKEN_LABEL
|
||||
|
||||
KEYMASTER = u'dnssecKeyMaster'
|
||||
-softhsm_slot = 0
|
||||
|
||||
|
||||
def get_dnssec_key_masters(conn):
|
||||
@@ -72,7 +71,7 @@ class OpenDNSSECInstance(service.Service):
|
||||
self.ods_gid = None
|
||||
self.conf_file_dict = {
|
||||
'SOFTHSM_LIB': paths.LIBSOFTHSM2_SO,
|
||||
- 'TOKEN_LABEL': dnskeysyncinstance.softhsm_token_label,
|
||||
+ 'TOKEN_LABEL': SOFTHSM_DNSSEC_TOKEN_LABEL,
|
||||
'KASP_DB': paths.OPENDNSSEC_KASP_DB,
|
||||
'ODS_USER': constants.ODS_USER,
|
||||
'ODS_GROUP': constants.ODS_GROUP,
|
||||
@@ -247,7 +246,8 @@ class OpenDNSSECInstance(service.Service):
|
||||
pin = f.read()
|
||||
|
||||
os.environ["SOFTHSM2_CONF"] = paths.DNSSEC_SOFTHSM2_CONF
|
||||
- p11 = p11helper.P11_Helper(softhsm_slot, pin, paths.LIBSOFTHSM2_SO)
|
||||
+ p11 = p11helper.P11_Helper(
|
||||
+ SOFTHSM_DNSSEC_TOKEN_LABEL, pin, paths.LIBSOFTHSM2_SO)
|
||||
try:
|
||||
# generate master key
|
||||
root_logger.debug("Creating master key")
|
||||
diff --git a/ipatests/test_ipapython/test_ipap11helper.py b/ipatests/test_ipapython/test_ipap11helper.py
|
||||
index 2c8fd28..5659d60 100644
|
||||
--- a/ipatests/test_ipapython/test_ipap11helper.py
|
||||
+++ b/ipatests/test_ipapython/test_ipap11helper.py
|
||||
@@ -55,12 +55,12 @@ def p11(request):
|
||||
with open('softhsm2.conf', 'w') as cfg:
|
||||
cfg.write(CONFIG_DATA % token_path)
|
||||
os.environ['SOFTHSM2_CONF'] = os.path.join(token_path, 'softhsm2.conf')
|
||||
- subprocess.check_call([SOFTHSM2_UTIL, '--init-token', '--slot', '0',
|
||||
+ subprocess.check_call([SOFTHSM2_UTIL, '--init-token', '--free',
|
||||
'--label', 'test', '--pin', '1234', '--so-pin',
|
||||
'1234'])
|
||||
|
||||
try:
|
||||
- p11 = _ipap11helper.P11_Helper(0, "1234", LIBSOFTHSM)
|
||||
+ p11 = _ipap11helper.P11_Helper('test', "1234", LIBSOFTHSM)
|
||||
except _ipap11helper.Error:
|
||||
pytest.fail('Failed to initialize the helper object.', pytrace=False)
|
||||
|
||||
@@ -70,6 +70,8 @@ def p11(request):
|
||||
except _ipap11helper.Error:
|
||||
pytest.fail('Failed to finalize the helper object.', pytrace=False)
|
||||
finally:
|
||||
+ subprocess.call(
|
||||
+ [SOFTHSM2_UTIL, '--delete-token', '--label', 'test'])
|
||||
del os.environ['SOFTHSM2_CONF']
|
||||
|
||||
request.addfinalizer(fin)
|
||||
1
debian/patches/series
vendored
1
debian/patches/series
vendored
@@ -1,4 +1,5 @@
|
||||
# upstreamed
|
||||
fix-pkcs11-helper.diff
|
||||
|
||||
# not upstreamable
|
||||
prefix.patch
|
||||
|
||||
Reference in New Issue
Block a user