2016-05-18 2 views
-1

私はSSLEngineを作成する前に、最初のSSLクライアントhello(もちろん存在する場合)の拡張子にSNIサーバー名が必要です。私はここClientHelloクラスを見ています...(私は現在jdk 8にいますが)。最初のhello SSLメッセージをjdk ClientHello.javaオブジェクトに変換する方法は?

http://hg.openjdk.java.net/jdk9/dev/jdk/file/6407a15e2274/src/share/classes/sun/security/ssl/HandshakeMessage.java

誰もが、私はより簡単にSNIのサーバー名をつかむために、データ構造へのByteBufferから行くことができる方法を知っていますか? (バイトバッファには、SSLパケットのサイズを確認してから、完全なssl helloパケットが出るまで待機するのに必要なサイズ以上のサイズが含まれます)。

また、この記事は場所で再利用する他の誰かのためにIs there any Java x509certificate ClientHello parser in Java?

おかげで、 ディーン

答えて

0

を開始する部分を取得するために非常によく働いていたが、これはそれで私の最初に行くであり、それは働きました私はハンドシェークが始まる前にsniServerNameをつかむことができるように...

public class ClientHelloParser { 
private static final short HANDSHAKE_CONTENT_TYPE = 22; 
private static final short CLIENTHELLO_MESSAGE_TYPE = 1; 
private static final short SSLV2_CLIENTHELLO = 128; 

private static final int SERVER_NAME_EXTENSION_TYPE = 0; 
private static final short HOST_NAME_TYPE = 0; 

private ByteBuffer cachedBuffer; 
private BufferPool pool; 

public ClientHelloParser(BufferPool pool) { 
    this.pool = pool; 
} 

/** 
* Returns null if we still need more data 
* 
* @param b 
* @return 
*/ 
ParseResult fetchServerNamesIfEntirePacketAvailable(ByteBuffer b) { 
    if(cachedBuffer != null) { 
     //prefix cachedBuffer in front of b and assign to b as the packet that is coming in 
     ByteBuffer newBuf = pool.nextBuffer(cachedBuffer.remaining()+b.remaining()); 
     newBuf.put(cachedBuffer); 
     newBuf.put(b); 
     newBuf.flip(); 
     pool.releaseBuffer(b); //release b that is now in the newBuf 
     pool.releaseBuffer(cachedBuffer); //release cached buffer that is now in newBuf 
     b = newBuf; 
    } 

    if(b.remaining() < 5) { 
     cachedBuffer = b; 
     return null; //wait for more data 
    } 

    int recordSize = 0; 
    ByteBuffer duplicate = b.duplicate(); 
    short contentType = getUnsignedByte(duplicate); 
    if(contentType == HANDSHAKE_CONTENT_TYPE) { 
     getUnsignedByte(duplicate); 
     getUnsignedByte(duplicate); 
     recordSize = getUnsignedShort(duplicate); 

      // Now wait until we have the entire record 
     if (b.remaining() < (5 + recordSize)) { 
      // Keep buffering 
      return null; 
     }     
    } else if (contentType == SSLV2_CLIENTHELLO) { 
     short len = getUnsignedByte(duplicate); 

     // Decode the length 
     recordSize = ((contentType & 0x7f) << 8 | len); 

     // Now wait until we have the entire record 
     if (b.remaining() < (2 + recordSize)) { 
      // Keep buffering 
      return null; 
     } 

    } else { 
     throw new IllegalStateException("contentType="+contentType+" not supported in ssl hello handshake packet"); 
    } 

    short messageType = getUnsignedByte(duplicate); 
    if (messageType != CLIENTHELLO_MESSAGE_TYPE) { 
     throw new IllegalStateException("something came before ClientHello :(messageType="+messageType); 
    } 

    if (contentType == HANDSHAKE_CONTENT_TYPE) { 
     // If we're not an SSLv2 ClientHello, then skip the ClientHello 
     // message size. 
     duplicate.get(new byte[3]); 

     // Use the ClientHello ProtocolVersion 
     getUnsignedShort(duplicate); 

     // Skip ClientRandom 
     duplicate.get(new byte[32]); 

     // Skip SessionID 
     int sessionIDSize = getUnsignedByte(duplicate); 
     duplicate.get(new byte[sessionIDSize]); 

     //read in and discard cipherSuite... 
     int cipherSuiteSize = getUnsignedShort(duplicate); 
     duplicate.get(new byte[cipherSuiteSize]); 

     //read in compression methods size and discard.. 
     short compressionMethodsLen = getUnsignedByte(duplicate); 
     duplicate.get(new byte[compressionMethodsLen]); 

     int extensionLen = getUnsignedShort(duplicate); 
     List<String> names = readInExtensionServerNames(duplicate, extensionLen); 

     return new ParseResult(b, names); 
    } else { 
     // SSLv2 ClientHello. 
     // Use the ClientHello ProtocolVersion 
     //SslVersion version = SslVersion.decode(getUnsignedByte(duplicate)); 

     throw new UnsupportedOperationException("not supported yet"); 
    } 
} 

private List<String> readInExtensionServerNames(ByteBuffer duplicate, int len) { 
    List<String> serverNames = new ArrayList<>(); 
    int byteCount = 0; 
    while(byteCount < len) { 
     byteCount += 4; //reading in 4 bytes so add them in 
     if(duplicate.remaining() < 4) 
      throw new IllegalStateException("Corrupt packet with incorrect format"); 
     int type = getUnsignedShort(duplicate); 
     int extLen = getUnsignedShort(duplicate); 

     if(duplicate.remaining() < extLen) 
      throw new IllegalStateException("Corrupt packet with incorrect format as len didn't match"); 

     if(type == SERVER_NAME_EXTENSION_TYPE) { 
      String name = readServerNames(duplicate, extLen); 
      serverNames.add(name); 
     } else 
      duplicate.get(new byte[extLen]); 
     byteCount += extLen; 
    } 

    return serverNames; 
} 

private String readServerNames(ByteBuffer duplicate, int extLen) { 
    int byteCount = 0; 

    byteCount += 2; //for listLen 2 bytes 
    int listLen = getUnsignedShort(duplicate); 
    if(listLen + 2 != extLen) 
     throw new RuntimeException("we have something we need to fix here as listLen is only two less bytes then extensionLength"); 

    byteCount += 1; //for serverNameType 
    short serverNameType = getUnsignedByte(duplicate); 
    if(serverNameType != HOST_NAME_TYPE) 
     throw new IllegalStateException("Server name type="+serverNameType+" not supported yet"); 

    byteCount += 2; //for serverNameLen 
    int serverNameLen = getUnsignedShort(duplicate); 

    byteCount += serverNameLen; 
    if(byteCount != extLen) 
     throw new UnsupportedOperationException("bytes read in servernames extension does not match extLen(we need to loop here then)"); 

    byte[] data = new byte[serverNameLen]; 
    duplicate.get(data); 

    String serverName = new String(data); 
    return serverName; 
} 

public short getUnsignedByte(ByteBuffer bb) { 
    return ((short)(bb.get() & 0xff)); 
} 

public int getUnsignedShort (ByteBuffer bb) 
{ 
    return (bb.getShort() & 0xffff); 
} 
} 
関連する問題