Проблема OpenJDK 11 - клиент закончил рукопожатие перед последней UNWRAP - PullRequest
0 голосов
/ 21 декабря 2018

Я перевожу нашу кодовую базу с Oracle Java 1.8.0_131 на OpenJDK 11.0.1.У нас есть код, который реализует каналы сокетов nio-ssl.В Java 8 клиент-серверное рукопожатие работает нормально.В Java 11 клиент завершает рукопожатие перед тем, как развернуть последнее рукопожатие с сервера.

Чтобы создать эту проблему, я просто устанавливаю соединение между клиентом и сервером и позволяю им выполнить рукопожатие SSL.Я НЕ посылаю никаких дополнительных данных через.

Я устанавливаю соединение с помощью Java 8 и получаю вывод ниже.Затем я компилирую, собираю и запускаю тот же код с использованием Java 11 и получаю другой вывод ниже.Я не изменяю ни один из моих кодов.

У меня есть регистрация на клиенте и сервере, чтобы показать, на каком этапе рукопожатия они находятся.

Вывод журнала Java 8 - клиент

SSL Handshake Started
WRAP:OK -   BytesProduced=172  BytesConsumed=0
UNWRAP:OK - BytesProduced=0    BytesConsumed=2295
TASK
WRAP:OK -   BytesProduced=1815 BytesConsumed=0
WRAP:OK -   BytesProduced=269  BytesConsumed=0
WRAP:OK -   BytesProduced=6    BytesConsumed=0
WRAP:OK -   BytesProduced=85   BytesConsumed=0
UNWRAP:OK - BytesProduced=0    BytesConsumed=6
UNWRAP:OK - BytesProduced=0    BytesConsumed=85
SSL Handshake complete

Вывод журнала Java 8 - сервер

SSL Handshake Started
UNWRAP:OK - BytesProduced=0    BytesConsumed=172
TASK
WRAP:OK -   BytesProduced=2295 BytesConsumed=0
UNWRAP:OK - BytesProduced=0    BytesConsumed=1815
TASK
UNWRAP:OK - BytesProduced=0    BytesConsumed=269
TASK
UNWRAP:OK - BytesProduced=0    BytesConsumed=6
UNWRAP:OK - BytesProduced=0    BytesConsumed=85
WRAP:OK -   BytesProduced=6    BytesConsumed=6
WRAP:OK -   BytesProduced=85   BytesConsumed=0
SSL Handshake complete

Вывод журнала Java 11 - клиент

SSL Handshake Started
WRAP:OK -   BytesProduced=422  BytesConsumed=0
UNWRAP:OK - BytesProduced=0    BytesConsumed=160
TASK
WRAP:OK -   BytesProduced=6    BytesConsumed=0
UNWRAP:OK - BytesProduced=0    BytesConsumed=6
UNWRAP:OK - BytesProduced=0    BytesConsumed=2204
TASK
WRAP:OK -   BytesProduced=2067 BytesConsumed=0
SSL Handshake complete
UNWRAP:OK - BytesProduced=0    BytesConsumed=72

Вывод журнала Java 11 - сервер

SSL Handshake Started
UNWRAP:OK - BytesProduced=0    BytesConsumed=422
TASK
WRAP:OK -   BytesProduced=160  BytesConsumed=0
WRAP:OK -   BytesProduced=6    BytesConsumed=0
WRAP:OK -   BytesProduced=2204 BytesConsumed=0
UNWRAP:OK - BytesProduced=0    BytesConsumed=6
UNWRAP:OK - BytesProduced=0    BytesConsumed=2067
TASK
WRAP:OK -   BytesProduced=72    BytesConsumed=0
SSL Handshake complete

Код для рукопожатия

engine.beginHandshake();
HandshakeStatus hs = engine.getHandshakeStatus();
while(hs != HandshakeStatus.FINISHED && hs != HandshakeStatus.NOT_HANDSHAKING){
  switch(hs){
    case NEED_WRAP:
      SSLEngineResult res = engine.wrap(myAppData, myNetData)
      hs = res.getHandshakeStatus();
      switch(res.getStatus()){
        case OK:
          // write myNetData
        case BUFFER_OVERFLOW:
          // increase size of myNetData
        case BUFFER_UNDERFLOW:
          // throw exception
        case CLOSED:
          // clean up
        default:
          // throw illegal state exception
      }
      break;
    case NEED_UNWRAP:
      boolean complete = false;
      while(!complete){
        /*
         * First handle any encrypted data left on buffer
         * If there is none, read in more
         */
        if(peerNetData.position() > 0 || channel.read(peerNetData) > 0){
          peerNetData.flip();
          res = engine.unwrap(peerNetData, peerAppData);
          hs = res.getHandshakeStatus();
          switch(res.getStatus()){
            case OK:
              complete = true;
              peerNetData.compact();
              break;
            case BUFFER_UNDERFLOW:
              // if buffer is full, increase size
              // if buffer isn't full, compact and read
            case BUFFER_OVERFLOW:
              // increase size of peerAppData
            case CLOSED:
              // cleanup
            default:
              // throw illegal state exception
          }
        }
      }
      break;
    case NEED_TASK:
      // Run task
      hs = engine.getHandshakeStatus();
      break;
    case FINISHED:
      break;
    case NOT_HANDSHAKING:
      break;
    default:
      // illegal state
  }
}

К сожалению, мой код находится в воздушном пространстве, поэтому вставить его здесь непросто.Я набрал его вручную, чтобы скобки и вкладки могли не совпадать.

Суть в том, что hs = res.getHandshakeStatus(...) возвращает FINISHED на клиентском компьютере после переноса 2067 байтов, когда кажется, что он должен вернутьсяNEED_UNWRAP.Если я изменю его на hs = engine.getHandshakeStatus(), он вернет NOT_HANDSHAKING.

. На серверном компьютере hs = engine.getHandshakeStatus() вернет NEED_WRAP после запуска последней задачи, в результате чего она будет WRAP длиться 72 байта.

Почему SSLEngine на моем клиентском компьютере дает мне статус рукопожатия "ЗАВЕРШЕНО", если на сервере еще есть 72 байта данных для UNWRAP с сервера?У кого-нибудь еще были проблемы с пользовательской логикой рукопожатия для Java 11?

1 Ответ

0 голосов
/ 21 декабря 2018

В JavaDoc SSLEngine есть примечание о параллелизме в конце описания класса.

Таким образом, я предполагаю, что ваша проблема похожа на проблему параллелизма, основанную на состоянии гонки.Может отличаться способ одновременного вызова функций wrap и unwrap после перехода с JDK 8 на JDK 11. В приведенном вами примере кода нет синхронизированных операторов.

Если вы синхронизируете оба вызова функцийс общим объектом рукопожатие должно завершаться каждый раз после последней разворачивания.

...