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

Gary Helmling commented on HBASE-10527:
---------------------------------------

So, from what I can tell, this appears to be due to some different behavior in 
ByteArrayOutputStream between IBM JDK7 and others, which is ultimately exposed 
through a bug in the Hadoop {{WritableUtils}} class.

In {{WritableUtils}}, we have...
{code}
  public static byte[] toByteArray(Writable... writables) {
    final DataOutputBuffer out = new DataOutputBuffer();
    try {
      for(Writable w : writables) {
        w.write(out);
      }
      out.close();
    } catch (IOException e) {
      throw new RuntimeException("Fail to convert writables to a byte array",e);
    }
    return out.getData();
  }
{code}

The problem is in {{return out.getData();}}, which returns the full current 
byte[] for output, not just the part that's been written.  
{{TokenIdentifier.getBytes()}} does similar processing, but handles this 
correctly...

{code}
  /**
   * Get the bytes for the token identifier
   * @return the bytes of the identifier
   */
  public byte[] getBytes() {
    DataOutputBuffer buf = new DataOutputBuffer(4096);
    try {
      this.write(buf);
    } catch (IOException ie) {
      throw new RuntimeException("i/o error in getBytes", ie);
    }
    return Arrays.copyOf(buf.getData(), buf.getLength());
  }
{code}

... returning a copy of just the array portion that has been written.

Now, why does this work in JDKs other than IBM JDK7?  The Oracle JDK 
implementation of BAOS zero initializes the underlying byte[].  However, IBM 
JDK does not seem to.  This seems to matter in computing the SHA1 for the token 
identifier password, where the trailing {{\x00}} bytes do not change the SHA1 
in the Oracle JDK, but the additional uninitialized junk does change the 
resulting SHA1 with IBM JDK.

The solution is simply to use {{TokenIdentifier.getBytes()}} in 
{{AuthenticationTokenSecretManager}}, where we had been using 
{{WritableUtils.toByteArray()}}.  This returns a correctly truncated byte array 
and matches the value returned by {{Token.getIdentifier()}}.

> TestTokenAuthentication fails with the IBM JDK
> ----------------------------------------------
>
>                 Key: HBASE-10527
>                 URL: https://issues.apache.org/jira/browse/HBASE-10527
>             Project: HBase
>          Issue Type: Bug
>    Affects Versions: 0.98.0
>         Environment: IBM J9 VM (build 2.7, JRE 1.7.0 Linux amd64-64 
> Compressed References 20131114_175264 (JIT enabled, AOT enabled)
>            Reporter: Andrew Purtell
>            Assignee: Andrew Purtell
>            Priority: Minor
>         Attachments: 
> org.apache.hadoop.hbase.security.token.TestTokenAuthentication-output.txt.gz
>
>
> "DIGEST-MD5: digest response format violation. Mismatched response."
> The failure trace:
> {noformat}
> 2014-02-13 15:41:00,449 WARN  [RpcServer.reader=1,port=54751] 
> ipc.RpcServer$Listener(794): RpcServer.listener,port=54751: count of bytes 
> read: 0
> javax.security.sasl.SaslException: DIGEST-MD5: digest response format 
> violation. Mismatched response.
>         at 
> com.ibm.security.sasl.digest.DigestMD5Server.validateClientResponse(DigestMD5Server.java:614)
>         at 
> com.ibm.security.sasl.digest.DigestMD5Server.evaluateResponse(DigestMD5Server.java:234)
>         at 
> org.apache.hadoop.hbase.ipc.RpcServer$Connection.saslReadAndProcess(RpcServer.java:1315)
>         at 
> org.apache.hadoop.hbase.ipc.RpcServer$Connection.readAndProcess(RpcServer.java:1501)
>         at 
> org.apache.hadoop.hbase.ipc.RpcServer$Listener.doRead(RpcServer.java:790)
>         at 
> org.apache.hadoop.hbase.ipc.RpcServer$Listener$Reader.doRunLoop(RpcServer.java:581)
>         at 
> org.apache.hadoop.hbase.ipc.RpcServer$Listener$Reader.run(RpcServer.java:556)
>         at 
> java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1170)
>         at 
> java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:640)
>         at java.lang.Thread.run(Thread.java:853)
> {noformat}



--
This message was sent by Atlassian JIRA
(v6.1.5#6160)

Reply via email to