in tools/codesigningtool/codesigningtool.py [0:0]
def _find_smartcard_identities(identity=None):
"""Finds smartcard identitites on the current system."""
ids = []
_, xml, _ = execute.execute_and_filter_output([
"/usr/sbin/system_profiler",
"SPSmartCardsDataType",
"-xml"
], raise_on_failure=True)
xml = plistlib.loads(str.encode(xml))
if len(xml) == 0:
return []
xml = xml[0].get("_items", None)
if not xml:
return []
tokens = _get_smartcard_tokens(xml)
keychain = _get_smartcard_keychain(xml)
# For each 'token' finds non-expired certs and:
#
# 1. Check if 'identity' was provided and if it matches a 'CN', in that case stop the loop
# and return the respective fingerprint (SHA1)
# 2. Otherwise append fingerprints found to 'ids' to be returned at the end
#
# ps: note that if 'identity' is provided and it does not match any existing item in the
# smartcard keychain 'ids' will be empty, making this function's behaviour consistent with
# '_find_codesign_identities' where it's being called
for token in tokens:
token_data = [x for x in keychain if x.get("_name", None) == token]
if len(token_data) == 0:
continue
token_data = token_data[0]
for (k, data) in token_data.items():
if k == "_name":
continue
# Extract expiry date and ignore expired certs. The row being processed looks like this:
#
# Valid from: 2021-02-12 21:35:04 +0000 to: 2022-02-12 21:35:05 +0000, SSL trust: NO, X509 trust: YES
#
expiry_date = re.search(r"(?<=to:)(.*?)(?=,)", data, re.DOTALL).group().strip()
expiry_date = datetime.datetime.strptime(expiry_date, "%Y-%m-%d %H:%M:%S %z")
now = datetime.datetime.now(expiry_date.tzinfo)
if now > expiry_date:
continue
# This is a valid identity, decode the certificate, extract
# Common Name and Fingerprint and handle their values accordingly
# as described above
cert = re.search(r"(?<=-----BEGIN CERTIFICATE-----)(.*?)(?=-----END CERTIFICATE-----)", data, re.DOTALL).group().strip()
cert = base64.b64decode(cert)
cert = _certificate_data(cert)
common_name = _certificate_common_name(cert)
fingerprint = _certificate_fingerprint(cert)
if identity == common_name:
return [fingerprint]
if not identity:
ids.append(fingerprint)
return ids