Почему SChannel TLS ограничивает сообщение до 32 КБ - PullRequest
0 голосов
/ 28 февраля 2020

Я работаю над использованием SChannel для создания клиент-серверной программы. Одна из вещей, которые я хотел бы сделать - это обмен файлами. Я нашел пример кода клиентской программы, использующей Schannel для связи, и мне интересно, почему максимальный размер сообщения составляет 32 КБ. Вот пример функции, которая принимает

int tls_handshake(tls_ctx *c, tls_session *s) {
    DWORD         flags_in, flags_out;
    SecBuffer     ib[2], ob[1];
    SecBufferDesc in, out;
    int           len;

    // send initial hello
    if (!tls_hello(c, s)) {
      return 0;
    }

    flags_in = ISC_REQ_REPLAY_DETECT   |
               ISC_REQ_CONFIDENTIALITY |
               ISC_RET_EXTENDED_ERROR  |
               ISC_REQ_ALLOCATE_MEMORY |
               ISC_REQ_MANUAL_CRED_VALIDATION;

    c->ss     = SEC_I_CONTINUE_NEEDED;
    s->buflen = 0;

    while (c->ss == SEC_I_CONTINUE_NEEDED ||
           c->ss == SEC_E_INCOMPLETE_MESSAGE ||
           c->ss == SEC_I_INCOMPLETE_CREDENTIALS)
    {
      if (c->ss  == SEC_E_INCOMPLETE_MESSAGE)
      {
        // receive data from server
        len = recv(s->sck, &s->buf[s->buflen], s->maxlen - s->buflen, 0);

        // socket error?
        if (len  == SOCKET_ERROR) {
          c->ss  =  SEC_E_INTERNAL_ERROR;
          break;
        // server disconnected?
        } else if (len==0) {
          c->ss = SEC_E_INTERNAL_ERROR;
          break;
        }
        // increase buffer position
        s->buflen += len;
      }

      // inspect what we've received
      //tls_hex_dump(s->buf, s->buflen);

      // input data
      ib[0].pvBuffer   = s->buf;
      ib[0].cbBuffer   = s->buflen;
      ib[0].BufferType = SECBUFFER_TOKEN;

      // empty buffer
      ib[1].pvBuffer   = NULL;
      ib[1].cbBuffer   = 0;
      ib[1].BufferType = SECBUFFER_VERSION;

      in.cBuffers      = 2;
      in.pBuffers      = ib;
      in.ulVersion     = SECBUFFER_VERSION;

      // output from schannel
      ob[0].pvBuffer   = NULL;
      ob[0].cbBuffer   = 0;
      ob[0].BufferType = SECBUFFER_VERSION;

      out.cBuffers     = 1;
      out.pBuffers     = ob;
      out.ulVersion    = SECBUFFER_VERSION;

      c->ss = c->sspi->
        InitializeSecurityContextA(
        &s->cc, &s->ctx, NULL, flags_in, 0,
        SECURITY_NATIVE_DREP, &in, 0, NULL,
        &out, &flags_out, NULL);

      // what have we got so far?
      if (c->ss == SEC_E_OK ||
          c->ss == SEC_I_CONTINUE_NEEDED ||
          (FAILED(c->ss) && (flags_out & ISC_RET_EXTENDED_ERROR)))
      {
        // response for server?
        if (ob[0].cbBuffer != 0 && ob[0].pvBuffer) {
          // send response
          tls_send(s->sck, ob[0].pvBuffer, ob[0].cbBuffer);
          // free response
          c->sspi->FreeContextBuffer(ob[0].pvBuffer);
          ob[0].pvBuffer = NULL;
        }
      }
      // incomplete message? continue reading
      if (c->ss==SEC_E_INCOMPLETE_MESSAGE) continue;

      // completed handshake?
      if (c->ss==SEC_E_OK) {
        s->established = 1;

        // If the "extra" buffer contains data, this is encrypted application
        // protocol layer stuff and needs to be saved. The application layer
        // will decrypt it later with DecryptMessage.
        if (ib[1].BufferType == SECBUFFER_EXTRA) {
          DEBUG_PRINT("  [ we have extra data after handshake.\n");
          memmove(s->pExtra.pvBuffer,
              &s->buf[(s->buflen - ib[1].cbBuffer)], ib[1].cbBuffer);

          s->pExtra.cbBuffer   = ib[1].cbBuffer;
          s->pExtra.BufferType = SECBUFFER_TOKEN;
        } else {
          // no extra data encountered
          s->pExtra.pvBuffer   = NULL;
          s->pExtra.cbBuffer   = 0;
          s->pExtra.BufferType = SECBUFFER_EMPTY;
        }
        break;
      }
      // some other error
      if(FAILED(c->ss)) break;

      // Copy any leftover data from the "extra" buffer, and go around again.
      if(ib[1].BufferType == SECBUFFER_EXTRA) {
        memmove(s->buf, &s->buf[(s->buflen - ib[1].cbBuffer)], ib[1].cbBuffer);
        s->buflen = ib[1].cbBuffer;
        DEBUG_PRINT("  [ we have %i bytes of extra data.\n", s->buflen);

        tls_hex_dump(s->buf, s->buflen);

      } else {
        s->buflen = 0;
      }
    }
    return c->ss==SEC_E_OK ? 1 : 0;
}

Код от Github, который я нашел здесь: https://github.com/odzhan/shells/blob/master/s6/tls.c

Внутри одного из его заголовочных файлов он определяет

#define TLS_MAX_BUFSIZ      32768

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

...