示例#1
0
    def sending(self, context):
        '''Signs XML before sending'''

        signature_template = '''
            <Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
              <SignedInfo>
              <CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
              <SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1" />
              <Reference URI="#%(REFERENCE_ID)s">
                <Transforms>
                  <Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" />
                  <Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
                </Transforms>
                <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
                <DigestValue></DigestValue>
              </Reference>
              </SignedInfo>
              <SignatureValue />
              <KeyInfo>
                <X509Data>
                  <X509Certificate />
                </X509Data>
              </KeyInfo>
            </Signature>
        '''

        envelope_element = Parser().parse(string=context.envelope).root()
        envelope_element.refitPrefixes()

        body = envelope_element.getChild('Body')
        payload = body[0]

        qname = payload.qname()
        if 'Echo' in qname:
            return

        reference_id = "refId:%s" % uuid4()
        payload.set('Id', reference_id)
        signature_template %= {'REFERENCE_ID': reference_id}

        signature_element = Parser().parse(string=signature_template).root()
        payload.append(signature_element)

        envelope = self.DTD_TEST_ID % qname
        envelope += envelope_element.str()
        envelope = envelope.encode('utf-8')

        signer = XMLDSIG()
        signer.load_key(self.key_path,
                        password=self.key_passphrase,
                        cert_path=self.cert_path)
        context.envelope = signer.sign(envelope)
        context.envelope = self.RE_DTD_TEST.sub('', context.envelope)
示例#2
0
    def sending(self, context):
        '''Signs XML before sending'''

        signature_template = '''
            <Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
              <SignedInfo>
              <CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
              <SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1" />
              <Reference URI="#%(REFERENCE_ID)s">
                <Transforms>
                  <Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" />
                  <Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
                </Transforms>
                <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
                <DigestValue></DigestValue>
              </Reference>
              </SignedInfo>
              <SignatureValue />
              <KeyInfo>
                <X509Data>
                  <X509Certificate />
                </X509Data>
              </KeyInfo>
            </Signature>
        '''

        envelope_element = Parser().parse(string=context.envelope).root()
        envelope_element.refitPrefixes()

        body = envelope_element.getChild('Body')
        payload = body[0]

        qname = payload.qname()
        if 'Echo' in qname:
            return

        reference_id = "refId:%s" % uuid4()
        payload.set('Id', reference_id)
        signature_template %= {'REFERENCE_ID': reference_id}

        signature_element = Parser().parse(string=signature_template).root()
        payload.append(signature_element)

        envelope = self.DTD_TEST_ID % qname
        envelope += envelope_element.str()
        envelope = envelope.encode('utf-8')

        signer = XMLDSIG()
        signer.load_key(self.key_path,
                        password=self.key_passphrase,
                        cert_path=self.cert_path)
        context.envelope = signer.sign(envelope)
        context.envelope = self.RE_DTD_TEST.sub('', context.envelope)
