/*
 * Copyright (c) 2002 - 2003
 * NetGroup, Politecnico di Torino (Italy)
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution.
 * 3. Neither the name of the Politecnico di Torino nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#ifdef HAVE_OPENSSL
#include <stdlib.h>

#include "portability.h"

#include "sslutils.h"

static const char *ssl_keyfile = "";   //!< file containing the private key in PEM format
static const char *ssl_certfile = "";  //!< file containing the server's certificate in PEM format
static const char *ssl_rootfile = "";  //!< file containing the list of CAs trusted by the client
// TODO: a way to set ssl_rootfile from the command line, or an envvar?

// TODO: lock?
static SSL_CTX *ctx;

void ssl_set_certfile(const char *certfile)
{
	ssl_certfile = certfile;
}

void ssl_set_keyfile(const char *keyfile)
{
	ssl_keyfile = keyfile;
}

int ssl_init_once(int is_server, int enable_compression, char *errbuf, size_t errbuflen)
{
	static int inited = 0;
	if (inited) return 0;

	SSL_library_init();
	SSL_load_error_strings();
	OpenSSL_add_ssl_algorithms();
	if (enable_compression)
		SSL_COMP_get_compression_methods();

	SSL_METHOD const *meth =
	    is_server ? SSLv23_server_method() : SSLv23_client_method();
	ctx = SSL_CTX_new(meth);
	if (! ctx)
	{
		snprintf(errbuf, errbuflen, "Cannot get a new SSL context: %s", ERR_error_string(ERR_get_error(), NULL));
		goto die;
	}

	SSL_CTX_set_mode(ctx, SSL_MODE_AUTO_RETRY);

	if (is_server)
	{
		char const *certfile = ssl_certfile[0] ? ssl_certfile : "cert.pem";
		if (1 != SSL_CTX_use_certificate_file(ctx, certfile, SSL_FILETYPE_PEM))
		{
			snprintf(errbuf, errbuflen, "Cannot read certificate file %s: %s", certfile, ERR_error_string(ERR_get_error(), NULL));
			goto die;
		}

		char const *keyfile = ssl_keyfile[0] ? ssl_keyfile : "key.pem";
		if (1 != SSL_CTX_use_PrivateKey_file(ctx, keyfile, SSL_FILETYPE_PEM))
		{
			snprintf(errbuf, errbuflen, "Cannot read private key file %s: %s", keyfile, ERR_error_string(ERR_get_error(), NULL));
			goto die;
		}
	}
	else
	{
		if (ssl_rootfile[0])
		{
			if (! SSL_CTX_load_verify_locations(ctx, ssl_rootfile, 0))
			{
				snprintf(errbuf, errbuflen, "Cannot read CA list from %s", ssl_rootfile);
				goto die;
			}
		}
		else
		{
			SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, NULL);
		}
	}

#if 0
	if (! RAND_load_file(RANDOM, 1024*1024))
	{
		snprintf(errbuf, errbuflen, "Cannot init random");
		goto die;
	}

	if (is_server)
	{
		SSL_CTX_set_session_id_context(ctx, (void *)&s_server_session_id_context, sizeof(s_server_session_id_context));
	}
#endif

	inited = 1;
	return 0;

die:
	return -1;
}

SSL *ssl_promotion(int is_server, SOCKET s, char *errbuf, size_t errbuflen)
{
	if (ssl_init_once(is_server, 1, errbuf, errbuflen) < 0) {
		return NULL;
	}

	SSL *ssl = SSL_new(ctx); // TODO: also a DTLS context
	SSL_set_fd(ssl, (int)s);

	if (is_server) {
		if (SSL_accept(ssl) <= 0) {
			snprintf(errbuf, errbuflen, "SSL_accept(): %s",
					ERR_error_string(ERR_get_error(), NULL));
			return NULL;
		}
	} else {
		if (SSL_connect(ssl) <= 0) {
			snprintf(errbuf, errbuflen, "SSL_connect(): %s",
					ERR_error_string(ERR_get_error(), NULL));
			return NULL;
		}
	}

	return ssl;
}

// Finish using an SSL handle; shut down the connection and free the
// handle.
void ssl_finish(SSL *ssl)
{
	//
	// We won't be using this again, so we can just send the
	// shutdown alert and free up the handle, and have our
	// caller close the socket.
	//
	// XXX - presumably, if the connection is shut down on
	// our side, either our peer won't have a problem sending
	// their shutdown alert or will not treat such a problem
	// as an error.  If this causes errors to be reported,
	// fix that as appropriate.
	//
	SSL_shutdown(ssl);
	SSL_free(ssl);
}

// Same return value as sock_send:
// 0 on OK, -1 on error but closed connection (-2).
int ssl_send(SSL *ssl, char const *buffer, int size, char *errbuf, size_t errbuflen)
{
	int status = SSL_write(ssl, buffer, size);
	if (status > 0)
	{
		// "SSL_write() will only return with success, when the complete contents (...) has been written."
		return 0;
	}
	else
	{
		int ssl_err = SSL_get_error(ssl, status); // TODO: does it pop the error?
		if (ssl_err == SSL_ERROR_ZERO_RETURN)
		{
			return -2;
		}
		else if (ssl_err == SSL_ERROR_SYSCALL)
		{
#ifndef _WIN32
			if (errno == ECONNRESET || errno == EPIPE) return -2;
#endif
		}
		snprintf(errbuf, errbuflen, "SSL_write(): %s",
		    ERR_error_string(ERR_get_error(), NULL));
		return -1;
	}
}

// Returns the number of bytes read, or -1 on syserror, or -2 on SSL error.
int ssl_recv(SSL *ssl, char *buffer, int size, char *errbuf, size_t errbuflen)
{
	int status = SSL_read(ssl, buffer, size);
	if (status <= 0)
	{
		int ssl_err = SSL_get_error(ssl, status);
		if (ssl_err == SSL_ERROR_ZERO_RETURN)
		{
			return 0;
		}
		else if (ssl_err == SSL_ERROR_SYSCALL)
		{
			return -1;
		}
		else
		{
			// Should not happen
			snprintf(errbuf, errbuflen, "SSL_read(): %s",
			    ERR_error_string(ERR_get_error(), NULL));
			return -2;
		}
	}
	else
	{
		return status;
	}
}

#endif // HAVE_OPENSSL
