def test_verify_wrong_signature(self):
        """Verify a wrong signature."""

        cert, key = gen_certificate()

        # Set up a token cookie with test data.
        atr = token_pb2.AuthTokenRequest()
        atr.certificate = _TEST_CERT
        atr.return_uri = 'https://localhost/login'
        atr.original_uri = 'https://localhost/'
        atr.app_name = 'Test Application'

        # Fill in a bogus signature.
        h = SHA256.new('A' * 42)
        signer = PKCS1_v1_5.new(key)
        atr.signature = signer.sign(h)

        # Finally, build our own base64.
        data = base64.urlsafe_b64encode(atr.SerializeToString())

        # Verify the signature.
        vatr = token_pb2.AuthTokenRequest()
        atrc = token_cookie.AuthTokenRequestCodec(vatr,
                                                  pubkey=cert.get_pub_key())
        self.assertRaises(token_cookie.SignatureException, atrc.decode, data)
    def test_request_authorization(self):
        """Test if we can request authorization correctly."""

        cert = x509.parse_certificate(_TEST_CERT)

        auth = authenticator.Authenticator("Unit Test",
                                           cert=_TEST_CERT,
                                           key=_TEST_KEY)
        dest = authenticator.urlparse(
            auth.request_authorization(
                'http://bazquux.foo/asdf/bsdf?q=x&r=x#asd'))

        self.assertEqual("https", dest.scheme)
        self.assertEqual("login.ancient-solutions.com", dest.hostname)
        self.assertEqual("/", dest.path)

        query = authenticator.parse_qs(dest.query)
        self.assertEqual(["token"], query["response_type"])
        self.assertEqual(["http://bazquux.foo/asdf/bsdf?q=x&r=x#asd"],
                         query["redirect_uri"])
        self.assertIn("client_id", query)

        atr = token_pb2.AuthTokenRequest()
        cdc = token_cookie.AuthTokenRequestCodec(atr,
                                                 pubkey=cert.get_pub_key())
        try:
            cdc.decode(query["client_id"][0])
        except token_cookie.SignatureException as e:
            self.fail("Cannot validate signature on auth token request")

        self.assertEqual("Unit Test", atr.app_name)
        self.assertEqual("http://bazquux.foo/asdf/bsdf?q=x&r=x#asd",
                         atr.original_uri)
        self.assertEqual("http://bazquux.foo/login", atr.return_uri)
    def test_sign_and_decrypt(self):
        """Encode and decode an authentication token request object."""

        # We need a CA signed certificate, so we use the one
        # from above.
        cert = x509.parse_certificate(_TEST_CERT)
        key = RSA.importKey(_TEST_KEY)
        cacert = x509.parse_certificate(_TEST_CA)

        # Sanity check for the above certificates.
        self.assertTrue(cert.check_signature(cacert))

        # Create an AuthTokenRequest with some correct-sounding data.
        atr = token_pb2.AuthTokenRequest()
        atr.certificate = _TEST_CERT
        atr.return_uri = 'https://localhost/login'
        atr.original_uri = 'https://localhost/'
        atr.app_name = 'Test Application'

        # Create the codec and encode.
        atrc = token_cookie.AuthTokenRequestCodec(atr, privkey=key)

        data = atrc.encode()

        # Verify the signature.
        vatr = token_pb2.AuthTokenRequest()
        vatrc = token_cookie.AuthTokenRequestCodec(vatr,
                                                   pubkey=cert.get_pub_key())
        try:
            vatrc.decode(data)
        except token_cookie.SignatureException as e:
            # TODO(caoimhe): Reenable this test.
            self.fail("Can't verify signature using original certificate")

        self.assertEqual(atr, vatr)

        # Decode again, using the contained certificate.
        vatr.Clear()
        vatrc = token_cookie.AuthTokenRequestCodec(vatr, cacert=cacert)
        try:
            vatrc.decode(data)
        except token_cookie.SignatureException as e:
            # TODO(caoimhe): reenable this test.
            # self.fail("Can't verify signature using inband certificate")
            pass

        self.assertEqual(atr, vatr)
    def test_verify_unknown_signer(self):
        """Verify a wrong signature."""

        cert, key = gen_certificate()
        cacert = x509.parse_certificate(_TEST_CA)

        # Set up a token cookie with test data.
        atr = token_pb2.AuthTokenRequest()
        atr.certificate = _TEST_CERT
        atr.return_uri = 'https://localhost/login'
        atr.original_uri = 'https://localhost/'
        atr.app_name = 'Test Application'

        # Create the codec and encode.
        atrc = token_cookie.AuthTokenRequestCodec(atr, privkey=key)
        data = atrc.encode()

        # Verify the signature.
        vatr = token_pb2.AuthTokenRequest()
        vatrc = token_cookie.AuthTokenRequestCodec(vatr, cacert=cacert)
        self.assertRaises(token_cookie.SignatureException, vatrc.decode, data)
Example #5
0
    def decode(self, src):
        """Verify the signature and decode the request.

        Decode the structure. Verifies the signature with the given
        public key, or with the key contained inside the message if
        None is passed.

        Args:
        src: string containing the base64 encoded cookie.

        Return:
        Integer value indicating the length of the data which was
        read; this is so it can be skipped if multiple records are
        returned. This length is after base64 decoding, so a
        multiplier must be applied.
        """
        data = base64.urlsafe_b64decode(src)
        self._atr.ParseFromString(data)

        # We'll need a copy of the data so we can verify it by
        # setting the signature to None.
        pb = token_pb2.AuthTokenRequest()
        pb.ParseFromString(data)
        pb.ClearField("signature")

        h = SHA256.new(pb.SerializeToString())

        if self._pub:
            verifier = PKCS1_v1_5.new(self._pub)
        else:
            # Attempt to extract the certificate from the request.
            cert = x509.parse_certificate(self._atr.certificate)

            if not self._ca:
                raise NoKeyException()
            if not cert.check_signature(self._ca):
                raise SignatureException()

            verifier = PKCS1_v1_5.new(cert.get_pub_key())

        if verifier.verify(h, self._atr.signature):
            return len(data)
        else:
            raise SignatureException()
Example #6
0
    def request_authorization(self, destination_url):
        """Generates an authentication request URL for the destination_url.

        Generates an URL which the web user needs to go to in order to log in
        and/or provide their authorization token to the current web
        application. After authentication has succeeded (if at all), the
        user will eventually be sent back to destination_url.

        Args:
        destination_url: URL which we would like to return to after a
        authenticating the user successfully.

        Returns: URL the user should be redirected to in order to commence
        authentication.
        """
        atr = token_pb2.AuthTokenRequest()
        returnuri = urlparse(urljoin(destination_url, '/login'))

        atr.app_name = self._app_name
        atr.certificate = self._plain_cert
        atr.return_uri = returnuri.geturl()
        atr.original_uri = destination_url

        if not self._rsa_key:
            raise token_cookie.NoKeyException()

        atrc = token_cookie.AuthTokenRequestCodec(
            atr, privkey=self._rsa_key, pubkey=self._cert.get_pub_key())
        atrdata = atrc.encode()

        params = {
            "client_id": atrdata,
            "redirect_uri": destination_url,
            "response_type": "token",
            "debug": str(atr),
        }
        newurl = ("https://" + self._authserver + "/?" + urlencode(params))
        return newurl