示例#3
0
    def received(self, context):
        '''Verifies XML signature of received message'''

        def _extract_keyinfo_cert(payload):
            '''Extract the signing certificate from KeyInfo.'''

            cert_der = payload.getChild('Signature')
            cert_der = cert_der.getChild('KeyInfo')
            cert_der = cert_der.getChild('X509Data')
            cert_der = cert_der.getChild('X509Certificate').getText().strip()
            cert_der = cert_der.decode('base64')
            return cert_der

        def _verify_cn(cert, cis_cert_cn):
            '''Verify signature certificate common name'''

            common_name = cert.get_subject().commonName

            if common_name != cis_cert_cn:
                raise Exception('Invalid certificate common name in response: '
                                '%s != %s' % (cis_cert_cn, common_name))

        def _fault(code, msg):
            '''Generate fault XML'''

            faultcode = Element('faultcode').setText(code)
            faultstring = Element('faultstring').setText(msg)
            fault = Element('Fault').append([faultcode, faultstring])
            body = Element('Body').append(fault)
            envelope = Element('Envelope', ns=soap_envns)
            envelope.append(body)
            envelope.refitPrefixes()

            return envelope.str()


        valid_signature = False

        try:
            if not self.cis_ca_path:
                raise Exception('Certificate Authority not defined')

            reply_element = Parser().parse(string=context.reply).root()
            body = reply_element.getChild('Body')
            payload = body[0]
            qname = payload.qname()
            cert_der = _extract_keyinfo_cert(payload)
            cert = crypto.load_certificate(crypto.FILETYPE_ASN1, cert_der)

            if 'Echo' in qname or 'Fault' in qname:
                LOGGER.warning('Not verifying certificate for qname: %s', qname)
                return

            if self.cis_cert_cn:
                _verify_cn(cert, self.cis_cert_cn)
            else:
                LOGGER.warning('CIS certificate common name not configured')

            reply = self.DTD_TEST_ID % qname
            reply += self.RE_XML_HEADER.sub('', context.reply)

            verifier = XMLDSIG()
            verifier.load_cert(self.cis_ca_path)
            valid_signature = verifier.verify(reply)

        except Exception as exc:
            LOGGER.exception('%s: %s', exc, context.reply)
            context.reply = _fault('Client',
                                   'Invalid response signature: %s' % exc)
        else:
            if not valid_signature:
                LOGGER.error('Invalid response signature: %s', context.reply)
                context.reply = _fault('Client',
                                       'Invalid response signature')
示例#4
0
    def received(self, context):
        '''Verifies XML signature of received message'''
        def _extract_keyinfo_cert(payload):
            '''Extract the signing certificate from KeyInfo.'''

            cert_der = payload.getChild('Signature')
            cert_der = cert_der.getChild('KeyInfo')
            cert_der = cert_der.getChild('X509Data')
            cert_der = cert_der.getChild('X509Certificate').getText().strip()
            cert_der = cert_der.decode('base64')
            return cert_der

        def _verify_cn(cert, cis_cert_cn):
            '''Verify signature certificate common name'''

            common_name = cert.get_subject().commonName

            if common_name != cis_cert_cn:
                raise Exception('Invalid certificate common name in response: '
                                '%s != %s' % (cis_cert_cn, common_name))

        def _fault(code, msg):
            '''Generate fault XML'''

            faultcode = Element('faultcode').setText(code)
            faultstring = Element('faultstring').setText(msg)
            fault = Element('Fault').append([faultcode, faultstring])
            body = Element('Body').append(fault)
            envelope = Element('Envelope', ns=soap_envns)
            envelope.append(body)
            envelope.refitPrefixes()

            return envelope.str()

        valid_signature = False

        try:
            if not self.cis_ca_path:
                raise Exception('Certificate Authority not defined')

            reply_element = Parser().parse(string=context.reply).root()
            body = reply_element.getChild('Body')
            payload = body[0]
            qname = payload.qname()
            cert_der = _extract_keyinfo_cert(payload)
            cert = crypto.load_certificate(crypto.FILETYPE_ASN1, cert_der)

            if 'Echo' in qname or 'Fault' in qname:
                LOGGER.warning('Not verifying certificate for qname: %s',
                               qname)
                return

            if self.cis_cert_cn:
                _verify_cn(cert, self.cis_cert_cn)
            else:
                LOGGER.warning('CIS certificate common name not configured')

            reply = self.DTD_TEST_ID % qname
            reply += self.RE_XML_HEADER.sub('', context.reply)

            verifier = XMLDSIG()
            verifier.load_cert(self.cis_ca_path)
            valid_signature = verifier.verify(reply)

        except Exception as exc:
            LOGGER.exception('%s: %s', exc, context.reply)
            context.reply = _fault('Client',
                                   'Invalid response signature: %s' % exc)
        else:
            if not valid_signature:
                LOGGER.error('Invalid response signature: %s', context.reply)
                context.reply = _fault('Client', 'Invalid response signature')