



(49 votes)/* osslserv.cpp by detour@metalshell.com * * A basic threaded OpenSSL server with non-blocking * connection handling. When a connection is made the thread * waits for data to be recieved, then sends an html response * so it can be tested with a browser. The thread closes the * connection and terminates without waiting for more data. The * default keys are 'cert' and 'pkey' included. * * Creating New Keys: * - Private Key * openssl genrsa -out pkey 2048 * - Certificate * openssl req -new -x509 -key pkey -out cert -days 365 * * Compile: * A Makefile is included to compile this example. * * Testing: * https://www.yourhostorip.com:1420/ * * http://www.metalshell.com/ * */ #include <openssl/ssl.h> #include <openssl/err.h> #include <iostream> #include <stdlib.h> #include <stdio.h> #include <time.h> #include "sslserver.h" #define REPLY "<html><body>Metalshell.com OpenSSL Server</body></html>" #define MAX_PACKET_SIZE 1024 // Called when a new connection is made. void *conn_thread(void *ssl) { int fd = SSL_get_fd((SSL *)ssl); if(SSL_accept((SSL *)ssl) == -1) { ERR_print_errors_fp(stderr); } else { char cipdesc[128]; SSL_CIPHER *sslciph = SSL_get_current_cipher((SSL *)ssl); cout << "Encryption Description:\n"; cout << SSL_CIPHER_description(sslciph, cipdesc, sizeof(cipdesc)) << endl; char buff[MAX_PACKET_SIZE]; // Wait for data to be sent. int bytes = SSL_read((SSL *)ssl, buff, sizeof(buff)); buff[bytes] = '\0'; // Show the browser request. cout << "Recieved: \n" << buff << endl; // Send the html reply. SSL_write((SSL *)ssl, REPLY, strlen(REPLY)); } // Tell the client we are closing the connection. SSL_shutdown((SSL *)ssl); // We do not wait for a reply, just clear everything. SSL_free((SSL *)ssl); close(fd); cout << "Connection Closed\n"; cout << "---------------------------------------------\n"; pthread_exit(NULL); } int main() { SSLServer server("cert", "pkey", 1420); // Set the thread function. server.SetPthread_F(conn_thread); while(1) { /* Wait for 10 seconds, and if no one trys * to connect return back. This allows us to do * other things while waiting. */ server.CheckClients(10); } return 0; }
#include "sslserver.h" SSLServer::SSLServer(char *cFile, char *kFile, int port) { PORT = port; CreateCTX(); LoadCerts(cFile, kFile); // Get the server started. BindPort(); } void SSLServer::CheckClients(int wait_t) { struct timeval tv; // Set how long to block. tv.tv_sec = wait_t; tv.tv_usec = 0; FD_ZERO(&fdset); FD_SET(master, &fdset); select(master+1, &fdset, NULL, NULL, (struct timeval *)&tv); // If master is set then someone is trying to connect if(FD_ISSET(master, &fdset)) { SSL *ssl; // Open up new connection struct sockaddr_in addr; int len = sizeof(addr); int client = accept(master, (struct sockaddr *)&addr, (socklen_t *)&len); #ifdef DEBUG struct in_addr ip_address; memcpy(&ip_address, &addr.sin_addr.s_addr, 4); cout << "\n\n---------------------------------------------\n"; cout << "Connection from: " << inet_ntoa(ip_address) << " (" << ntohs(addr.sin_port) << ")\n"; #endif /* DEBUG */ if(client == -1) perror("accept"); ssl = SSL_new(ctx); SSL_set_fd(ssl, client); #ifdef DEBUG cout << "Creating Thread\n"; #endif /* DEBUG */ pthread_t thread; if(pthread_create(&thread, NULL, pthr_f, (void *)ssl) != 0) { fprintf(stderr, "pthread_create() has failed.\n"); exit(1); } } } void SSLServer::BindPort(void) { struct sockaddr_in addr; master = socket(PF_INET, SOCK_STREAM, 0); memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_port = htons(PORT); addr.sin_addr.s_addr = INADDR_ANY; // Open the socket if(bind(master, (struct sockaddr *)&addr, sizeof(addr)) != 0) { perror("bind"); _exit(1); } // Set a limit on connection queue. if(listen(master, 5) != 0) { perror("listen"); _exit(1); } } void SSLServer::CreateCTX(void) { // The method describes which SSL protocol we will be using. SSL_METHOD *method; // Load algorithms and error strings. OpenSSL_add_all_algorithms(); SSL_load_error_strings(); // Compatible with SSLv2, SSLv3 and TLSv1 method = SSLv23_server_method(); // Create new context from method. ctx = SSL_CTX_new(method); if(ctx == NULL) { ERR_print_errors_fp(stderr); _exit(1); } } /* Load the certification files, ie the public and private keys. */ void SSLServer::LoadCerts(char *cFile, char *kFile) { if ( SSL_CTX_use_certificate_chain_file(ctx, cFile) <= 0) { ERR_print_errors_fp(stderr); _exit(1); } if ( SSL_CTX_use_PrivateKey_file(ctx, kFile, SSL_FILETYPE_PEM) <= 0) { ERR_print_errors_fp(stderr); _exit(1); } // Verify that the two keys goto together. if ( !SSL_CTX_check_private_key(ctx) ) { fprintf(stderr, "Private key is invalid.\n"); _exit(1); } }
#include <pthread.h> #include <openssl/ssl.h> #include <openssl/err.h> #include <sys/socket.h> #include <arpa/inet.h> #include <resolv.h> #include <unistd.h> #include <stdio.h> #include <string.h> #include <iostream> #ifndef __SSL_SERVER_H__ #define __SSL_SERVER_H__ using namespace std; typedef void *(*P_ARG)(void *); class SSLServer { // Private data private: SSL_CTX *ctx; int PORT; fd_set fdset; // FD for server int master; // Thread function P_ARG pthr_f; // Private Functions private: // Load algorithms and create context. void CreateCTX(void); // Load certification files. void LoadCerts(char *cFile, char *kFile); // Create and attach socket. void BindPort(void); public: // Set function for pthread to call. void SetPthread_F(P_ARG fp) { pthr_f = fp; } // Constructors SSLServer(char *cFile, char *kFile, int port); /* Check for new connections, block for wait_t amount of seconds, if no connection is made within wait_t function returns. This must be called regularly from within main */ void CheckClients(int wait_t = 0); }; #endif
OBJS = sslserver.o main.o EXECUTABLE = sslserver CC=g++ CFLAGS=-Wall -ggdb -DDEBUG COMPILE=$(CC) $(CFLAGS) -c all: sslserver sslserver: $(OBJS) $(CC) -lpthread -lssl -o $(EXECUTABLE) $(OBJS) main.o: main.cpp $(COMPILE) -o main.o main.cpp sslserver.o: sslserver.cpp $(COMPILE) -o sslserver.o sslserver.cpp clean: -rm $(OBJS) $(EXECUTABLE)
-----BEGIN CERTIFICATE----- MIIDpTCCAo2gAwIBAgIBADANBgkqhkiG9w0BAQQFADBFMQswCQYDVQQGEwJVUzET MBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0cyBQ dHkgTHRkMB4XDTAzMDUyNDE0NTI0MloXDTA2MDUyMzE0NTI0MlowRTELMAkGA1UE BhMCVVMxEzARBgNVBAgTClNvbWUtU3RhdGUxITAfBgNVBAoTGEludGVybmV0IFdp ZGdpdHMgUHR5IEx0ZDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALr7 vaKNMG9FbtEya2+GIX7NGfzEUU/b7Pmt0SaC5bZn/Fo1JNlEPnAtFPqZyW6zcqM5 SrCNCVS0B4H3n2GygssPppa88IkM2FolKhlWjWi2k4b+MGuYWwRGu/UGhEK//ciC S+fNTHS20+6U4XXLuPbEIv7TQk/GNF2rSNxTBtL/cp8rpIk+fIY59FymZx6/Gxrp +5vlrbYZFZMPUUd2JgaAUxOy1schetQhoRzrjlDmX9+fmwqKJYQ+ZLb1aCGZZJuR W/i29CyxQODm1fUBpb1WwEFjXUZb8j2iicLoS9s9nJaUFvd2fImWic/11iYi+ufF cMRjakVKMYXF24+GZd8CAwEAAaOBnzCBnDAdBgNVHQ4EFgQU2Ejnhbxwj0yLEdaW BfSbx+qAj2wwbQYDVR0jBGYwZIAU2Ejnhbxwj0yLEdaWBfSbx+qAj2yhSaRHMEUx CzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRl cm5ldCBXaWRnaXRzIFB0eSBMdGSCAQAwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0B AQQFAAOCAQEAoYBkFbBwSO+Vn56ilNG+mOl5ryHAwtjCgqdl156N52ysUFq+qar2 WNbmD3ieDm+UrNqX4FcLV/CkZQAXWj3YHLyGbMCekLbpctjbfmCVTD3EQ+a7Rw1s uQVyrzbLHggzhBuzQrjKflr42MnfNClQAiiM7kOyuo1pwVgWZ4GXIBOfazizG3Yh If0p+MUKJk7maKgXoiu+NrZIu7jyB4lyqTVGh1fKr1rWrciK5xnC7mxkndGuzcGo XM/ea0cPl79g8PRHAtgqLoqECP184HC4gR+AVLoonva4Yz3mI6BiRI0lrcjQLWEF GmLEzRjFsm/tdyMSzH2eM7zp1ibogbSBiA== -----END CERTIFICATE-----
-----BEGIN RSA PRIVATE KEY----- MIIEpQIBAAKCAQEAuvu9oo0wb0Vu0TJrb4Yhfs0Z/MRRT9vs+a3RJoLltmf8WjUk 2UQ+cC0U+pnJbrNyozlKsI0JVLQHgfefYbKCyw+mlrzwiQzYWiUqGVaNaLaThv4w a5hbBEa79QaEQr/9yIJL581MdLbT7pThdcu49sQi/tNCT8Y0XatI3FMG0v9ynyuk iT58hjn0XKZnHr8bGun7m+WtthkVkw9RR3YmBoBTE7LWxyF61CGhHOuOUOZf35+b CoolhD5ktvVoIZlkm5Fb+Lb0LLFA4ObV9QGlvVbAQWNdRlvyPaKJwuhL2z2clpQW 93Z8iZaJz/XWJiL658VwxGNqRUoxhcXbj4Zl3wIDAQABAoIBAAWTL+pCz2jh5xXx rOZcV29Sai3xJIN/CSfAmPXO/U5c91cxMnIP6NSrY269WxYj340iTinJarfNzlN/ sI7XJbMsOklQRNOxQFoftYuf2wN+PhPOTF9I4Z3VBhGeKh9bXhO2XtEAfAEW2mbI pZg/hLpGysxSPC3ouPL6AmgfSZrM2e6Jqgo1OxZnkxsMYG1iLUdyA01P4IwbnIF1 zTEi+cpqBiaX9QR3Q5bkXIhyscmaLCeqvjiAhLZXqy2fRy+VW48T08JWoPjOh/vW EzFOADYXf3bOEeKw62+iSGvF97J87iiqGn7+aMG3FT4YqZ5luu4D1o++xfPj8om/ Rjte4GECgYEA4Z2GzYmaldfcxV1vfoUQDlSmdpcJ3UM/gMew4fSH22obpM81krih H84KMzCIBT1dTJWygSwsNbivhTclRseV/TJ2vN2OQOCk4jwgXjuKyqMVEv7UFVp0 2Z3KTI9+AOTplSRUUymka0dwLd0B7rhuqIfPWT6cC7pgpJCWR4JR3gkCgYEA1CpP mwLhTsDhkjkwsEvIYTJPvKg1ch77Ck3RYQ01tAaJ0IMZfBMuVYAzzbgVrsTuxgMP tAoHTw9fgk+KU0ksIWR3yxrYnFALN9DJvT4nyYjesF1Y83MAwhVE+REJ77efJV7T IkB4OZgdljn5caPEZMAGQxLWFRaV6HHvYnGtnqcCgYEA3OcIHiclHKIGn5gkmpRe bCml82dfWS2G9+iN4C809jimaHAZ3Fa6LBHpGsXh6H904o+P/7nob5EtCho8fVje GtNWPwYPSqapynlkl99kvZOABuFLdrzivFAqy1uT2/xGWKkBh4u2WPPRepZyVfJv JsQS2SbcUv9hsL+A5PNMhUECgYEAwoCbhB9K0HjxEq1NXoHLDJgkE28duCaAvHyE s/V5QzYvR7G4PlATTRz/4NufPR6bS3po/gOnmaodRAiJZjsRsvc4/0D4Tazv69aD 6/K8ZP0OMh8RufW3PzZiifc95b6vroHVC3SRAzPaA+vYK38YP8jutLTjAGg5O+Sf sd9HbMcCgYEAliEIS+BRsf7Uj6jZj+/n3LIiREbZ0Euhqbfh8ZWnFA6Qs64jMvRs /XJgfK/4jYvVWyMsnPOBRnTvI83PiC12UV4yJP2SbyJFkynqcmQjU9tXJoxfTg8m CayJ0aG8qGd2SWmJob8w8WIC+2k7Pt4Otcgfm0KxgJ3jNQ5bwHQ8Udo= -----END RSA PRIVATE KEY-----