/**
* dhserver.cpp
* josuegomes.com
*/
#include <iostream>
#ifdef WIN32
#include <windows.h>
#endif
#include <openssl/ssl.h>
#include <openssl/err.h>
using std::exit;
#define int_error(msg) handle_error(__FILE__, __LINE__, msg)
void handle_error(const char* file, int lineno, const char* msg)
{
std::cerr << "\n** " << file << ":" << lineno << " " << msg << "\n";
ERR_print_errors_fp(stderr);
exit(-1);
}
void init_OpenSSL()
{
std::cout << "Initializng OpenSSL library ... ";
if (!SSL_library_init())
int_error("OpenSSL initialization failed");
std::cout << "done\n";
SSL_load_error_strings();
}
DH* setup_dh()
{
DH* dh = DH_new();
if (!dh)
int_error("DH_new failed");
std::cout << "Generating DH parameters ... ";
if (!DH_generate_parameters_ex(dh, 2, DH_GENERATOR_2, 0))
int_error("DH_generate_parameters_ex failed");
std::cout << "done\n";
std::cout << "Checking DH parameters ... ";
int codes = 0;
if (!DH_check(dh, &codes))
int_error("DH_check failed");
std::cout << "done\n";
std::cout << "Generating DH keys ... ";
if (!DH_generate_key(dh))
int_error("DH_generate_key failed");
std::cout << "done\n";
return dh;
}
SSL_CTX* setup_ctx()
{
SSL_CTX* ctx;
std::cout << "Creating context ... ";
ctx = SSL_CTX_new(TLSv1_server_method());
if (!ctx)
int_error("SSL_CTX_new failed");
std::cout << "done\n";
DH* dh = setup_dh();
std::cout << "Setting DH parameters ... ";
SSL_CTX_set_tmp_dh(ctx, dh);
std::cout << "done\n";
std::cout << "Setting cipher list ... ";
if (SSL_CTX_set_cipher_list(ctx, "ADH-AES256-SHA") != 1)
int_error("Error setting cipher list (no valid ciphers)");
std::cout << "done\n";
return ctx;
}
int main()
{
init_OpenSSL();
BIO *acc, *client;
SSL* ssl;
SSL_CTX* ctx;
ctx = setup_ctx();
std::cout << "Creating server socket ... ";
acc = BIO_new_accept("13011");
if (!acc)
int_error("Error creating server socket");
std::cout << "done\n";
std::cout << "Binding server socket ... ";
if (BIO_do_accept(acc) <= 0)
int_error("Error binding server socket");
std::cout << "done\n";
while (true) {
std::cout << "Accepting connections ...\n";
if (BIO_do_accept(acc) <= 0)
int_error("Error accepting connection");
client = BIO_pop(acc);
std::cout << "Creating context ... ";
if (!(ssl = SSL_new(ctx)))
int_error("Error creating SSL context");
std::cout << "done\n";
SSL_set_bio(ssl, client, client);
if (SSL_accept(ssl) <= 0)
int_error("Error accepting SSL connection");
std::cout << "SSL connection opened: " << SSL_get_cipher(ssl) << " " <<
SSL_get_cipher_version(ssl) << " (" << SSL_get_cipher_bits(ssl, 0) << " bits)\n";
char buff[256] = {0};
int r = SSL_read(ssl, buff, sizeof buff);
if (r > 0) {
std::cout << "Server received: <" << buff << ">\n";
char answer[256] = {0};
r = sprintf(answer, "I (the server) received this: <%s>", buff);
SSL_write(ssl, answer, r);
}
SSL_shutdown(ssl);
SSL_free(ssl);
std::cout << "SSL connection finished\n";
}
SSL_CTX_free(ctx);
BIO_free(acc);
std::cout << "Server closed\n";
}