#include "headers.h"

#ifndef NOSSL

/* make an official SSL connection */
void makeSSLconn()
{
   int res;
   int flags = SSL_VERIFY_PEER; /* | SSL_VERIFY_FAIL_IF_NO_PEER_CERT; */

   static int init = 0;

   char *clientpem = PARAMDIR "/client.pem";
   char *serverpem = PARAMDIR "/server.pem";

   if (init == 0) 
   {
      init = 1;
      SSL_load_error_strings();
      SSLeay_add_all_algorithms(), SSLeay_add_ssl_algorithms();
   }

   /* clean up after any previous connections */
   if (sslconn != NULL) SSL_free(sslconn);
   if (sslctx != NULL) SSL_CTX_free(sslctx);

   sslconn = NULL, sslctx = NULL;

   /* create a context */
   sslctx = SSL_CTX_new(SSLv3_client_method());
   if (sslctx == NULL) 
   {
      error("error with SSL_CTX_new(): %s\n\n", strerror(errno));

      ERR_print_errors_fp(stderr), ERR_print_errors_fp(errlogfd1);
      if (debugging == 1) ERR_print_errors_fp(dblogfd1);

      quit(ERROR);
   }

   /* clear all options since they all have to do with bugs */
   SSL_CTX_set_options(sslctx, 0);

   res = SSL_CTX_set_cipher_list(sslctx, "ADH:+DES:+EXP");

   if (res <= 0) 
   {
      error("error with SSL_CTX_set_cipher_list(): %s\n\n", strerror(errno));

      ERR_print_errors_fp(stderr), ERR_print_errors_fp(errlogfd1);
      if (debugging == 1) ERR_print_errors_fp(dblogfd1);

      quit(ERROR);
   }
         
   /* indicate strong verification */
   SSL_CTX_set_verify(sslctx, flags, NULL);

   /* indicate where we can find the server's certificate */
   res = SSL_CTX_load_verify_locations(sslctx, serverpem, PARAMDIR);
   if (res < 0) 
   {
      error("error with SSL_CTX_load_verify_locations(): %s\n\n", 
            strerror(errno));

      ERR_print_errors_fp(stderr), ERR_print_errors_fp(errlogfd1);
      if (debugging == 1) ERR_print_errors_fp(dblogfd1);

      quit(ERROR);
   }
      
   res = SSL_CTX_set_default_verify_paths(sslctx);
   if (res < 0) 
   {
      error("error with SSL_CTX_set_default_verify_paths(): %s\n\n", 
            strerror(errno));

      ERR_print_errors_fp(stderr), ERR_print_errors_fp(errlogfd1);
      if (debugging == 1) ERR_print_errors_fp(dblogfd1);

      quit(ERROR);
   }
      
    
   /* create a connection */
   sslconn = SSL_new(sslctx);
   if (sslconn == NULL) 
   {
      error("error with SSL_new(): %s\n\n", strerror(errno));

      ERR_print_errors_fp(stderr), ERR_print_errors_fp(errlogfd1);
      if (debugging == 1) ERR_print_errors_fp(dblogfd1);

      quit(ERROR);
   }
   
   /* specify where our private key is */
   res = SSL_use_PrivateKey_file(sslconn, clientpem, SSL_FILETYPE_PEM);
   if (res <= 0) 
   {
      error("error with SSL_use_PrivateKey_file(): %s\n\n", strerror(errno));

      ERR_print_errors_fp(stderr), ERR_print_errors_fp(errlogfd1);
      if (debugging == 1) ERR_print_errors_fp(dblogfd1);

      quit(ERROR);
   }
      
   /* specify where our certificate is */
   res = SSL_use_certificate_file(sslconn, clientpem, SSL_FILETYPE_PEM);
   if (res <= 0) 
   {
      error("error with SSL_use_certificate_file(): %s\n\n", strerror(errno));

      ERR_print_errors_fp(stderr), ERR_print_errors_fp(errlogfd1);
      if (debugging == 1) ERR_print_errors_fp(dblogfd1);

      quit(ERROR);
   }
    
   /* communicate which socket we are using */
   res = SSL_set_fd(sslconn, sockfd);
   if (res <= 0) 
   {
      error("error with SSL_set_fd(): %s\n\n", strerror(errno));

      ERR_print_errors_fp(stderr), ERR_print_errors_fp(errlogfd1);
      if (debugging == 1) ERR_print_errors_fp(dblogfd1);

      quit(ERROR);
   }
      
   /* setup to connect next time we send/recv data */
   SSL_set_connect_state(sslconn);
}

#endif /* NOSSL */
