int main(int argc , char *argv[]) { int socket_desc , client_sock , read_size; socklen_t c; struct sockaddr_in server , client; char client_message[0xFFFF]; const char msg[] = "HTTP/1.1 200 OK\r\nContent-length: 31\r\nContent-type: text/plain\r\n\r\nHello world from TLSe (TLS 1.2)"; #ifdef _WIN32 WSADATA wsaData; WSAStartup(MAKEWORD(2, 2), &wsaData); #else signal(SIGPIPE, SIG_IGN); #endif socket_desc = socket(AF_INET , SOCK_STREAM , 0); if (socket_desc == -1) { printf("Could not create socket"); return 0; } server.sin_family = AF_INET; server.sin_addr.s_addr = INADDR_ANY; server.sin_port = htons(2000); int enable = 1; setsockopt(socket_desc, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int)); if( bind(socket_desc,(struct sockaddr *)&server , sizeof(server)) < 0) { perror("bind failed. Error"); return 1; } listen(socket_desc , 3); c = sizeof(struct sockaddr_in); unsigned int size; SSL *server_ctx = SSL_CTX_new(SSLv3_server_method()); if (!server_ctx) { fprintf(stderr, "Error creating server context\n"); return -1; } SSL_CTX_use_certificate_file(server_ctx, "testcert/fullchain.pem", SSL_SERVER_RSA_CERT); SSL_CTX_use_PrivateKey_file(server_ctx, "testcert/privkey.pem", SSL_SERVER_RSA_KEY); if (!SSL_CTX_check_private_key(server_ctx)) { fprintf(stderr, "Private key not loaded\n"); return -2; } while (1) { client_sock = accept(socket_desc, (struct sockaddr *)&client, &c); if (client_sock < 0) { fprintf(stderr, "Accept failed\n"); return -3; } SSL *client = SSL_new(server_ctx); if (!client) { fprintf(stderr, "Error creating SSL client\n"); return -4; } SSL_set_fd(client, client_sock); if (SSL_accept(client)) { fprintf(stderr, "Cipher %s\n", tls_cipher_name(client)); while ((read_size = SSL_read(client, client_message, sizeof(client_message))) >= 0) { fwrite(client_message, read_size, 1, stdout); if (SSL_write(client, msg, strlen(msg)) < 0) fprintf(stderr, "Error in SSL write\n"); break; } } else fprintf(stderr, "Error in handshake\n"); SSL_shutdown(client); #ifdef __WIN32 shutdown(client_sock, SD_BOTH); closesocket(client_sock); #else shutdown(client_sock, SHUT_RDWR); close(client_sock); #endif SSL_free(client); } SSL_CTX_free(server_ctx); return 0; }
int main(int argc , char *argv[]) { int socket_desc , client_sock , read_size; socklen_t c; struct sockaddr_in server , client; char client_message[0xFFFF]; #ifdef _WIN32 WSADATA wsaData; WSAStartup(MAKEWORD(2, 2), &wsaData); #else signal(SIGPIPE, SIG_IGN); #endif socket_desc = socket(AF_INET , SOCK_STREAM , 0); if (socket_desc == -1) { printf("Could not create socket"); return 0; } int port = 2000; if (argc > 1) { port = atoi(argv[1]); if (port <= 0) port = 2000; } server.sin_family = AF_INET; server.sin_addr.s_addr = INADDR_ANY; server.sin_port = htons(port); if( bind(socket_desc,(struct sockaddr *)&server , sizeof(server)) < 0) { perror("bind failed. Error"); return 1; } int enable = 1; setsockopt(socket_desc, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int)); listen(socket_desc , 3); c = sizeof(struct sockaddr_in); unsigned int size; struct TLSContext *server_context = tls_create_context(1, TLS_V12); // load keys load_keys(server_context, "testcert/fullchain.pem", "testcert/privkey.pem"); char source_buf[0xFFFF]; int source_size = read_from_file("tlshelloworld.c", source_buf, 0xFFFF); while (1) { identity_str[0] = 0; client_sock = accept(socket_desc, (struct sockaddr *)&client, &c); if (client_sock < 0) { perror("accept failed"); return 1; } struct TLSContext *context = tls_accept(server_context); // uncomment next line to request client certificate tls_request_client_certificate(context); // make the TLS context serializable (this must be called before negotiation) tls_make_exportable(context, 1); fprintf(stderr, "Client connected\n"); while ((read_size = recv(client_sock, client_message, sizeof(client_message), 0)) > 0) { if (tls_consume_stream(context, client_message, read_size, verify_signature) > 0) break; } send_pending(client_sock, context); if (read_size > 0) { fprintf(stderr, "USED CIPHER: %s\n", tls_cipher_name(context)); int ref_packet_count = 0; int res; while ((read_size = recv(client_sock, client_message, sizeof(client_message) , 0)) > 0) { if (tls_consume_stream(context, client_message, read_size, verify_signature) < 0) { fprintf(stderr, "Error in stream consume\n"); break; } send_pending(client_sock, context); if (tls_established(context) == 1) { unsigned char read_buffer[0xFFFF]; int read_size = tls_read(context, read_buffer, sizeof(read_buffer) - 1); if (read_size > 0) { read_buffer[read_size] = 0; unsigned char export_buffer[0xFFF]; // simulate serialization / deserialization to another process char sni[0xFF]; sni[0] = 0; if (context->sni) snprintf(sni, 0xFF, "%s", context->sni); /* COOL STUFF => */ int size = tls_export_context(context, export_buffer, sizeof(export_buffer), 1); if (size > 0) { /* COOLER STUFF => */ struct TLSContext *imported_context = tls_import_context(export_buffer, size); // This is cool because a context can be sent to an existing process. // It will work both with fork and with already existing worker process. fprintf(stderr, "Imported context (size: %i): %x\n", size, imported_context); if (imported_context) { // destroy old context tls_destroy_context(context); // simulate serialization/deserialization of context context = imported_context; } } // ugly inefficient code ... don't write like me char send_buffer[0xF000]; char send_buffer_with_header[0xF000]; char out_buffer[0xFFF]; int tls_version = 2; switch (context->version) { case TLS_V10: tls_version = 0; break; case TLS_V11: tls_version = 1; break; } snprintf(send_buffer, sizeof(send_buffer), "Hello world from TLS 1.%i (used chipher is: %s), SNI: %s\r\nYour identity is: %s\r\n\r\nCertificate: %s\r\n\r\nBelow is the received header:\r\n%s\r\nAnd the source code for this example: \r\n\r\n%s", tls_version, tls_cipher_name(context), sni, identity_str, tls_certificate_to_string(server_context->certificates[0], out_buffer, sizeof(out_buffer)), read_buffer, source_buf); int content_length = strlen(send_buffer); snprintf(send_buffer_with_header, sizeof(send_buffer), "HTTP/1.1 200 OK\r\nConnection: close\r\nContent-type: text/plain\r\nContent-length: %i\r\n\r\n%s", content_length, send_buffer); tls_write(context, send_buffer_with_header, strlen(send_buffer_with_header)); tls_close_notify(context); send_pending(client_sock, context); break; } } } } #ifdef __WIN32 shutdown(client_sock, SD_BOTH); closesocket(client_sock); #else shutdown(client_sock, SHUT_RDWR); close(client_sock); #endif tls_destroy_context(context); } tls_destroy_context(server_context); return 0; }