def _load_certificate_data(certtype, buffer, result_typeid): """ Load a certificate with the supplied type and data. @param certtype: ignored @type certtype: - @param buffer: name of the KeyChain item to lookup @type buffer: L{str} @param result_typeid: The type to return (certificate or key) @type result_typeid: L{ffi.CFTypeID} @return: the certificate @rtype: L{X509} """ # First try to get the identity from the KeyChain data = CFDataRef.fromString(buffer) results = ffi.new("CFArrayRef *") err = security.SecItemImport(data.ref(), ffi.NULL, ffi.NULL, ffi.NULL, 0, ffi.NULL, ffi.NULL, results) if err != 0: raise Error("Could not load certificate data") results = CFArrayRef(results[0]).toList() # Try to find a SecCertificateRef for result in results: if result.instanceTypeId() == result_typeid: return result else: raise Error("No certificate in data")
def check_keychain_identity(identity, allowInteraction=False): """ Verify that the Keychain identity exists and that the private key is accessible. @param identity: identity value to match @type identity: L{str} @return: empty L{str} if OK, error message if not @rtype: L{str} """ # Always turn off user interaction security.SecKeychainSetUserInteractionAllowed(allowInteraction) try: secidentity = load_keychain_identity(identity) except Error: return "Unable to load Keychain identity: {}".format(identity) pkey = ffi.new("SecKeyRef *") err = security.SecIdentityCopyPrivateKey(secidentity.ref(), pkey) if err != 0: return "Unable to load private key for Keychain identity: {}".format( identity) pkey = CFObjectRef(pkey[0]) # Try to sign some data with the pkey to check we have access error = ffi.new("CFErrorRef *") signer = security.SecSignTransformCreate(pkey.ref(), error) if error[0] != ffi.NULL: cferror = CFErrorRef(error[0]) return "Unable to use private key for Keychain identity: {} - {}".format( identity, cferror.description()) signer = CFObjectRef(signer) signMe = CFDataRef.fromString("sign me") security.SecTransformSetAttribute(signer.ref(), security.kSecTransformInputAttributeName, signMe.ref(), error) if error[0] != ffi.NULL: cferror = CFErrorRef(error[0]) return "Unable to use private key for Keychain identity: {} - {}".format( identity, cferror.description()) signature = security.SecTransformExecute(signer.ref(), error) if error[0] != ffi.NULL or signature == ffi.NULL: cferror = CFErrorRef(error[0]) return "Unable to use private key for Keychain identity: {} - {}".format( identity, cferror.description()) signature = CFObjectRef(signature) return ""
def test_cms_sign_verify_ok(self): """ Use the simple encode. """ # Sign some data sign = "Something to be signed" result = ffi.new("CFDataRef *") signer = load_keychain_identity("org.calendarserver.test") error = cms.CMSEncodeContent( signer.ref(), ffi.NULL, ffi.NULL, False, cms.kCMSAttrNone, sign, len(sign), result, ) self.assertEqual(error, 0) result = CFDataRef(result[0]) self.assertNotEqual(result.count(), 0) # Now verify the result decoder = ffi.new("CMSDecoderRef *") error = cms.CMSDecoderCreate(decoder) self.assertEqual(error, 0) decoder = CFObjectRef(decoder[0]) error = cms.CMSDecoderUpdateMessage(decoder.ref(), result.toString(), result.count()) self.assertEqual(error, 0) error = cms.CMSDecoderFinalizeMessage(decoder.ref()) self.assertEqual(error, 0) number = ffi.new("size_t *") error = cms.CMSDecoderGetNumSigners(decoder.ref(), number) self.assertEqual(error, 0) self.assertEqual(number[0], 1) encrypted = ffi.new("Boolean *") error = cms.CMSDecoderIsContentEncrypted(decoder.ref(), encrypted) self.assertEqual(error, 0) self.assertEqual(encrypted[0], False) policy = cms.SecPolicyCreateBasicX509() policy = CFObjectRef(policy) status = ffi.new("CMSSignerStatus *") verify_result = ffi.new("OSStatus *") error = cms.CMSDecoderCopySignerStatus( decoder.ref(), 0, policy.ref(), True, status, ffi.NULL, verify_result, ) self.assertEqual(error, 0) self.assertEqual(status[0], cms.kCMSSignerValid) self.assertEqual(verify_result[0], 0) result = ffi.new("CFDataRef *") error = cms.CMSDecoderCopyContent(decoder.ref(), result) self.assertEqual(error, 0) result = CFDataRef(result[0]) self.assertEqual(result.toString(), sign)
def convertStringsFile(src, dest): dir = os.path.dirname(dest) if not os.path.exists(dir): try: os.makedirs(dir) except OSError: # can't create directory to hold .po file return # Parse the binary plist .strings file: with open(src) as f: data = f.read() data = CFDataRef.fromString(data) try: parsed = CFPropertyListRef.createFromData(data) strings = parsed.toDict() except CFError as error: raise ParseError(error) # The format of GNUtext MO files is described here: # http://www.gnu.org/software/autoconf/manual/gettext/MO-Files.html originals = strings.keys() originals.sort() descriptors = [] keys = '' values = '' for original in originals: translation = strings[original] if isinstance(original, unicode): original = original.encode("UTF-8") if isinstance(translation, unicode): translation = translation.encode("UTF-8") descriptors.append( (len(keys), len(original), len(values), len(translation))) keys += original + '\0' # <NUL> terminated values += translation + '\0' # The header is 28 bytes, each descriptor is 8 bytes, with two descriptors # per string (one pointing at original, one pointing at translation) keysOffset = 28 + len(originals) * 2 * 8 valuesOffset = keysOffset + len(keys) keyDescriptors = [] valueDescriptors = [] for origOffset, origLen, transOffset, transLen in descriptors: keyDescriptors.append(origLen) keyDescriptors.append(keysOffset + origOffset) valueDescriptors.append(transLen) valueDescriptors.append(valuesOffset + transOffset) result = struct.pack( "Iiiiiii", 0x950412DEL, # magic number 0, # file format revision len(originals), # number of strings 28, # offset of table with original strings 28 + len(originals) * 8, # offset of table with translation strings 0, # size of hashing table 0 # offset of hashing table ) result += array.array("i", keyDescriptors).tostring() result += array.array("i", valueDescriptors).tostring() result += keys result += values with open(dest, "wb") as outFile: outFile.write(result)