URL: https://github.com/freeipa/freeipa/pull/675 Author: MartinBasti Title: #675: [WIP] Fix PKCS11 helper Action: opened
PR body: """ 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 """ To pull the PR as Git branch: git remote add ghfreeipa https://github.com/freeipa/freeipa git fetch ghfreeipa pull/675/head:pr675 git checkout pr675
From 8295a9a504fe8a7b0c3bd6c24697fcd0c2358a82 Mon Sep 17 00:00:00 2001 From: Martin Basti <mba...@redhat.com> Date: Wed, 29 Mar 2017 18:53:11 +0200 Subject: [PATCH] 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 --- ipalib/constants.py | 2 ++ ipaserver/install/dnskeysyncinstance.py | 8 +++--- ipaserver/install/opendnssecinstance.py | 7 ++--- ipaserver/p11helper.py | 50 ++++++++++++++++++++++++++++++--- 4 files changed, 55 insertions(+), 12 deletions(-) diff --git a/ipalib/constants.py b/ipalib/constants.py index f8a194c..e604bb4 100644 --- a/ipalib/constants.py +++ b/ipalib/constants.py @@ -313,3 +313,5 @@ '.cache' ) ) + +SOFTHSM_DNSSEC_TOKEN_LABEL = u'ipaDNSSEC' diff --git a/ipaserver/install/dnskeysyncinstance.py b/ipaserver/install/dnskeysyncinstance.py index 861a170..8817f25 100644 --- a/ipaserver/install/dnskeysyncinstance.py +++ b/ipaserver/install/dnskeysyncinstance.py @@ -23,9 +23,9 @@ from ipaplatform.constants import constants from ipaplatform.paths import paths from ipalib import errors, api +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" @@ -254,8 +254,8 @@ def __setup_softhsm(self): 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, ] @@ -274,7 +274,7 @@ def __setup_replica_keys(self): 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 467f1f0..2af4d29 100644 --- a/ipaserver/install/opendnssecinstance.py +++ b/ipaserver/install/opendnssecinstance.py @@ -20,10 +20,9 @@ from ipaplatform.paths import paths from ipalib import errors, api from ipaserver import p11helper -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): @@ -68,7 +67,7 @@ def __init__(self, fstore=None): 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, @@ -237,7 +236,7 @@ def __generate_master_key(self): 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/ipaserver/p11helper.py b/ipaserver/p11helper.py index 5963c6d..0ad8589 100644 --- a/ipaserver/p11helper.py +++ b/ipaserver/p11helper.py @@ -387,6 +387,7 @@ def new_array(ctype, *args): 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 +404,10 @@ def new_array(ctype, *args): 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 +801,10 @@ def _id_exists(self, id, id_len, class_): # 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 +812,7 @@ def __init__(self, slot, user_pin, library_path): # 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 +833,16 @@ def __init__(self, slot, user_pin, library_path): 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 +853,37 @@ def __init__(self, slot, user_pin, library_path): 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 recursion + rv = self.p11.C_GetSlotList(CK_TRUE, NULL, object_count_ptr) + check_return_value(rv, "get slot - 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 slot - prepare") + slots = result_ids_ptr + + 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') + + if self.token_label == token_info_ptr[0].label: + return slot + def finalize(self): """ Finalize operations with pkcs11 library
-- Manage your subscription for the Freeipa-devel mailing list: https://www.redhat.com/mailman/listinfo/freeipa-devel Contribute to FreeIPA: http://www.freeipa.org/page/Contribute/Code