<commit_before>/** @file

  A brief file description

  @section license License

  Licensed to the Apache Software Foundation (ASF) under one
  or more contributor license agreements.  See the NOTICE file
  distributed with this work for additional information
  regarding copyright ownership.  The ASF licenses this file
  to you under the Apache License, Version 2.0 (the
  "License"); you may not use this file except in compliance
  with the License.  You may obtain a copy of the License at

      http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
 */
#include "ink_config.h"
#include "records/I_RecHttp.h"
#include "P_Net.h"
#include "P_SSLNextProtocolSet.h"
#include "P_SSLUtils.h"
#include "InkAPIInternal.h"	// Added to include the ssl_hook definitions

// Defined in SSLInternal.c, should probably make a separate include
// file for this at some point
void SSL_set_rbio(SSLNetVConnection *sslvc, BIO *rbio);

#define SSL_READ_ERROR_NONE	  0
#define SSL_READ_ERROR		  1
#define SSL_READ_READY		  2
#define SSL_READ_COMPLETE	  3
#define SSL_READ_WOULD_BLOCK      4
#define SSL_READ_EOS		  5
#define SSL_HANDSHAKE_WANT_READ   6
#define SSL_HANDSHAKE_WANT_WRITE  7
#define SSL_HANDSHAKE_WANT_ACCEPT 8
#define SSL_HANDSHAKE_WANT_CONNECT 9
#define SSL_WRITE_WOULD_BLOCK     10
#define SSL_WAIT_FOR_HOOK         11

#ifndef UIO_MAXIOV
#define NET_MAX_IOV 16          // UIO_MAXIOV shall be at least 16 1003.1g (5.4.1.1)
#else
#define NET_MAX_IOV UIO_MAXIOV
#endif

ClassAllocator<SSLNetVConnection> sslNetVCAllocator("sslNetVCAllocator");

namespace {
  /// Callback to get two locks.
  /// The lock for this continuation, and for the target continuation.
  class ContWrapper : public Continuation
  {
  public:
    /** Constructor.
        This takes the secondary @a mutex and the @a target continuation
        to invoke, along with the arguments for that invocation.
    */
    ContWrapper(
      ProxyMutex* mutex ///< Mutex for this continuation (primary lock).
      , Continuation* target ///< "Real" continuation we want to call.
      , int eventId = EVENT_IMMEDIATE ///< Event ID for invocation of @a target.
      , void* edata = 0 ///< Data for invocation of @a target.
      )
      : Continuation(mutex)
      , _target(target)
      , _eventId(eventId)
      , _edata(edata)
    {
      SET_HANDLER(&ContWrapper::event_handler);
    }

    /// Required event handler method.
    int event_handler(int, void*)
    {
      EThread* eth = this_ethread();

      MUTEX_TRY_LOCK(lock, _target->mutex, eth);
      if (lock.is_locked()) { // got the target lock, we can proceed.
        _target->handleEvent(_eventId, _edata);
        delete this;
      } else { // can't get both locks, try again.
        eventProcessor.schedule_imm(this, ET_NET);
      }
      return 0;
    }

    /** Convenience static method.

        This lets a client make one call and not have to (accurately)
        copy the invocation logic embedded here. We duplicate it near
        by textually so it is easier to keep in sync.

        This takes the same arguments as the constructor but, if the
        lock can be obtained immediately, does not construct an
        instance but simply calls the @a target.
    */
    static void wrap(
      ProxyMutex* mutex ///< Mutex for this continuation (primary lock).
      , Continuation* target ///< "Real" continuation we want to call.
      , int eventId = EVENT_IMMEDIATE ///< Event ID for invocation of @a target.
      , void* edata = 0 ///< Data for invocation of @a target.
      ) {
      EThread* eth = this_ethread();
      MUTEX_TRY_LOCK(lock, target->mutex, eth);
      if (lock.is_locked()) {
        target->handleEvent(eventId, edata);
      } else {
        eventProcessor.schedule_imm(new ContWrapper(mutex, target, eventId, edata), ET_NET);
      }
    }

  private:
    Continuation* _target; ///< Continuation to invoke.
    int _eventId; ///< with this event
    void* _edata; ///< and this data
  };
}

//
// Private
//

static SSL *
make_ssl_connection(SSL_CTX * ctx, SSLNetVConnection * netvc)
{
  SSL * ssl;

  if (likely(ssl = SSL_new(ctx))) {
    netvc->ssl = ssl;

    // Only set up the bio stuff for the server side
    if (netvc->getSSLClientConnection()) {
      SSL_set_fd(ssl, netvc->get_socket());
    } else {
      netvc->initialize_handshake_buffers();
      BIO *rbio = BIO_new(BIO_s_mem());
      BIO *wbio = BIO_new_fd(netvc->get_socket(), BIO_NOCLOSE);
      BIO_set_mem_eof_return(wbio, -1);
      BIO* old_rbio = SSL_get_rbio(ssl);
      BIO* old_wbio = SSL_get_wbio(ssl);
      if (old_rbio) {
        BIO_free(old_rbio);
      }
      if (old_wbio) {
        BIO_free(old_wbio);
      }
      SSL_set_bio(ssl, rbio, wbio);
    }

    SSL_set_app_data(ssl, netvc);
  }

  return ssl;
}

