def from_pkcs7_der(cls, pkcs7_der): m2_p7_bio = BIO.MemoryBuffer(pkcs7_der) m2_p7 = SMIME.PKCS7(m2.pkcs7_read_bio_der(m2_p7_bio._ptr()), 1) ct_p7 = cast(c_void_p(long(m2_p7._ptr())), POINTER(PKCS7)) ct_sis = get_lc().PKCS7_get_signer_info(ct_p7) assert get_lc().sk_num(ct_sis) == 1 ct_si = cast(c_void_p(get_lc().sk_value(ct_sis, 0)), POINTER(PKCS7_SIGNER_INFO)) ct_x509 = get_lc().X509_find_by_issuer_and_serial( ct_p7.contents.d.sign.contents.cert, ct_si.contents.issuer_and_serial.contents.issuer, ct_si.contents.issuer_and_serial.contents.serial) signing_cert_int = m2_x509_from_ct_ptr(ct_x509) signing_cert = X509.X509(m2.x509_dup(signing_cert_int._ptr())) m2_p7buf = BIO.MemoryBuffer() ct_p7buf = c_void_p(long(m2_p7buf._ptr())) assert get_lc().PKCS7_signatureVerify(ct_p7buf, ct_p7, ct_si, ct_x509) >= 0 assert ct_si.contents.auth_attr assert get_lc().sk_num(ct_si.contents.auth_attr) attrs = [] for i in xrange(0, get_lc().sk_num(ct_si.contents.auth_attr)): # loop through the signed attributes ct_x509_attr_p = get_lc().sk_value(ct_si.contents.auth_attr, i) assert ct_x509_attr_p ct_x509_attr = cast(ct_x509_attr_p, POINTER(X509_ATTRIBUTE)) try: # try to find a matching OID attribute that we handle oid_obj = SCEPAttribute.find_by_matching_x509_attr_asn1_obj(ct_x509_attr) except SCEPAttributeKeyError: continue attrs.append((oid_obj, oid_obj.get_string(ct_x509_attr))) message_types = [attr for attr in attrs if issubclass(attr[0], MessageType)] assert message_types message_type = message_types[0] attrs.remove(message_types[0]) ct_p7bio = get_lc().PKCS7_dataInit(ct_p7, None) assert ct_p7bio m2_p7bio = m2_MemoryBuffer_from_ct_ptr(ct_p7bio) ncls = SCEPMessage.find_by_message_type(message_type[1])() ncls.signing_cert = signing_cert ncls.signedcontent = m2_p7bio.read() ncls._set_attrs(attrs) return ncls
def decrypt_email_body(client: Client, args: Dict, file_path=None): """ Decrypt the message Args: client: Client args: Dict file_path: relevant for the test module """ if file_path: encrypt_message = file_path else: encrypt_message = demisto.getFilePath(args.get('encrypt_message')) client.smime.load_key(client.private_key_file, client.public_key_file) try: p7, data = SMIME.smime_load_pkcs7(encrypt_message['path']) out = client.smime.decrypt(p7).decode('utf-8') except SMIME.SMIME_Error as e: if str( e ) == 'no content type': # If no content type; see if we can process as DER format with open(encrypt_message['path'], "rb") as message_file: p7data = message_file.read() p7bio = BIO.MemoryBuffer(p7data) p7 = SMIME.PKCS7(m2.pkcs7_read_bio_der(p7bio._ptr())) out = client.smime.decrypt( p7, flags=SMIME.PKCS7_NOVERIFY).decode('utf-8') entry_context = {'SMIME.Decrypted': {'Message': out}} human_readable = f'The decrypted message is: \n{out}' return human_readable, entry_context
def _get_digital_signers(self): if not self.pe: return None retlist = None if HAVE_CRYPTO: address = self.pe.OPTIONAL_HEADER.DATA_DIRECTORY[pefile.DIRECTORY_ENTRY['IMAGE_DIRECTORY_ENTRY_SECURITY']].VirtualAddress #check if file is digitally signed if address == 0: return retlist signature = self.pe.write()[address+8:] bio = BIO.MemoryBuffer(signature) if bio: swig_pkcs7 = m2.pkcs7_read_bio_der(bio.bio_ptr()) if swig_pkcs7: p7 = SMIME.PKCS7(swig_pkcs7) xst = p7.get0_signers(X509.X509_Stack()) retlist = [] if xst: for cert in xst: sn = cert.get_serial_number() sha1_fingerprint = cert.get_fingerprint('sha1').lower() md5_fingerprint = cert.get_fingerprint('md5').lower() subject_str = str(cert.get_subject()) cn = subject_str[subject_str.index("/CN=")+len("/CN="):] retlist.append({"sn":str(sn), "cn":cn, "sha1_fingerprint" : sha1_fingerprint, "md5_fingerprint" : md5_fingerprint }) return retlist
def verify_signature_block(certificate_file, content_file, signature): """Verifies the 'signature' over the 'content', trusting the 'certificate'. :param certificate_file: the trusted certificate (PEM format) :type certificate_file: str :param content_file: The signature should match this content :type content_file: str :param signature: data (DER format) subject to check :type signature: str :return: Error message, or None if the signature validates. :rtype: str """ sig_bio = BIO.MemoryBuffer(signature) pkcs7 = SMIME.PKCS7(m2.pkcs7_read_bio_der(sig_bio._ptr()), 1) signers_cert_stack = pkcs7.get0_signers(X509.X509_Stack()) trusted_cert_store = X509.X509_Store() trusted_cert_store.load_info(certificate_file) smime = SMIME.SMIME() smime.set_x509_stack(signers_cert_stack) smime.set_x509_store(trusted_cert_store) data_bio = BIO.openfile(content_file) try: smime.verify(pkcs7, data_bio) except SMIME.PKCS7_Error, message: return "Signature verification error: %s" % message
def verify_signature_block(certificate_file, content, signature): """ Verifies the 'signature' over the 'content', trusting the 'certificate'. :param certificate_file: the trusted certificate (PEM format) :type certificate_file: str :param content: The signature should match this content :type content: str :param signature: data (DER format) subject to check :type signature: str :return None if the signature validates. :exception SignatureBlockVerificationError """ sig_bio = BIO.MemoryBuffer(signature) pkcs7 = SMIME.PKCS7(m2.pkcs7_read_bio_der(sig_bio._ptr()), 1) signers_cert_stack = pkcs7.get0_signers(X509.X509_Stack()) trusted_cert_store = X509.X509_Store() trusted_cert_store.set_verify_cb(ignore_missing_email_protection_eku_cb) trusted_cert_store.load_info(certificate_file) smime = SMIME.SMIME() smime.set_x509_stack(signers_cert_stack) smime.set_x509_store(trusted_cert_store) data_bio = BIO.MemoryBuffer(content) try: smime.verify(pkcs7, data_bio) except SMIME.PKCS7_Error as message: raise SignatureBlockVerificationError(message) else: return None
def run(self): """Run analysis. @return: analysis results dict or None. """ if not os.path.exists(self.file_path): return None try: self.pe = pefile.PE(self.file_path) except pefile.PEFormatError: return None results = {} results["peid_signatures"] = self._get_peid_signatures() results["pe_imports"] = self._get_imported_symbols() results["pe_exports"] = self._get_exported_symbols() results["pe_dirents"] = self._get_directory_entries() results["pe_sections"] = self._get_sections() results["pe_overlay"] = self._get_overlay() results["pe_resources"] = self._get_resources() results["pe_versioninfo"] = self._get_versioninfo() results["pe_imphash"] = self._get_imphash() results["pe_timestamp"] = self._get_timestamp() results["imported_dll_count"] = len( [x for x in results["pe_imports"] if x.get("dll")]) if HAVE_CRYPTO: address = self.pe.OPTIONAL_HEADER.DATA_DIRECTORY[ pefile.DIRECTORY_ENTRY[ 'IMAGE_DIRECTORY_ENTRY_SECURITY']].VirtualAddress #check if file is digitally signed if address == 0: return results signature = self.pe.write()[address + 8:] bio = BIO.MemoryBuffer(signature) if bio: swig_pkcs7 = m2.pkcs7_read_bio_der(bio.bio_ptr()) if swig_pkcs7: p7 = SMIME.PKCS7(swig_pkcs7) xst = p7.get0_signers(X509.X509_Stack()) results["digital_signer"] = {} if xst: for cert in xst: sn = cert.get_serial_number() subject_str = str(cert.get_subject()) cn = subject_str[subject_str.index("/CN=") + len("/CN="):] results["digital_signer"] = [{ "sn": str(sn), "cn": cn }] return results
def processSignedPlist(infile): certstore_path = "/etc/ssl/certs/ca-certificates.crt" file_descriptor = infile input_bio = BIO.MemoryBuffer(file_descriptor) signer = SMIME.SMIME() cert_store = X509.X509_Store() cert_store.load_info(certstore_path) signer.set_x509_store(cert_store) try: p7 = SMIME.PKCS7(m2.pkcs7_read_bio_der(input_bio._ptr()), 1) except SMIME.SMIME_Error, e: logging.error('load pkcs7 error: ' + str(e))
def to_pkcs7_der(self, digest_algo='sha256'): m2_p7 = SMIME.PKCS7() ct_p7 = cast(c_void_p(long(m2_p7._ptr())), POINTER(PKCS7)) assert get_lc().PKCS7_set_type(ct_p7, m2.PKCS7_SIGNED) assert get_lc().PKCS7_content_new(ct_p7, m2.PKCS7_DATA) ct_signing_cert = c_void_p(long(self.signing_cert._ptr())) assert get_lc().PKCS7_add_certificate(ct_p7, ct_signing_cert) m2_digest = getattr(m2, digest_algo) ct_evp_md = c_void_p(long(m2_digest())) ct_si = get_lc().PKCS7_add_signature( ct_p7, ct_signing_cert, c_void_p(long(self.signing_pkey._ptr())), ct_evp_md) assert ct_si ct_attr_sk = get_lc().sk_new_null() assert ct_attr_sk assert get_lc().sk_push(ct_attr_sk, MessageType.ct_asn1_attribute(self.message_type)) for a in self._get_attrs(): get_lc().sk_push(ct_attr_sk, a) assert get_lc().PKCS7_set_signed_attributes(ct_si, ct_attr_sk) assert get_lc().PKCS7_add_signed_attribute( ct_si, NID_pkcs9_contentType, V_ASN1_OBJECT, get_lc().OBJ_nid2obj(m2.PKCS7_DATA)) ct_p7bio = get_lc().PKCS7_dataInit(ct_p7, None) assert ct_p7bio m2_p7bio = m2_MemoryBuffer_from_ct_ptr(ct_p7bio) m2_p7bio.write(self.get_signed_content()) assert get_lc().PKCS7_dataFinal(ct_p7, ct_p7bio) m2_bio_der = BIO.MemoryBuffer() m2_p7.write_der(m2_bio_der) return m2_bio_der.read()
def _run(self, scanObject, result, depth, args): moduleResult = [] flags = [] buffer = scanObject.buffer cert = None try: #scanObject.addMetadata(self.module_name, key, value) input_bio = BIO.MemoryBuffer(buffer) #Check for PEM or DER if buffer[:1] == "0": #DER p7 = SMIME.PKCS7(m2.pkcs7_read_bio_der(input_bio._ptr()), 1) else: #PEM p7 = SMIME.load_pkcs7_bio(input_bio) certs = p7.get0_signers(X509.X509_Stack()) #some pkcs7's should have more than one certificate in them. openssl can extract them handily. #openssl pkcs7 -inform der -print_certs -in MYKEY.DSA i = 0 for cert in certs: cert_filename = "%x.der" % (cert.get_serial_number()) moduleResult.append( ModuleObject( buffer=cert.as_der(), externalVars=ExternalVars(filename=cert_filename))) i = i + 1 except (QuitScanException, GlobalScanTimeoutError, GlobalModuleTimeoutError): raise except: exc_type, exc_value, exc_traceback = sys.exc_info() logging.exception("Error parsing cert in " + str(get_scanObjectUID(getRootObject(result)))) ugly_error_string = str(exc_value) #nicer_error_string = string.split(string.split(ugly_error_string,":")[4])[0] nicer_error_string = ugly_error_string.split(":")[4].split()[0] scanObject.addFlag("pkcs7:err:" + nicer_error_string) return moduleResult
def decrypt(input_bio, private_key, cert, keyring_source, type): """ Decrypts the input data with the private key and the certificate from keyring source. @type input_bio: M2Crypto.BIO @param input_bio: input data to sign. @type private_key: filepath or M2Crypto.BIO or M2Crypto.EVP.PKey @param private_key: recipient private key reference, could be from file, from memory or from pkcs11 smartcard, based on keyring_soruce input parameter. @type cert: filepath or M2Crypto.BIO or M2Crypto.X509.X509 @param cert: recipient certificate, could be from filepath, from memory or from pkcs11 smartcard, based on keyring_soruce input parameter. @type keyring_source: str @keyword keyring_source: the type of the source for input certificate, used to recall the appropriate method for decrypter settings. Ammitted values are: file, memory, pkcs11. @type type: str @keyword type: specifies the type of input PKCS#7 data: PEM or DER @rtype: str @return: the decrypted data in plain form. @raise BadPKCS7Type: The requested PKCS#7 type is not valid. Ammitted values are PEM and DER. """ decrypter = SMIME.SMIME() set_keyring(decrypter, private_key, cert, keyring_source) try: if type == 'PEM': p7, data_bio = SMIME.smime_load_pkcs7_bio(input_bio) elif type == 'DER': p7 = SMIME.PKCS7(m2.pkcs7_read_bio_der(input_bio._ptr()), 1) else: logging.error('pkcs7 type error: unknown type') raise BadPKCS7Type('unknown type: ' + type + '; possible values: PEM, DER') except SMIME.SMIME_Error as e: logging.error('load pkcs7 error: ' + str(e)) pass try: decrypted_data = decrypter.decrypt(p7) except SMIME.SMIME_Error as e: logging.error('smime error: ' + str(e)) raise except SMIME.PKCS7_Error as e: logging.error('pkcs7 error: ' + str(e)) raise return decrypted_data.replace(b'\r', b'')
def getCertificateDetails(filename): basename = "" cert_details = {} basename = os.path.basename(filename).split('.')[0] cert_name = "%s_digisig.crt" % basename try: if _extractDigitalSignature(filename, signatureFile=cert_name) != None: bio=BIO.File(open(cert_name)) smime_object = SMIME.PKCS7(m2.pkcs7_read_bio_der(bio._ptr())) signers = smime_object.get0_signers(X509.X509_Stack()) cert_details["cert_issued_by"] = signers[0].get_issuer().CN cert_details["cert_issued_to"] = signers[0].get_subject().CN validity = signers[0].get_not_after().get_datetime() cert_details["cert_expiration"] = "%s-%s-%s" % (validity.year, validity.month, validity.day) except Exception, ex: print "ERROR: Problem in retrieving certificate details : %s" % ex
def test_signing(): """ This test can only run locally if you provide your personal Apple Wallet certificates, private key and password. It would not be wise to add them to git. Store them in the files indicated below, they are ignored by git. """ try: with open(password_file) as file_: password = file_.read().strip() except IOError: password = '' passfile = create_shell_pass() manifest_json = passfile._createManifest(passfile._createPassJson()) signature = passfile._createSignature( manifest_json, certificate, key, wwdr_certificate, password, ) smime_obj = SMIME.SMIME() store = X509.X509_Store() store.load_info(str(wwdr_certificate)) smime_obj.set_x509_store(store) signature_bio = BIO.MemoryBuffer(signature) signature_p7 = SMIME.PKCS7(m2.pkcs7_read_bio_der(signature_bio._ptr()), 1) stack = signature_p7.get0_signers(X509.X509_Stack()) smime_obj.set_x509_stack(stack) data_bio = BIO.MemoryBuffer(manifest_json) # PKCS7_NOVERIFY = do not verify the signers certificate of a signed message. assert smime_obj.verify( signature_p7, data_bio, flags=SMIME.PKCS7_NOVERIFY ) == manifest_json tampered_manifest = '{"pass.json": "foobar"}' data_bio = BIO.MemoryBuffer(tampered_manifest) # Verification MUST fail! with pytest.raises(SMIME.PKCS7_Error): smime_obj.verify(signature_p7, data_bio, flags=SMIME.PKCS7_NOVERIFY)
def verify(input_bio, certstore_path, AUTO_SIGNED_CERT, type): """ Retrieves X.509 certificate from input data and verifies signed message using as certificate store input certstore, inspired by: U{http://code.activestate.com/recipes/285211/}. @type input_bio: M2Crypto.BIO @param input_bio: input data to verify @type certstore_path: filepath @param certstore_path: path to the file of the trusted certificates, for example /etc/ssl/certs/ca-certificats.crt. @type type: str @keyword type: specifies the type of input PKCS#7 data: PEM or DER @type AUTO_SIGNED_CERT: boolean @keyword AUTOSIGNED_CERT: to accept or not auto signed certificates as valid for verification. @rtype: list or None @return: a list of verified certificates retrieved from the original data if verification success, else None. @raise CertStoreNotAvailable: the reference certstore for verification is not available. @raise MissingSignerCertificate: the input PKCS#7 is not a signed PKCS#7. """ signer = SMIME.SMIME() cert_store = X509.X509_Store() if not os.access(certstore_path, os.R_OK): logging.error('certstore not available for verify') raise CertStoreNotAvailable('certstore not available %' % (certstore_path)) cert_store.load_info(certstore_path) signer.set_x509_store(cert_store) data_bio = None try: if type == 'PEM': p7, data_bio = SMIME.smime_load_pkcs7_bio(input_bio) elif type == 'DER': p7 = SMIME.PKCS7(m2.pkcs7_read_bio_der(input_bio._ptr()), 1) else: logging.error('pkcs7 type error: unknown type') raise BadPKCS7Type('unknown type: ' + type + '; possible values: PEM, DER') except SMIME.SMIME_Error, e: logging.error('load pkcs7 error: ' + str(e)) raise
def upload_encr(): mdm_ca = get_ca() upl_encrypt = unhexlify(request.files['upload_encr_file'].stream.read()) s = SMIME.SMIME() bio = BIO.MemoryBuffer(upl_encrypt) s.load_key_bio(BIO.MemoryBuffer(mdm_ca.get_private_key().to_pem()), BIO.MemoryBuffer(mdm_ca.get_cacert().to_pem())) p7 = SMIME.PKCS7(m2.pkcs7_read_bio_der(bio._ptr())) out = s.decrypt(p7) response = make_response(out) response.headers['Content-Type'] = 'application/octet-stream' response.headers[ 'Content-Disposition'] = 'attachment; filename=mdm_signed_request.%s.plist.b64' % datetime.datetime.now( ).strftime('%Y%m%d_%H%M%S') return response
def verify(client: Client, args: Dict): """ Verify the signature Args: client: Client args: Dict """ signed_message = demisto.getFilePath(args.get('signed_message')) x509 = X509.load_cert(client.public_key_file) sk = X509.X509_Stack() sk.push(x509) client.smime.set_x509_stack(sk) st = X509.X509_Store() st.load_info(client.public_key_file) client.smime.set_x509_store(st) try: p7, data = SMIME.smime_load_pkcs7(signed_message['path']) v = client.smime.verify(p7, data, flags=SMIME.PKCS7_NOVERIFY) human_readable = f'The signature verified\n\n{v}' except SMIME.SMIME_Error as e: if str( e ) == 'no content type': # If no content type; see if we can process as DER format with open(signed_message['path'], "rb") as message_file: p7data = message_file.read() p7bio = BIO.MemoryBuffer(p7data) p7 = SMIME.PKCS7(m2.pkcs7_read_bio_der(p7bio._ptr())) v = client.smime.verify(p7, flags=SMIME.PKCS7_NOVERIFY) return_results( fileResult('unwrapped-' + signed_message.get('name'), v)) human_readable = 'The signature verified\n\n' return human_readable, {}
def check_if_singed(self, pe) -> list: ''' check file if it has Signature or not ''' i = 0 _list = [] _extracted = {} Problems = False address = pe.OPTIONAL_HEADER.DATA_DIRECTORY[ DIRECTORY_ENTRY['IMAGE_DIRECTORY_ENTRY_SECURITY']].VirtualAddress if address != 0: try: sig = pe.write()[address + 8:] m2cbio = BIO.MemoryBuffer(bytes(sig)) if m2cbio: pkcs7bio = m2.pkcs7_read_bio_der(m2cbio.bio_ptr()) if pkcs7bio: pkcs7 = SMIME.PKCS7(pkcs7bio) for cert in pkcs7.get0_signers(X509.X509_Stack()): tempcert = "CERT_{}".format(i) _extracted[tempcert] = { "CommonName": None, "OrganizationalUnit": None, "Organization": None, "Locality": None, "StateOrProvinceName": None, "CountryName": None, "Start": None, "Ends": None, "SerialNumber": None } try: _extracted[tempcert][ "CommonName"] = cert.get_subject().CN except: pass try: _extracted[tempcert][ "OrganizationalUnit"] = cert.get_subject( ).OU except: pass try: _extracted[tempcert][ "Organization"] = cert.get_subject().O except: pass try: _extracted[tempcert][ "Locality"] = cert.get_subject().L except: pass try: _extracted[tempcert][ "StateOrProvinceName"] = cert.get_subject( ).S except: pass try: _extracted[tempcert][ "CountryName"] = cert.get_subject().C except: pass try: _extracted[tempcert][ "Email"] = cert.get_subject().Email except: pass try: _extracted[tempcert]["Start"] = str( cert.get_not_before()) except: pass try: _extracted[tempcert]["Ends"] = str( cert.get_not_after()) except: pass try: _extracted[tempcert][ "SerialNumber"] = cert.get_serial_number() _extracted[tempcert][ "SerialNumberMD5"] = cert.get_fingerprint( 'md5').lower().rjust(32, '0') except: pass except: Problems = True sighex = "".join("{:02x}".format(x) for x in sig) _list.append({"Wrong": Problems, "SignatureHex": sighex}) return _list, _extracted
def load_pkcs7_bio_der(p7_bio): p7_ptr = m2.pkcs7_read_bio_der(p7_bio._ptr()) if p7_ptr is None: raise SMIME.PKCS7_Error(Err.get_error()) return SMIME.PKCS7(p7_ptr, 1)
def checkin(request): logger = logging.getLogger('django') logger.debug('WWW Query: %s', request.body) if settings.USE_CERTIFICATE == True: # Get the certificate fingerprint try: bio = BIO.MemoryBuffer( base64.b64decode(request.META['HTTP_MDM_SIGNATURE'])) p7 = SMIME.PKCS7(m2.pkcs7_read_bio_der(bio._ptr()), 1) stk = X509.X509_Stack() sk3 = p7.get0_signers(stk) cert = sk3.pop() fingerprint = cert.get_fingerprint('md5') if len(fingerprint) == 31: fingerprint = '0' + fingerprint except: fingerprint = None logger.debug('Fingerprint: %s', fingerprint) # If no certificate supplied, permission denied. if fingerprint == None and settings.REQUIRE_CERTIFICATE == True: return HttpResponseForbidden() # If no certificate found, permission denied. certificate = Certificate.objects.filter(md5=fingerprint).first() if certificate == None and settings.REQUIRE_CERTIFICATE == True: return HttpResponseForbidden() # If certificate does not match device, permission denied. # TODO else: certificate = None # Prepare handling of checkin request and response commands. responseData = plistlib.writePlistToString(dict()) standard_commands.initialize() try: plist = plistlib.readPlistFromString(request.body) except: plist = dict() if 'MessageType' in plist: if plist['MessageType'] == 'Authenticate': if 'UserID' in plist: return HttpResponseBadRequest( 'User binding not currently supported') device = Device.objects.filter(udid=plist['UDID']).first() if device == None: device = Device(udid=plist['UDID'], push_topic=plist['Topic']) device.last_checkin = datetime.now() device.last_notification = datetime.now() device.save() if certificate != None: certificate.device = device certificate.save() try: group = DeviceGroup.objects.filter( uuid=settings.DEFAULT_DEVICE_GROUP).first() group.devices.add(device) group.save() except: pass elif plist['MessageType'] == 'TokenUpdate': if 'UserID' in plist: return HttpResponseBadRequest( 'User binding not currently supported') device = Device.objects.get(udid=plist['UDID']) device.push_topic = plist['Topic'] device.push_token = plist['Token'].asBase64(maxlinelength=8000) device.push_magic = plist['PushMagic'] device.last_checkin = datetime.now() device.save() DeviceCommand.NewDeviceInformation(device) DeviceCommand.NewProfileList(device) DeviceCommand.NewInstalledApplicationList(device) push.push_notification(device) elif plist['MessageType'] == 'CheckOut': if 'UserID' in plist: return HttpResponseBadRequest( 'User binding not currently supported') Device.objects.get(udid=plist['UDID']).delete() else: print 'Unknown message type: ' + plist['MessageType'] print plist elif 'Status' in plist: responseData = '' # Update device checkin time device = Device.objects.get(udid=plist['UDID']) device.last_checkin = datetime.now() device.save() # Update device location if it has been 15 minutes since last. since = datetime.now() - timedelta(minutes=15) location = DeviceCheckin.objects.filter( device=device).order_by('-end_date').first() if location and location.ip == request.META['REMOTE_ADDR']: location.end_date = datetime.now() location.save() else: location = DeviceCheckin(device=device) location.start_date = datetime.now() location.end_date = datetime.now() location.ip = request.META['REMOTE_ADDR'] loc = geo.geocode(request.META['REMOTE_ADDR']) location.latitude = loc['latitude'] location.longitude = loc['longitude'] location.country_code = loc['country_code'] location.region_code = loc['region_code'] location.city = loc['city'] if 'country_name' in loc: location.country_name = loc['country_name'] if 'region_name' in loc: location.region_name = loc['region_name'] location.save() if plist['Status'] == 'Acknowledged': cmd = DeviceCommand.objects.get(uuid=plist['CommandUUID']) cmd.status = DeviceCommand.SUCCESS cmd.date_completed = datetime.now() cmd.save() commands.handleCommandResponse(cmd, plist) elif plist['Status'] == 'Error' or plist[ 'Status'] == 'CommandFormatError': cmd = DeviceCommand.objects.get(uuid=plist['CommandUUID']) cmd.status = DeviceCommand.FAILED cmd.date_completed = datetime.now() cmd.save() elif plist['Status'] == 'NotNow': cmd = DeviceCommand.objects.get(uuid=plist['CommandUUID']) cmd.status = DeviceCommand.PENDING cmd.attempts = 0 cmd.save() if plist['Status'] == 'Idle' or plist['Status'] == 'Acknowledged': # Look for the next command, mark as failed if too many attempts. cmd = DeviceCommand.objects.filter( device=device, status__in=[DeviceCommand.PENDING, DeviceCommand.RUNNING]).first() while cmd and cmd.attempts >= 3: cmd.status = DeviceCommand.FAILED cmd.save() cmd = DeviceCommand.objects.filter( device=device, status__in=[DeviceCommand.PENDING, DeviceCommand.RUNNING]).first() # Run the next command. if cmd: data = commands.dataForCommand(cmd) responseData = plistlib.writePlistToString(data) cmd.status = DeviceCommand.RUNNING cmd.attempts += 1 cmd.save() logger.debug('WWW Result: %s', responseData) response = HttpResponse(responseData, content_type='application/xml; charset=UTF-8') response['Content-Length'] = len(responseData) return response
from M2Crypto import SMIME, X509, BIO, m2 import plistlib import sys if len(sys.argv) < 3: print "Usage: %s [Provisioning Profile] [Out .xcconfig]" % __file__ exit() inProfile = sys.argv[1] outXcConfig = sys.argv[2] provision = open(inProfile, 'r') inBio = BIO.File(provision) pkcs7 = SMIME.PKCS7(m2.pkcs7_read_bio_der(inBio._ptr())) smime = SMIME.SMIME() stack = X509.X509_Stack() smime.set_x509_stack(stack) store = X509.X509_Store() smime.set_x509_store(store) dataBio = None blob = smime.verify(pkcs7, dataBio, SMIME.PKCS7_NOVERIFY | SMIME.PKCS7_NOSIGS) certs = pkcs7.get0_signers(stack) signer = certs[0] items = signer.get_subject().get_entries_by_nid(X509.X509_Name.nid["CN"])
def verify_file_with_ds_certificate(self, filename, p7filename, is_self_signed=True): if not os.access(filename, os.R_OK): self.logger.error("No filename to verify '%s' found" % filename) return None if not os.access(p7filename, os.R_OK): self.logger.error("No filename to verify '%s' found" % filename) return None if not self.load_engine(): return None # nel caso sia fallito il caricamento smartcard_atr = SmartcardFetcher.get_smartcard_atr(self.logger) smartcard_library = SmartcardFetcher.get_smartcard_library( smartcard_atr, self.config, self.logger) smartcard = SmartcardFetcher.SmartcardFetcher(smartcard_library, self.logger) self.logger.status('get ds id') ds_id = smartcard.get_ds_id( ) # ottengo l'id per estrarre il certificato dall smartcard self.logger.status('get ds certificate') certificate = self.get_ds_certificate(ds_id) # ottengo il certificato if certificate is None: return None # creo uno store di certificati store_stack = X509.X509_Stack() store_stack.push(certificate) store = X509.X509_Store() store.add_x509(certificate) signer = SMIME.SMIME() signer.set_x509_stack(store_stack) signer.set_x509_store(store) #p7, data = SMIME.load_pkcs7(p7m_file) # carico il file firmato in formato PEM self.logger.status('read p7mfile %s' % p7filename) p7m_fd = open(p7filename, "rb") p7_input_bio = BIO.File(p7m_fd) # carico il file p7m p7 = SMIME.PKCS7( m2.pkcs7_read_bio_der(p7_input_bio._ptr()), 1 ) # al momento non c'e' nessun modo per estrarre i dati del DER dal certificato # p7, data = SMIME.load_pkcs7_bio(p7_input_bio) # l'input bio deve essere in formato PEM (basa64) data_bio = None try: if is_self_signed: self.logger.status('verifing file') v = signer.verify(p7, data_bio, flags=SMIME.PKCS7_NOVERIFY) else: v = signer.verify(p7, data_bio) except SMIME.SMIME_Error, e: self.logger.error('smime error: ' + str(e)) return None
def verify_file(path): with open(path, 'rb') as ota_file: ota_file.seek(0, 2) length = ota_file.tell() ota_file.seek(-FOOTER_SIZE, 2) footer = bytearray(ota_file.read()) if (footer[2] != 0xff or footer[3] != 0xff): print("This zip is not signed!") return False comment_size = footer[4] + (footer[5] << 8) signature_start = footer[0] + (footer[1] << 8) print("Comment is %d bytes; signature %d bytes from end." % (comment_size, signature_start)) eocd_size = comment_size + EOCD_HEADER_SIZE ota_file.seek(-eocd_size, 2) signed_len = ota_file.tell() + EOCD_HEADER_SIZE - 2 eocd = bytearray(ota_file.read(eocd_size)) if (eocd[0] != 0x50 or eocd[1] != 0x4b or eocd[2] != 0x05 or eocd[3] != 0x06): print("Signature length doesn't match EOCD marker.") return False for i in range(4, eocd_size-3): if (eocd[i] == 0x50 and eocd[i+1] == 0x4b and eocd[i+2] == 0x05 and eocd[i+3] == 0x06): print("EOCD marker occurs after start of EOCD") return False ota_file.seek(0,0) zip_content = bytearray(ota_file.read(signed_len)) sha1 = hashlib.sha1() sha1.update(zip_content) signature_size = signature_start - FOOTER_SIZE signature = eocd[eocd_size-signature_start:signature_size] print("Signature (offset: %x, length: %d):" % (length-signature_start, signature_size)) s = SMIME.SMIME() # Load the signer's cert. x509 = X509.load_cert('certificate.pem') sk = X509.X509_Stack() sk.push(x509) s.set_x509_stack(sk) # Load the signer's CA cert. In this case, because the signer's # cert is self-signed, it is the signer's cert itself. st = X509.X509_Store() st.load_info('certificate.pem') s.set_x509_store(st) # Load the data, verify it. # signature is a buffer containing the signature in pkcs#7 DER format p7bio = BIO.MemoryBuffer(signature) contentbio = BIO.MemoryBuffer(zip_content) contentbio = BIO.openfile('ota-unsign.zip') p7 = SMIME.PKCS7(m2.pkcs7_read_bio_der(p7bio._ptr())) md = EVP.MessageDigest('sha1') md.update(zip_content) print binascii.b2a_hex(md.digest()) v = s.verify(p7) v = s.verify(p7, contentbio) print v
# To run, provide the path to a signed profile at the command line: # ./unsignprofile.py SignedProfile.mobileconfig from M2Crypto import SMIME, X509, m2, BIO from plistlib import * import sys import logging # Can be any file probably since we're not verifying. certstore_path = "/etc/ssl/certs/ca-certificates.crt" file_descriptor = open(sys.argv[1], 'rb') input_bio = BIO.File(file_descriptor) signer = SMIME.SMIME() cert_store = X509.X509_Store() cert_store.load_info(certstore_path) signer.set_x509_store(cert_store) try: p7 = SMIME.PKCS7(m2.pkcs7_read_bio_der(input_bio._ptr()), 1) except SMIME.SMIME_Error, e: logging.error('load pkcs7 error: ' + str(e)) sk3 = p7.get0_signers(X509.X509_Stack()) signer.set_x509_stack(sk3) data_bio = None content = signer.verify(p7, data_bio, flags=SMIME.PKCS7_NOVERIFY) # Printing the contents of the profile/plist, modify to save to file with write() print readPlistFromString(content)
def verify(input_bio, certstore_path, AUTO_SIGNED_CERT, type): """ Retrieves X.509 certificate from input data and verifies signed message using as certificate store input certstore, inspired by: U{http://code.activestate.com/recipes/285211/}. @type input_bio: M2Crypto.BIO @param input_bio: input data to verify @type certstore_path: filepath @param certstore_path: path to the file of the trusted certificates, for example /etc/ssl/certs/ca-certificats.crt. @type type: str @keyword type: specifies the type of input PKCS#7 data: PEM or DER @type AUTO_SIGNED_CERT: boolean @keyword AUTOSIGNED_CERT: to accept or not auto signed certificates as valid for verification. @rtype: list or None @return: a list of verified certificates retrieved from the original data if verification success, else None. @raise CertStoreNotAvailable: the reference certstore for verification is not available. @raise MissingSignerCertificate: the input PKCS#7 is not a signed PKCS#7. """ signer = SMIME.SMIME() cert_store = X509.X509_Store() if not os.access(certstore_path, os.R_OK): logging.error('certstore not available for verify') raise CertStoreNotAvailable('certstore not available %' % (certstore_path)) cert_store.load_info(certstore_path) signer.set_x509_store(cert_store) data_bio = None try: if type == 'PEM': p7, data_bio = SMIME.smime_load_pkcs7_bio(input_bio) elif type == 'DER': p7 = SMIME.PKCS7(m2.pkcs7_read_bio_der(input_bio._ptr()), 1) else: logging.error('pkcs7 type error: unknown type') raise BadPKCS7Type('unknown type: ' + type + '; possible values: PEM, DER') except SMIME.SMIME_Error as e: logging.error('load pkcs7 error: ' + str(e)) raise if data_bio is not None: data = data_bio.read() data_bio = BIO_from_buffer(data) sk3 = p7.get0_signers(X509.X509_Stack()) if len(sk3) == 0: logging.error('missing certificate') raise MissingSignerCertificate('missing certificate') signer_certs = [] for cert in sk3: signer_certs.append( "-----BEGIN CERTIFICATE-----\n{}-----END CERTIFICATE-----\n". format(base64.encodestring(cert.as_der()).decode('ascii'))) signer.set_x509_stack(sk3) v = None try: if AUTO_SIGNED_CERT: v = signer.verify(p7, data_bio, flags=SMIME.PKCS7_NOVERIFY) else: v = signer.verify(p7, data_bio) except SMIME.SMIME_Error as e: logging.error('smime error: ' + str(e)) raise except SMIME.PKCS7_Error as e: logging.error('pkcs7 error: ' + str(e)) raise if data_bio is not None and data != v and v is not None: return return signer_certs