Exemple #1
0
    def _send_msg(self, message, msgid):
        '''
        Send one message using stomppy.  The message will be signed using
        the host cert and key.  If an encryption certificate
        has been supplied, the message will also be encrypted.
        '''
        log.info('Sending message: %s', msgid)
        headers = {
            'destination': self._dest,
            'receipt': msgid,
            'empa-id': msgid
        }

        if message is not None:
            to_send = crypto.sign(message, self._cert, self._key)
            if self._enc_cert is not None:
                to_send = crypto.encrypt(to_send, self._enc_cert)
        else:
            to_send = ''

        try:
            # Try using the v4 method signiture
            self._conn.send(self._dest, to_send, headers=headers)
        except TypeError:
            # If it fails, use the v3 metod signiture
            self._conn.send(to_send, headers=headers)
Exemple #2
0
    def test_message_tampering(self):
        """Test that a tampered message is not accepted as valid."""
        signed_message = sign(MSG, TEST_CERT_FILE, TEST_KEY_FILE)
        tampered_message = signed_message.replace(MSG, "Spam")

        # Verifying the orignal, un-tampered message should be fine.
        verified_message, verified_signer = verify(signed_message, TEST_CA_DIR,
                                                   False)
        self.assertEqual(verified_message, MSG)
        self.assertEqual(verified_signer, TEST_CERT_DN)

        # Verifying the tampered message should not be fine.
        self.assertRaises(CryptoException, verify, tampered_message,
                          TEST_CA_DIR, False)
Exemple #3
0
    def test_get_signer_cert(self):
        '''
        Check that the certificate retrieved from the signed message
        matches the certificate used to sign it.
        '''
        signed_msg = sign(MSG, TEST_CERT_FILE, TEST_KEY_FILE)

        cert = get_signer_cert(signed_msg)
        # Remove any information preceding the encoded certificate.
        cert = cert[cert.find('-----BEGIN'):]

        with open(TEST_CERT_FILE, 'r') as test_cert:
            cert_string = test_cert.read()

        if cert.strip() != cert_string.strip():
            self.fail('Certificate retrieved from signature '
                      'does not match certificate used to sign.')
Exemple #4
0
    def _send_msg(self, message, msgid):
        """
        Send one message using stomppy.  The message will be signed using 
        the host cert and key.  If an encryption certificate
        has been supplied, the message will also be encrypted.
        """
        log.info("Sending message: " + msgid)
        headers = {"destination": self._dest, "receipt": msgid, "empa-id": msgid}

        if message is not None:
            to_send = crypto.sign(message, self._cert, self._key)
            if self._enc_cert is not None:
                to_send = crypto.encrypt(to_send, self._enc_cert)
        else:
            to_send = ""

        self._conn.send(to_send, headers=headers)
Exemple #5
0
    def test_get_signer_cert(self):
        '''
        Check that the certificate retrieved from the signed message
        matches the certificate used to sign it.
        '''
        signed_msg = sign(MSG, TEST_CERT_FILE, TEST_KEY_FILE)

        cert = get_signer_cert(signed_msg)
        # Remove any information preceding the encoded certificate.
        cert = cert[cert.find('-----BEGIN'):]

        with open(TEST_CERT_FILE, 'r') as test_cert:
            cert_string = test_cert.read()

        if cert.strip() != cert_string.strip():
            self.fail('Certificate retrieved from signature '
                      'does not match certificate used to sign.')
Exemple #6
0
 def _send_msg(self, message, msgid):
     '''
     Send one message using stomppy.  The message will be signed using 
     the host cert and key.  If an encryption certificate
     has been supplied, the message will also be encrypted.
     '''
     log.info('Sending message: %s', msgid)
     headers = {'destination': self._dest, 'receipt': msgid,
                'empa-id': msgid}
     
     if message is not None:
         to_send = crypto.sign(message, self._cert, self._key)
         if self._enc_cert is not None:
             to_send = crypto.encrypt(to_send, self._enc_cert)
     else:
         to_send = ''
         
     self._conn.send(to_send, headers=headers)