static void
debug_certificate_name(const char * msg, X509_NAME * name)
{
  BIO * bio;

  if (name == NULL) {<commit_msg>[TS-3261]: remove redundant BIO_free() for new SSL object, per Leif's suggestion<commit_after>/** @file

  A brief file description

  @section license License

  Licensed to the Apache Software Foundation (ASF) under one
  or more contributor license agreements.  See the NOTICE file
  distributed with this work for additional information
  regarding copyright ownership.  The ASF licenses this file
  to you under the Apache License, Version 2.0 (the
  "License"); you may not use this file except in compliance
  with the License.  You may obtain a copy of the License at

      http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
 */
#include "ink_config.h"
#include "records/I_RecHttp.h"
#include "P_Net.h"
#include "P_SSLNextProtocolSet.h"
#include "P_SSLUtils.h"
#include "InkAPIInternal.h"	// Added to include the ssl_hook definitions

// Defined in SSLInternal.c, should probably make a separate include
// file for this at some point
void SSL_set_rbio(SSLNetVConnection *sslvc, BIO *rbio);

#define SSL_READ_ERROR_NONE	  0
#define SSL_READ_ERROR		  1
#define SSL_READ_READY		  2
#define SSL_READ_COMPLETE	  3
#define SSL_READ_WOULD_BLOCK      4
#define SSL_READ_EOS		  5
#define SSL_HANDSHAKE_WANT_READ   6
#define SSL_HANDSHAKE_WANT_WRITE  7
#define SSL_HANDSHAKE_WANT_ACCEPT 8
#define SSL_HANDSHAKE_WANT_CONNECT 9
#define SSL_WRITE_WOULD_BLOCK     10
#define SSL_WAIT_FOR_HOOK         11

#ifndef UIO_MAXIOV
#define NET_MAX_IOV 16          // UIO_MAXIOV shall be at least 16 1003.1g (5.4.1.1)
#else
#define NET_MAX_IOV UIO_MAXIOV
#endif

ClassAllocator<SSLNetVConnection> sslNetVCAllocator("sslNetVCAllocator");

namespace {
  /// Callback to get two locks.
  /// The lock for this continuation, and for the target continuation.
  class ContWrapper : public Continuation
  {
  public:
    /** Constructor.
        This takes the secondary @a mutex and the @a target continuation
        to invoke, along with the arguments for that invocation.
    */
    ContWrapper(
      ProxyMutex* mutex ///< Mutex for this continuation (primary lock).
      , Continuation* target ///< "Real" continuation we want to call.
      , int eventId = EVENT_IMMEDIATE ///< Event ID for invocation of @a target.
      , void* edata = 0 ///< Data for invocation of @a target.
      )
      : Continuation(mutex)
      , _target(target)
      , _eventId(eventId)
      , _edata(edata)
    {
      SET_HANDLER(&ContWrapper::event_handler);
    }

    /// Required event handler method.
    int event_handler(int, void*)
    {
      EThread* eth = this_ethread();

      MUTEX_TRY_LOCK(lock, _target->mutex, eth);
      if (lock.is_locked()) { // got the target lock, we can proceed.
        _target->handleEvent(_eventId, _edata);
        delete this;
      } else { // can't get both locks, try again.
        eventProcessor.schedule_imm(this, ET_NET);
      }
      return 0;
    }

    /** Convenience static method.

        This lets a client make one call and not have to (accurately)
        copy the invocation logic embedded here. We duplicate it near
        by textually so it is easier to keep in sync.

        This takes the same arguments as the constructor but, if the
        lock can be obtained immediately, does not construct an
        instance but simply calls the @a target.
    */
    static void wrap(
      ProxyMutex* mutex ///< Mutex for this continuation (primary lock).
      , Continuation* target ///< "Real" continuation we want to call.
      , int eventId = EVENT_IMMEDIATE ///< Event ID for invocation of @a target.
      , void* edata = 0 ///< Data for invocation of @a target.
      ) {
      EThread* eth = this_ethread();
      MUTEX_TRY_LOCK(lock, target->mutex, eth);
      if (lock.is_locked()) {
        target->handleEvent(eventId, edata);
      } else {
        eventProcessor.schedule_imm(new ContWrapper(mutex, target, eventId, edata), ET_NET);
      }
    }

  private:
    Continuation* _target; ///< Continuation to invoke.
    int _eventId; ///< with this event
    void* _edata; ///< and this data
  };
}

//
// Private
//

static SSL *
make_ssl_connection(SSL_CTX * ctx, SSLNetVConnection * netvc)
{
  SSL * ssl;

  if (likely(ssl = SSL_new(ctx))) {
    netvc->ssl = ssl;

    // Only set up the bio stuff for the server side
    if (netvc->getSSLClientConnection()) {
      SSL_set_fd(ssl, netvc->get_socket());
    } else {
      netvc->initialize_handshake_buffers();
      BIO *rbio = BIO_new(BIO_s_mem());
      BIO *wbio = BIO_new_fd(netvc->get_socket(), BIO_NOCLOSE);
      BIO_set_mem_eof_return(wbio, -1);
      SSL_set_bio(ssl, rbio, wbio);
    }

    SSL_set_app_data(ssl, netvc);
  }

  return ssl;
}

static void
debug_certificate_name(const char * msg, X509_NAME * name)
{
  BIO * bio;

  if (name == NULL) {
{'fraction_non_alphanumeric': 0.09084719385273807, 'fraction_numerical': 0.007781344227215252, 'mean_word_length': 2.966820987654321, 'pattern_counts': {'":': 0, '<': 27, '<?xml version=': 0, '>': 23, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 2, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4016863', 'n_tokens_mistral': 3318, 'n_tokens_neox': 3185, 'n_words': 1074}