public void parseClientHeader()

in redback-integrations/redback-common-integrations/src/main/java/org/apache/archiva/redback/integration/filter/authentication/digest/HttpDigestHeader.java [62:147]


    public void parseClientHeader( String rawHeader, String expectedRealm, String digestKey )
        throws HttpAuthenticationException
    {
        Properties authHeaderProps = HttpUtils.complexHeaderToProperties( rawHeader, ",", "=" );

        username = authHeaderProps.getProperty( "username" );
        realm = authHeaderProps.getProperty( "realm" );
        nonce = authHeaderProps.getProperty( "nonce" );
        uri = authHeaderProps.getProperty( "uri" );
        response = authHeaderProps.getProperty( "response" );
        qop = authHeaderProps.getProperty( "qop" );
        nc = authHeaderProps.getProperty( "nc" );
        cnonce = authHeaderProps.getProperty( "cnonce" );

        // [RFC 2067] Validate all required values
        if ( StringUtils.isEmpty( username ) || StringUtils.isEmpty( realm ) || StringUtils.isEmpty( nonce )
            || StringUtils.isEmpty( uri ) || StringUtils.isEmpty( response ) )
        {
            log.debug( "Missing mandatory fields: Raw Digest Header : [{}]", rawHeader );

            throw new HttpAuthenticationException( "Missing mandatory digest fields per RFC2069." );
        }

        // [RFC 2617] Validate realm.
        if ( !StringUtils.equals( expectedRealm, realm ) )
        {
            log.debug( "Realm name is invalid: expected [{}] but got [{}]", expectedRealm, realm );

            throw new HttpAuthenticationException( "Response realm does not match expected realm." );
        }

        // [RFC 2617] Validate "auth" qop
        if ( StringUtils.equals( "auth", qop ) )
        {
            if ( StringUtils.isEmpty( nc ) || StringUtils.isEmpty( cnonce ) )
            {
                log.debug( "Missing mandatory qop fields: nc [{}] cnonce [{}]", nc, cnonce );

                throw new HttpAuthenticationException( "Missing mandatory qop digest fields per RFC2617." );
            }
        }

        // [RFC 2617] Validate nonce
        if ( !Base64.isBase64( nonce.getBytes() ) )
        {
            log.debug( "Nonce is not encoded in Base64: nonce [{}]", nonce );

            throw new HttpAuthenticationException( "Response nonce is not encoded in Base64." );
        }

        // Decode nonce
        String decodedNonce = new String( Base64.decodeBase64( nonce.getBytes() ) );
        String nonceTokens[] = StringUtils.split( decodedNonce, ":" );

        // Validate nonce format
        if ( nonceTokens.length != 2 )
        {
            log.debug( "Nonce format expected [2] elements, but got [{}] instead.  Decoded nonce [{}]",
                       nonceTokens.length, decodedNonce );

            throw new HttpAuthenticationException(
                "Nonce format is invalid.  " + "Received an unexpected number of sub elements." );
        }

        // Extract nonce timestamp
        long nonceTimestamp = 0;

        try
        {
            nonceTimestamp = Long.parseLong( nonceTokens[0] );
        }
        catch ( NumberFormatException e )
        {
            throw new HttpAuthenticationException( "Unexpected nonce timestamp." );
        }

        // Extract nonce signature
        String expectedSignature = Digest.md5Hex( nonceTimestamp + ":" + digestKey );

        if ( !StringUtils.equals( expectedSignature, nonceTokens[1] ) )
        {
            log.error( "Nonce parameter has been compromised." );

            throw new HttpAuthenticationException( "Nonce parameter has been compromised." );
        }
    }