/*
 * This code is part of Screws project.
 * Copylefted by pancake@phreaker.net at 2003
 */

#include "Ssl.h"
#include "Error.h"

#if USESSL
bool
SslLoadCertificates(ctx,cert,key)
	SSL_CTX *ctx;
	const char *cert, *key;
{
	// check if files exist!! //
	if (access(cert,R_OK) || access(key,R_OK))
	{
		printf("[E] Cannot find cert/key file. Please check config file.\n");
		return false;
	}

	/* PEM  = binary *
	 * ASN1 = ascii  */
	if ( SSL_CTX_use_certificate_file(ctx,cert,SSL_FILETYPE_PEM) != 1 )
	{
		printf("Error loading public certificate in '%s'.\n",cert);
		if(Svr.v>=V_SSL)
		ERR_print_errors_fp(stderr);
		return false;
	}
	if ( SSL_CTX_use_PrivateKey_file(ctx,key,SSL_FILETYPE_PEM) != 1 )
	{
		printf("Error loading private key in '%s'.\n",key);
		if (Svr.v>=V_SSL)
		ERR_print_errors_fp(stderr);
		return false;
	}
	if ( SSL_CTX_check_private_key( ctx ) != 1)
	{
		printf("Private key does not match the public certificate.\n");
		if (Svr.v>=V_SSL)
		ERR_print_errors_fp(stderr);
		return false;
	}
	return true;
}

void
SslShowCertificates( ssl )
	SSL *ssl;
{
	X509 *cert;
	char *line;

	cert = SSL_get_peer_certificate(ssl);
	if (cert)
	{
		printf("[i] SSL certificates:\n");
		line = X509_NAME_oneline(X509_get_subject_name(cert), 0, 0);
	        printf("    Subject: %s\n", line);
		free(line);
		line = X509_NAME_oneline(X509_get_issuer_name(cert), 0, 0);
		printf("    Issuer: %s\n", line);
		free(line);
		SSL_version(ssl);
		X509_free(cert);
	}
}

bool
SslInit(n,ctx)
	int n;
	SSL_CTX **ctx;
{
	SSL_METHOD *sm;

	/* Load minimum data */
	OpenSSL_add_all_ciphers();
	OpenSSL_add_all_digests();
	//OpenSSL_add_all_algorithms();
	SSL_load_error_strings();
	
	switch(Svr.enc)
	{
	case ENC_SSL3:
		sm=SSLv3_server_method();
		break;
	case ENC_SSL23:
		sm=SSLv23_server_method();
		break;
	case ENC_TLS:
		sm=TLSv1_server_method();
		break;
	}
	if ( !sm )
	{
		printf("Cannot initialize Server method for SSL support.\n");
		return false;
	}

	/* Create new Context */
	*ctx = SSL_CTX_new( sm );
	if (!*ctx)
	{
		printf("Cannot create new SSL context.\n");
		return false;
	}
	ERR_print_errors_fp(stderr);
	
	/* Load Certificates */
	if (!	SslLoadCertificates(
				*ctx,
				Svr.Lis[n].S[_SSLCRT],
				Svr.Lis[n].S[_SSLKEY]) )
	{
		printf("Disabling SSL on this thread.\n");
		Svr.Lis[n].usessl=false;
		return false;
	}
	return true;
}

#endif

bool screws_ssl_init(int n)
{
#if USESSL
   if (Svr.Lis[n].usessl)
   {  
      if (Svr.io==IO_DIRECT)
      {
      exit( Error(Svr.Lis[n].name,ERROR_SSLIO) );
      }
   Svr.Lis[n].usessl = SslInit(n, &Svr.Lis[n].ctx);
   }
#endif
	return true;
}