Exemple #7
0
    def _send_msg_ams(self, text, msgid):
        """Send one message using AMS, returning the AMS ID of the mesage.

        The message will be signed using the host cert and key. If an
        encryption certificate has been supplied, the message will also be
        encrypted.
        """
        log.info('Sending message: %s', msgid)
        if text is not None:
            # First we sign the message
            to_send = crypto.sign(text, self._cert, self._key)
            # Possibly encrypt the message.
            if self._enc_cert is not None:
                to_send = crypto.encrypt(to_send, self._enc_cert)
            # Then we need to wrap text up as an AMS Message.
            message = AmsMessage(data=to_send,
                                 attributes={'empaid': msgid}).dict()

            argo_response = self._ams.publish(self._dest, message, retry=3)
            return argo_response['messageIds'][0]
Exemple #8
0
    def test_sign(self):
        '''
        I haven't found a good way to test this yet.  Each time you sign a 
        message, the output has a random element, so you can't compare strings.
        '''
        signed = sign(MSG, self.certpath, self.keypath)
        
        if not 'MIME-Version' in signed:
            self.fail("Didn't get MIME message when signing.")
            
        if not MSG in signed:
            self.fail('The plaintext should be included in the signed message.')
        
        # Indirect testing, using the verify_message() method
        retrieved_msg, retrieved_dn = verify(signed, self.ca_dir, False)
        
        if not retrieved_dn == TEST_CERT_DN:
            self.fail("The DN of the verified message didn't match the cert.")

        if not retrieved_msg == MSG:
            self.fail("The verified message didn't match the original.")
Exemple #9
0
    def _send_msg(self, message, msgid):
        '''
        Send one message using stomppy.  The message will be signed using 
        the host cert and key.  If an encryption certificate
        has been supplied, the message will also be encrypted.
        '''
        log.info('Sending message: ' + msgid)
        headers = {
            'destination': self._dest,
            'receipt': msgid,
            'empa-id': msgid
        }

        if message is not None:
            to_send = crypto.sign(message, self._cert, self._key)
            if self._enc_cert is not None:
                to_send = crypto.encrypt(to_send, self._enc_cert)
        else:
            to_send = ''

        self._conn.send(to_send, headers=headers)
Exemple #10
0
    def test_sign(self):
        '''
        I haven't found a good way to test this yet.  Each time you sign a
        message, the output has a random element, so you can't compare strings.
        '''
        signed = sign(MSG, TEST_CERT_FILE, TEST_KEY_FILE)

        if not 'MIME-Version' in signed:
            self.fail("Didn't get MIME message when signing.")

        if not MSG in signed:
            self.fail(
                'The plaintext should be included in the signed message.')

        # Indirect testing, using the verify_message() method
        retrieved_msg, retrieved_dn = verify(signed, TEST_CA_DIR, False)

        if not retrieved_dn == TEST_CERT_DN:
            self.fail("The DN of the verified message didn't match the cert.")

        if not retrieved_msg == MSG:
            self.fail("The verified message didn't match the original.")
