#include "h9.h"

SSL_CTX *setup_ssl_context(void)
{
  SSL_CTX *context = NULL;

  /* Create a SSL context */
  if ((context = SSL_CTX_new(SSLv23_method())) == NULL) {
    ERR_print_errors_fp(stderr);
  }
  SSL_CTX_set_options(context, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1);

  /* Load the certificate (public key) into the SSL context: */
  if (SSL_CTX_use_certificate_file(context, SERVER_CERT, SSL_FILETYPE_PEM) <= 0) {
    ERR_print_errors_fp(stderr);
    exit(1);
  }
  /* Load the server private-key into the SSL context: */
  if (SSL_CTX_use_PrivateKey_file(context, SERVER_KEY, SSL_FILETYPE_PEM) <= 0) {
    ERR_print_errors_fp(stderr);
    exit(1);
  }
  /* Check that the public / private keys go together */
  if (!SSL_CTX_check_private_key(context)) {
    fprintf(stderr,"Private key does not match public key\n");
    exit(1);
  }
  /* Load trusted CA. (NULL for a self signed cert) */
  if (!SSL_CTX_load_verify_locations(context,CA_CERT,NULL)) { 
    ERR_print_errors_fp(stderr);
    exit(1);
  }
  /* Set to require peer (client) certificate verification */
  SSL_CTX_set_verify(context, SSL_VERIFY_NONE, NULL); // verify_callback);
  /* Set the verification depth to 1 */
  SSL_CTX_set_verify_depth(context,1);

  return context;
}

ssl_conn *ssl_accept(int sock, SSL_CTX *context)
{
  ssl_conn *c;
  int conn;
  
  if ((conn = accept(sock, NULL, NULL)) < 0) {
    perror("accept");
    return NULL;
  }

  c = malloc(sizeof(ssl_conn));
  memset(c, 0, sizeof(ssl_conn));
  c->sock = conn;
  if ((c->handle = SSL_new(context)) == NULL) {
    ERR_print_errors_fp(stderr);
    return NULL;
  }
  if (!SSL_set_fd(c->handle, conn)) {
    ERR_print_errors_fp(stderr);
    return NULL;
  }
  if (SSL_accept(c->handle) != 1) {
    ERR_print_errors_fp(stderr);
  }
  return c;
}

void ssl_disconnect(ssl_conn *c)
{
  if (c->handle) {
    SSL_shutdown(c->handle);
    SSL_free(c->handle);
  }
  if (c->sock) close(c->sock);
  free(c);  
}
