view seobeo/s_ssl.c @ 177:24fe8ff94056

Fixed few issues with current setup.
author MrJuneJune <me@mrjunejune.com>
date Wed, 21 Jan 2026 19:40:48 -0800
parents 70401cf61e97
children
line wrap: on
line source

#include "seobeo/seobeo.h"

#ifndef SEOBEO_NO_SSL

void Seobeo_Web_SSL_Init()
{
  SSL_load_error_strings();
  OpenSSL_add_ssl_algorithms();
}

void Seobeo_Web_SSL_Cleanup(void)
{
  EVP_cleanup(); // I don't think these are needed...
}

int Seobeo_SSL_Setup_Client(Seobeo_Handle *p_handle, const char *host, int socket_fd)
{
  if (!p_handle) return -1;

  Seobeo_Log(SEOBEO_INFO, "Using SSL/TLS encryption\n");
  Seobeo_Web_SSL_Init();
  p_handle->ssl_ctx = SSL_CTX_new(TLS_client_method());
  if (!p_handle->ssl_ctx)
  {
    Seobeo_Log(SEOBEO_ERROR, "SSL_CTX_new failed\n");
    ERR_print_errors_fp(stderr);
    return -1;
  }

  SSL_CTX_set_default_verify_paths(p_handle->ssl_ctx);

  p_handle->ssl = SSL_new(p_handle->ssl_ctx);
  if (!p_handle->ssl)
  {
    Seobeo_Log(SEOBEO_ERROR, "SSL_new failed\n");
    ERR_print_errors_fp(stderr);
    SSL_CTX_free(p_handle->ssl_ctx);
    p_handle->ssl_ctx = NULL;
    return -1;
  }

  SSL_set_fd(p_handle->ssl, socket_fd);
  SSL_set_tlsext_host_name(p_handle->ssl, host);

  // Blocking for TLS handshake
  fcntl(socket_fd, F_SETFL, 0);

  if (SSL_connect(p_handle->ssl) != 1)
  {
    Seobeo_Log(SEOBEO_ERROR, "SSL_connect failed\n");
    ERR_print_errors_fp(stderr);
    SSL_free(p_handle->ssl);
    SSL_CTX_free(p_handle->ssl_ctx);
    p_handle->ssl = NULL;
    p_handle->ssl_ctx = NULL;
    return -1;
  }

  return 0;
}

void Seobeo_SSL_Cleanup(Seobeo_Handle *p_handle)
{
  if (!p_handle) return;

  if (p_handle->ssl)
  {
    SSL_shutdown(p_handle->ssl);
    SSL_free(p_handle->ssl);
    p_handle->ssl = NULL;
  }

  if (p_handle->ssl_ctx)
  {
    SSL_CTX_free(p_handle->ssl_ctx);
    p_handle->ssl_ctx = NULL;
  }
}

int32 Seobeo_SSL_Write(Seobeo_Handle *p_handle, const uint8 *data, uint32 length)
{
  if (!p_handle || !p_handle->ssl) return -1;

  int n = SSL_write(p_handle->ssl, data, length);
  if (n < 0)
  {
    int err = SSL_get_error(p_handle->ssl, n);
    if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE)
    {
      // caller must wait for socket readiness and retry
      return 0;
    }
    ERR_print_errors_fp(stderr);
    return -1;
  }
  return n;
}

int32 Seobeo_SSL_Read(Seobeo_Handle *p_handle, uint8 *buffer, uint32 length)
{
  if (!p_handle || !p_handle->ssl) return -1;

  int32 read_size = (int32)SSL_read(p_handle->ssl, buffer, length);
  if (read_size <= 0)
  {
    int err = SSL_get_error(p_handle->ssl, read_size);
    switch (err)
    {
      case SSL_ERROR_WANT_READ:
      case SSL_ERROR_WANT_WRITE:
        return 0;
      case SSL_ERROR_ZERO_RETURN:
      default:
        // TODO: Handle these errors
        return -2;
    }
  }
  return read_size;
}

#else

// Stub implementations when SSL is disabled
void Seobeo_Web_SSL_Init() {}
void Seobeo_Web_SSL_Cleanup(void) {}
int Seobeo_SSL_Setup_Client(Seobeo_Handle *p_handle, const char *host, int socket_fd)
{
  (void)p_handle; (void)host; (void)socket_fd;
  Seobeo_Log(SEOBEO_WARNING, "SSL support not compiled in\n");
  return -1;
}
void Seobeo_SSL_Cleanup(Seobeo_Handle *p_handle) { (void)p_handle; }
int32 Seobeo_SSL_Write(Seobeo_Handle *p_handle, const uint8 *data, uint32 length)
{
  (void)p_handle; (void)data; (void)length;
  return -1;
}
int32 Seobeo_SSL_Read(Seobeo_Handle *p_handle, uint8 *buffer, uint32 length)
{
  (void)p_handle; (void)buffer; (void)length;
  return -1;
}

#endif