Exemple #11
0
    def test_verify(self):

        signed_msg = sign(MSG, TEST_CERT_FILE, TEST_KEY_FILE)

        # This is a manual 'fudge' to make MS2 appear like a
        # quoted-printable message when signed
        # Encode MSG2 so it's 'quoted-printable'
        quopri_msg = quopri.encodestring(MSG2)
        # Add Content-Type and Content-Transfer-Encoding
        # headers to message
        header_quopri_msg = ('Content-Type: text/xml; charset=utf8\n'
                             'Content-Transfer-Encoding: quoted-printable\n'
                             '\n'
                             '%s' % quopri_msg)

        # We can't use crypto.sign as that assumes the use of the '-text' option
        # which cause the message to be interpreted as plaintext
        p1 = Popen([
            'openssl', 'smime', '-sign', '-inkey', TEST_KEY_FILE, '-signer',
            TEST_CERT_FILE
        ],
                   stdin=PIPE,
                   stdout=PIPE,
                   stderr=PIPE)

        signed_msg2, error = p1.communicate(header_quopri_msg)

        if error != '':
            self.fail(error)

        retrieved_msg, retrieved_dn = verify(signed_msg, TEST_CA_DIR, False)

        if not retrieved_dn == TEST_CERT_DN:
            self.fail("The DN of the verified message didn't match the cert.")

        if not retrieved_msg.strip() == MSG:
            self.fail("The verified messge didn't match the original.")

        retrieved_msg2, retrieved_dn2 = verify(signed_msg2, TEST_CA_DIR, False)

        if not retrieved_dn2 == TEST_CERT_DN:
            print retrieved_dn2
            print TEST_CERT_DN
            self.fail("The DN of the verified message didn't match the cert.")

        if not retrieved_msg2.strip() == MSG2:
            print retrieved_msg2
            print MSG2
            self.fail("The verified messge didn't match the original.")

        # Try empty string
        try:
            verify('', TEST_CA_DIR, False)
        except CryptoException:
            pass
        # Try rubbish
        try:
            verify('Bibbly bobbly', TEST_CA_DIR, False)
        except CryptoException:
            pass
        # Try None arguments
        try:
            verify('Bibbly bobbly', None, False)
        except CryptoException:
            pass
        try:
            verify(None, 'not a path', False)
        except CryptoException:
            pass
Exemple #12
0
    def test_verify(self):

        signed_msg = sign(MSG, TEST_CERT_FILE, TEST_KEY_FILE)

        # This is a manual 'fudge' to make MS2 appear like a
        # quoted-printable message when signed
        # Encode MSG2 so it's 'quoted-printable', after encoding it to ensure
        # it's a bytes object for Python 3. Latter is a no-op in Python 2.
        quopri_msg = quopri.encodestring(MSG2.encode())

        # In Python 3, encodestring() returns bytes so decode to a string while
        # Python 2 compatability is still required.
        if not isinstance(quopri_msg, str):
            quopri_msg = quopri_msg.decode()

        # Add Content-Type and Content-Transfer-Encoding
        # headers to message
        header_quopri_msg = ('Content-Type: text/xml; charset=utf8\n'
                             'Content-Transfer-Encoding: quoted-printable\n'
                             '\n'
                             '%s' % quopri_msg)

        # We can't use crypto.sign as that assumes the use of the '-text' option
        # which cause the message to be interpreted as plaintext
        p1 = Popen([
            'openssl', 'smime', '-sign', '-inkey', TEST_KEY_FILE, '-signer',
            TEST_CERT_FILE
        ],
                   stdin=PIPE,
                   stdout=PIPE,
                   stderr=PIPE,
                   universal_newlines=True)

        signed_msg2, error = p1.communicate(header_quopri_msg)

        if error != '':
            self.fail(error)

        retrieved_msg, retrieved_dn = verify(signed_msg, TEST_CA_DIR, False)

        if not retrieved_dn == TEST_CERT_DN:
            self.fail("The DN of the verified message didn't match the cert.")

        if not retrieved_msg.strip() == MSG:
            self.fail("The verified messge didn't match the original.")

        retrieved_msg2, retrieved_dn2 = verify(signed_msg2, TEST_CA_DIR, False)

        if not retrieved_dn2 == TEST_CERT_DN:
            print(retrieved_dn2)
            print(TEST_CERT_DN)
            self.fail("The DN of the verified message didn't match the cert.")

        if not retrieved_msg2.strip() == MSG2:
            print(retrieved_msg2)
            print(MSG2)
            self.fail("The verified messge didn't match the original.")

        # Try empty string
        try:
            verify('', TEST_CA_DIR, False)
        except CryptoException:
            pass
        # Try rubbish
        try:
            verify('Bibbly bobbly', TEST_CA_DIR, False)
        except CryptoException:
            pass
        # Try None arguments
        try:
            verify('Bibbly bobbly', None, False)
        except CryptoException:
            pass
        try:
            verify(None, 'not a path', False)
        except CryptoException:
            pass
