[ 
https://issues.apache.org/jira/browse/CXF-6579?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14737523#comment-14737523
 ] 

Phillip Klinefelter commented on CXF-6579:
------------------------------------------

The following inflateToken using a ByteArrayOutputStream passes 
testInvalidContent and testInvalidContentAfterBase64 as written.  It also 
supports any compression ratio that a client might send.

{code}
    public InputStream inflateToken(byte[] deflatedToken)
            throws DataFormatException {
        Inflater inflater = new Inflater(true);
        inflater.setInput(deflatedToken);

        byte[] buffer = new byte[deflatedToken.length];
        int inflateLen;
        ByteArrayOutputStream inflatedToken = new ByteArrayOutputStream();
        while (!inflater.finished()) {
            inflateLen = inflater.inflate(buffer, 0, deflatedToken.length);
            if (inflateLen == 0 && !inflater.finished()) {
                if (inflater.needsInput()) {
                    throw new DataFormatException("Inflater can not inflate all 
the token bytes");
                } else {
                    break;
                }
            }

            inflatedToken.write(buffer, 0, inflateLen);
        }

        return new ByteArrayInputStream(inflatedToken.toByteArray());
    }
{code}

The stream approach will also throw an exception but only when reading from the 
stream.  testInvalidContent and testInvalidContentAfterBase64 currently assume 
an exception will be thrown before reading the stream.  The stream version will 
not go into an infinite loop as described in CXF-5390 but instead throw an 
exception when trying to read the inflated token.

{code}
    public InputStream inflateToken(byte[] deflatedToken)
        throws DataFormatException {
        return new InflaterInputStream(new ByteArrayInputStream(deflatedToken),
            new Inflater(true));
    }

    @Test(expected = ZipException.class) // Caused by: 
java.util.zip.ZipException: invalid stored block lengths
    public void testInvalidContent() throws Exception {
        DeflateEncoderDecoder inflater = new DeflateEncoderDecoder();
        IOUtils.toString(inflater.inflateToken("invalid_grant".getBytes()));
    }

    @Test(expected = EOFException.class) // Caused by: java.io.EOFException: 
Unexpected end of ZLIB input stream
    public void testInvalidContentAfterBase64() throws Exception {
        DeflateEncoderDecoder inflater = new DeflateEncoderDecoder();
        byte[] base64decoded = Base64Utility.decode("invalid_grant");
        IOUtils.toString(inflater.inflateToken(base64decoded));
    }
{code}

> Inflated tokens can be corrupted if compression ratio is greater than 2:1
> -------------------------------------------------------------------------
>
>                 Key: CXF-6579
>                 URL: https://issues.apache.org/jira/browse/CXF-6579
>             Project: CXF
>          Issue Type: Bug
>          Components: Core, JAX-RS Security
>    Affects Versions: 3.0.6, 2.7.17, 3.1.2
>            Reporter: Phillip Klinefelter
>            Assignee: Sergey Beryozkin
>            Priority: Critical
>             Fix For: 3.1.3, 2.7.18, 3.0.7
>
>
> DeflateEncoderDecoder/CompressionUtils inflate method assumes that the 
> compression ratio will be 2:1.  That assumption is not true for SAML tokens 
> with many similar attribute statements.  The inflated token will be corrupted 
> with a portion of the token replaced with null characters.
> https://github.com/apache/cxf/blob/cxf-2.7.17/rt/rs/security/xml/src/main/java/org/apache/cxf/rs/security/saml/DeflateEncoderDecoder.java#L34
> https://github.com/apache/cxf/blob/cxf-3.0.6/core/src/main/java/org/apache/cxf/common/util/CompressionUtils.java#L41
> https://github.com/apache/cxf/blob/cxf-3.1.2/core/src/main/java/org/apache/cxf/common/util/CompressionUtils.java#L41
> {code}
>     @Test
>     public void testInflateDeflateWithTokenDuplication() throws Exception {
>         String token = "valid_grant valid_grant valid_grant valid_grant 
> valid_grant valid_grant";
>         DeflateEncoderDecoder deflateEncoderDecoder = new 
> DeflateEncoderDecoder();
>         byte[] deflatedToken = 
> deflateEncoderDecoder.deflateToken(token.getBytes());
>         String cxfInflatedToken = IOUtils
>                 .toString(deflateEncoderDecoder.inflateToken(deflatedToken));
>         String streamInflatedToken = IOUtils.toString(
>                 new InflaterInputStream(new 
> ByteArrayInputStream(deflatedToken),
>                         new Inflater(true)));
>         assertThat(streamInflatedToken, is(token));
>         assertThat(cxfInflatedToken, is(token));
>     }
> {code}
> The stream inflated token is correct but the CXF inflated token is invalid.
> {code}
> java.lang.AssertionError: 
> Expected: is "valid_grant valid_grant valid_grant valid_grant valid_grant 
> valid_grant"
>      got: "t valid_grant valid_grant valid_grant"
> {code}



--
This message was sent by Atlassian JIRA
(v6.3.4#6332)

Reply via email to