Exemple #13
0
    def send_all(self):
        '''
        Send all the messages in the outgoing queue.

        Either via STOMP or HTTPS (to an Argo Message Broker).
        '''
        log.info('Found %s messages.', self._outq.count())
        for msgid in self._outq:
            if not self._outq.lock(msgid):
                log.warn('Message was locked. %s will not be sent.', msgid)
                continue

            text = self._outq.get(msgid)

            if self._protocol == Ssm2.STOMP_MESSAGING:
                # Then we are sending to a STOMP message broker.
                self._send_msg(text, msgid)

                log.info('Waiting for broker to accept message.')
                while self._last_msg is None:
                    if not self.connected:
                        raise Ssm2Exception('Lost connection.')

                log_string = "Sent %s" % msgid

            elif self._protocol == Ssm2.AMS_MESSAGING:
                # Then we are sending to an Argo Messaging Service instance.
                if text is not None:
                    # First we sign the message
                    to_send = crypto.sign(text, self._cert, self._key)
                    # Possibly encrypt the message.
                    if self._enc_cert is not None:
                        to_send = crypto.encrypt(to_send, self._enc_cert)

                    # Then we need to wrap text up as an AMS Message.
                    message = AmsMessage(data=to_send,
                                         attributes={
                                             'empaid': msgid
                                         }).dict()

                    argo_response = self._ams.publish(self._dest, message)

                    argo_id = argo_response['messageIds'][0]
                    log_string = "Sent %s, Argo ID: %s" % (msgid, argo_id)

            else:
                # The SSM has been improperly configured
                raise Ssm2Exception('Unknown messaging protocol: %s' %
                                    self._protocol)

            time.sleep(0.1)
            # log that the message was sent
            log.info(log_string)

            self._last_msg = None
            self._outq.remove(msgid)

        log.info('Tidying message directory.')
        try:
            # Remove empty dirs and unlock msgs older than 5 min (default)
            self._outq.purge()
        except OSError, e:
            log.warn('OSError raised while purging message queue: %s', e)
Exemple #14
0
    def test_verify(self):

        signed_msg = sign(MSG, TEST_CERT_FILE, TEST_KEY_FILE)

        # This is a manual 'fudge' to make MS2 appear like a
        # quoted-printable message when signed
        # Encode MSG2 so it's 'quoted-printable'
        quopri_msg = quopri.encodestring(MSG2)
        # Add Content-Type and Content-Transfer-Encoding
        # headers to message
        header_quopri_msg = ('Content-Type: text/xml; charset=utf8\n'
                             'Content-Transfer-Encoding: quoted-printable\n'
                             '\n'
                             '%s' % quopri_msg)

        # We can't use crypto.sign as that assumes the use of the '-text' option
        # which cause the message to be interpreted as plaintext
        p1 = Popen(['openssl', 'smime', '-sign', '-inkey', TEST_KEY_FILE, '-signer', TEST_CERT_FILE],
                   stdin=PIPE, stdout=PIPE, stderr=PIPE)

        signed_msg2, error = p1.communicate(header_quopri_msg)

        if error != '':
            self.fail(error)

        retrieved_msg, retrieved_dn = verify(signed_msg, TEST_CA_DIR, False)
        
        if not retrieved_dn == TEST_CERT_DN:
            self.fail("The DN of the verified message didn't match the cert.")
            
        if not retrieved_msg.strip() == MSG:
            self.fail("The verified messge didn't match the original.")
            
        retrieved_msg2, retrieved_dn2 = verify(signed_msg2, TEST_CA_DIR, False)
        
        if not retrieved_dn2 == TEST_CERT_DN:
            print retrieved_dn2
            print TEST_CERT_DN
            self.fail("The DN of the verified message didn't match the cert.")
            
        if not retrieved_msg2.strip() == MSG2:
            print retrieved_msg2
            print MSG2
            self.fail("The verified messge didn't match the original.")
            
        # Try empty string    
        try:
            verify('', TEST_CA_DIR, False)
        except CryptoException:
            pass
        # Try rubbish
        try:
            verify('Bibbly bobbly', TEST_CA_DIR, False)
        except CryptoException:
            pass
        # Try None arguments 
        try:
            verify('Bibbly bobbly', None, False)
        except CryptoException:
            pass
        try:
            verify(None, 'not a path', False)
        except CryptoException:
            pass