summaryrefslogtreecommitdiffstats
path: root/demos
diff options
context:
space:
mode:
authorbobwirka <bobwirka@yahoo.com>2021-12-12 14:53:13 -0500
committerMatt Caswell <matt@openssl.org>2022-04-12 15:12:57 +0100
commit801c638c50406c93d683c1ab8bd1d430cff4b6d0 (patch)
treec380a5ff188debc8bb7b89d3ebb8a67246bc3e9d /demos
parentcb629550cdab518c925e9b402e11b86497a03845 (diff)
Added Simple SSL Echo Client/Server to demos.
Reviewed-by: Paul Dale <pauli@openssl.org> Reviewed-by: Matt Caswell <matt@openssl.org> (Merged from https://github.com/openssl/openssl/pull/17260)
Diffstat (limited to 'demos')
-rw-r--r--demos/README.txt3
-rw-r--r--demos/sslecho/A-SSL-Docs.txt20
-rw-r--r--demos/sslecho/README.md26
-rw-r--r--demos/sslecho/cert.pem32
-rw-r--r--demos/sslecho/key.pem52
-rw-r--r--demos/sslecho/main.c340
-rw-r--r--demos/sslecho/makefile12
7 files changed, 485 insertions, 0 deletions
diff --git a/demos/README.txt b/demos/README.txt
index 650529572c..a4b8be0fe3 100644
--- a/demos/README.txt
+++ b/demos/README.txt
@@ -50,3 +50,6 @@ signature:
EVP_Signature_demo.c Compute and verify a signature from multiple buffers
rsa_pss_direct.c Compute and verify an RSA-PSS signature from a hash
rsa_pss_hash.c Compute and verify an RSA-PSS signature over a buffer
+
+sslecho:
+main.c Simple SSL echo client/server.
diff --git a/demos/sslecho/A-SSL-Docs.txt b/demos/sslecho/A-SSL-Docs.txt
new file mode 100644
index 0000000000..865960e4bd
--- /dev/null
+++ b/demos/sslecho/A-SSL-Docs.txt
@@ -0,0 +1,20 @@
+Useful Links:
+
+OpenSSL API Documentation: https://www.openssl.org/docs
+
+Github: https://github.com/openssl/openssl
+
+OpenSSL Wiki: https://wiki.openssl.org/index.php/Main_Page
+
+Original Simple Server: https://wiki.openssl.org/index.php/Simple_TLS_Server
+
+---------------------------------------------------------------
+
+Generate self signed cert and key 'pem' files (good for 10 years):
+
+openssl req -newkey rsa:4096 -x509 -sha256 -days 3650 -nodes -out cert.pem -keyout key.pem
+
+You can just hit carriage returns to accept the default values, except for "Common Name"; you
+should enter 'localhost', or an actual hostname.
+
+The same keys can be used for both communicating instances; same or different machines.
diff --git a/demos/sslecho/README.md b/demos/sslecho/README.md
new file mode 100644
index 0000000000..58f7ca0724
--- /dev/null
+++ b/demos/sslecho/README.md
@@ -0,0 +1,26 @@
+OpenSSL Simple Echo Client/Server
+=================================
+
+This project implements a simple echo client/server.
+
+It is a console application, with command line parameters determining the mode
+of operation (client or server). Start it with no parameters to see usage.
+
+The server code was adapted from the Simple TLS Server on the OpenSSL Wiki.
+The server code was modified to perform the echo function, and client code
+was added to open a connection with the server and to send keyboard input
+to the server.
+
+The new client code illustrates that:
+
+- Connection to the SSL server starts as a standard TCP 'connect'.
+- Once connected with TCP, the client 'upgrades' to SSL using
+ SSL_connect().
+- When the SSL connection completes, data is sent and received using
+ SSL_write() and SSL_read().
+- Pretty simple.
+
+The cert.pem and key.pem files included are self signed certificates with the
+"Common Name" of 'localhost'.
+
+Best to create the 'pem' files using an actual hostname.
diff --git a/demos/sslecho/cert.pem b/demos/sslecho/cert.pem
new file mode 100644
index 0000000000..834d46285f
--- /dev/null
+++ b/demos/sslecho/cert.pem
@@ -0,0 +1,32 @@
+-----BEGIN CERTIFICATE-----
+MIIFkzCCA3ugAwIBAgIUQJ8FQFwuVg1UlnIBam0+liL0RSQwDQYJKoZIhvcNAQEL
+BQAwWTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoM
+GEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDESMBAGA1UEAwwJbG9jYWxob3N0MB4X
+DTIyMDIwMjE0MzgzNloXDTMyMDEzMTE0MzgzNlowWTELMAkGA1UEBhMCQVUxEzAR
+BgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5
+IEx0ZDESMBAGA1UEAwwJbG9jYWxob3N0MIICIjANBgkqhkiG9w0BAQEFAAOCAg8A
+MIICCgKCAgEAyPZfTbR9lVvpHxIGRzpYb1gYFjPZ7yTXYZVKEqQLVxw/O2L32ufa
+lODiYJr/pKu9++9T+JrmRnonYlyl0uFta3w4rMY9PzHsT7jIZJByoFdraNz1SnxF
+1UaHjzF9fjIA0/n/ZGVJDZCCYulpcVkpW14oNG4tTW5IefYUH3GxmPZ5godhWEla
+6OXl3+9xkGd5yXq1O4VZbsekcVcZlznuq7blmvs3UrjrEZ5xgmCd8kNzy/E9APKY
+SSGx87/U9yyiz5GAphgSNTqAfEWqpzouMv+hUm/J5NuZCXbOPYbE7zfDDauspYiY
+/wdGty9ZvDy5g+fFz8sZig1OWuHqvU8QGoIfVRCxjhX3+p0/KshGDBWjLHek+8Wh
+IZHmuf1LgT+gOzN3dxxVEcphSiJX0eZ/OhBelowrdabEycm2WAk3qs/tUDMbWh6V
+VSH22ODLX/cBrSAY2sk2EU8Mz5Mbm6gFTcJhqOBgVn5g8/3QCAhFG3xq/2LKZ+za
+itAKbaeQqyAw5G/+oc7mKCjUqSKE92n6FKZRsJrB+vfy3AQYyqJevHcIf2nbBimX
+vb4/rDed/gvSOVGIXIUiUlFHgg8DoVZqMrfJ+y/xwr+Ya+AX8n6J8EB2It3W4EEf
+nmosupBcZPb6U2VrtpEe/199nPj2ZXQHGLLQfw8lYjvZDghCFiP0o8cCAwEAAaNT
+MFEwHQYDVR0OBBYEFDClIPCiAkevl1qh188Ycjz5IZ/DMB8GA1UdIwQYMBaAFDCl
+IPCiAkevl1qh188Ycjz5IZ/DMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEL
+BQADggIBAGQm27D74xUm1X99GbDQpgJenUIu+Bszk8qXCsPfyyQZy4H6+70uXlkC
+ASf/keQjrPzrco3rBelbtlCGqqWhsCznVplrjNIntBAkLD0fU3z92SjsMvHEcBDa
+Nu6aXExN9gv85EBJHNnj16hqjo8Mk+ydNQ8BtcnZa4zi7GdVh29KbPuEzeoyRnXP
+xh5yHUj5Bs6hEUbirhm1WLEK8bvfWykfEJiGOQO8MHAeYK1uPFXDmswgTwJFzZyA
+6LSXYbmGOnCM8yAmVXHMnXXCKd+DQFyQ0KrXDiixyTinYFtrONBkNNt/7SnCjJt5
+H3LRTNuoZvvGmaS7GxbIMemBjLdrigKicVZunEPGFRTEL7K+spmSMnpAiITStxjR
+70wHEe3M9IUbJximKaxvMhXhP0VSPJGOzgG304A2MqMS7UPBDzD/pz5c7gn7ILfM
+LcxzStnQcbTqqmdpNVlMv31YpOk5nel5RY3UmwKbQkix6UAo/CJmC1Q3yLU8uG5O
+6j7vS8t0wOYcVTAA845JU8C7V5yy6UeCB9F2oGDgVwCe6U8bzTIoCDnkzIKO7LlS
+734KP+fNK9LatNzpPQWW+1SK4XEZBNLOMePwu560GLVzPgr9ji0z83E+0yAcWrAO
+4gKT+/h3Ep1Ut73daskFAvNJFFt/5Rm+xZECHrxRkXqW1AN/2eXX
+-----END CERTIFICATE-----
diff --git a/demos/sslecho/key.pem b/demos/sslecho/key.pem
new file mode 100644
index 0000000000..75b86c3a38
--- /dev/null
+++ b/demos/sslecho/key.pem
@@ -0,0 +1,52 @@
+-----BEGIN PRIVATE KEY-----
+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
+DDFU5HazFnn1G0/rg2SnKHTRLV2E9g==
+-----END PRIVATE KEY-----
diff --git a/demos/sslecho/main.c b/demos/sslecho/main.c
new file mode 100644
index 0000000000..c6f087c56f
--- /dev/null
+++ b/demos/sslecho/main.c
@@ -0,0 +1,340 @@
+/*
+ * Copyright 2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <openssl/ssl.h>
+#include <openssl/err.h>
+
+static const int server_port = 4433;
+
+typedef unsigned char bool;
+#define true 1
+#define false 0
+
+/*
+ * This flag won't be useful until both accept/read (TCP & SSL) methods
+ * can be called with a timeout. TBD.
+ */
+static volatile bool server_running = true;
+
+int create_socket(bool isServer)
+{
+ int s;
+ int optval = 1;
+ struct sockaddr_in addr;
+
+ s = socket(AF_INET, SOCK_STREAM, 0);
+ if (s < 0) {
+ perror("Unable to create socket");
+ exit(EXIT_FAILURE);
+ }
+
+ if (isServer) {
+ addr.sin_family = AF_INET;
+ addr.sin_port = htons(server_port);
+ addr.sin_addr.s_addr = INADDR_ANY;
+
+ /* Reuse the address; good for quick restarts */
+ if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval))
+ < 0) {
+ perror("setsockopt(SO_REUSEADDR) failed");
+ exit(EXIT_FAILURE);
+ }
+
+ if (bind(s, (struct sockaddr*) &addr, sizeof(addr)) < 0) {
+ perror("Unable to bind");
+ exit(EXIT_FAILURE);
+ }
+
+ if (listen(s, 1) < 0) {
+ perror("Unable to listen");
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ return s;
+}
+
+SSL_CTX* create_context(bool isServer)
+{
+ const SSL_METHOD *method;
+ SSL_CTX *ctx;
+
+ if (isServer)
+ method = TLS_server_method();
+ else
+ method = TLS_client_method();
+
+ ctx = SSL_CTX_new(method);
+ if (ctx == NULL) {
+ perror("Unable to create SSL context");
+ ERR_print_errors_fp(stderr);
+ exit(EXIT_FAILURE);
+ }
+
+ return ctx;
+}
+
+void configure_server_context(SSL_CTX *ctx)
+{
+ /* Set the key and cert */
+ if (SSL_CTX_use_certificate_chain_file(ctx, "cert.pem") <= 0) {
+ ERR_print_errors_fp(stderr);
+ exit(EXIT_FAILURE);
+ }
+
+ if (SSL_CTX_use_PrivateKey_file(ctx, "key.pem", SSL_FILETYPE_PEM) <= 0) {
+ ERR_print_errors_fp(stderr);
+ exit(EXIT_FAILURE);
+ }
+}
+
+void configure_client_context(SSL_CTX *ctx)
+{
+ /*
+ * Configure the client to abort the handshake if certificate verification
+ * fails
+ */
+ SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL);
+ /*
+ * In a real application you would probably just use the default system certificate trust store and call:
+ * SSL_CTX_set_default_verify_paths(ctx);
+ * In this demo though we are using a self-signed certificate, so the client must trust it directly.
+ */
+ if (!SSL_CTX_load_verify_locations(ctx, "cert.pem", NULL)) {
+ ERR_print_errors_fp(stderr);
+ exit(EXIT_FAILURE);
+ }
+}
+
+void usage()
+{
+ printf("Usage: sslecho s\n");
+ printf(" --or--\n");
+ printf(" sslecho c ip\n");
+ printf(" c=client, s=server, ip=dotted ip of server\n");
+ exit(1);
+}
+
+int main(int argc, char **argv)
+{
+ bool isServer;
+ int result;
+
+ SSL_CTX *ssl_ctx = NULL;
+ SSL *ssl = NULL;
+
+ int server_skt = -1;
+ int client_skt = -1;
+
+ char txbuf[128];
+ size_t txcap = sizeof(txbuf);
+ int txlen;
+
+ char rxbuf[128];
+ size_t rxcap = sizeof(rxbuf);
+ int rxlen;
+
+ char *rem_server_ip = NULL;
+
+ struct sockaddr_in addr;
+ unsigned int addr_len = sizeof(addr);
+
+ /* Splash */
+ printf("\nsslecho : Simple Echo Client/Server (OpenSSL 3.0.1-dev) : %s : %s\n\n", __DATE__,
+ __TIME__);
+
+ /* Need to know if client or server */
+ if (argc < 2) {
+ usage();
+ /* NOTREACHED */
+ }
+ isServer = (argv[1][0] == 's') ? true : false;
+ /* If client get remote server address (could be 127.0.0.1) */
+ if (!isServer) {
+ if (argc != 3) {
+ usage();
+ /* NOTREACHED */
+ }
+ rem_server_ip = argv[2];
+ }
+
+ /* Create context used by both client and server */
+ ssl_ctx = create_context(isServer);
+
+ /* If server */
+ if (isServer) {
+
+ printf("We are the server on port: %d\n\n", server_port);
+
+ /* Configure server context with appropriate key files */
+ configure_server_context(ssl_ctx);
+
+ /* Create server socket; will bind with server port and listen */
+ server_skt = create_socket(true);
+
+ /*
+ * Loop to accept clients.
+ * Need to implement timeouts on TCP & SSL connect/read functions
+ * before we can catch a CTRL-C and kill the server.
+ */
+ while (server_running) {
+ /* Wait for TCP connection from client */
+ client_skt = accept(server_skt, (struct sockaddr*) &addr,
+ &addr_len);
+ if (client_skt < 0) {
+ perror("Unable to accept");
+ exit(EXIT_FAILURE);
+ }
+
+ printf("Client TCP connection accepted\n");
+
+ /* Create server SSL structure using newly accepted client socket */
+ ssl = SSL_new(ssl_ctx);
+ SSL_set_fd(ssl, client_skt);
+
+ /* Wait for SSL connection from the client */
+ if (SSL_accept(ssl) <= 0) {
+ ERR_print_errors_fp(stderr);
+ server_running = false;
+ } else {
+
+ printf("Client SSL connection accepted\n\n");
+
+ /* Echo loop */
+ while (true) {
+ /* Get message from client; will fail if client closes connection */
+ if ((rxlen = SSL_read(ssl, rxbuf, rxcap)) <= 0) {
+ if (rxlen == 0) {
+ printf("Client closed connection\n");
+ }
+ ERR_print_errors_fp(stderr);
+ break;
+ }
+ /* Insure null terminated input */
+ rxbuf[rxlen] = 0;
+ /* Look for kill switch */
+ if (strcmp(rxbuf, "kill\n") == 0) {
+ /* Terminate...with extreme prejudice */
+ printf("Server received 'kill' command\n");
+ server_running = false;
+ break;
+ }
+ /* Show received message */
+ printf("Received: %s", rxbuf);
+ /* Echo it back */
+ if (SSL_write(ssl, rxbuf, rxlen) <= 0) {
+ ERR_print_errors_fp(stderr);
+ }
+ }
+ }
+ if (server_running) {
+ /* Cleanup for next client */
+ SSL_shutdown(ssl);
+ SSL_free(ssl);
+ close(client_skt);
+ }
+ }
+ printf("Server exiting...\n");
+ }
+ /* Else client */
+ else {
+
+ printf("We are the client\n\n");
+
+ /* Configure client context so we verify the server correctly */
+ configure_client_context(ssl_ctx);
+
+ /* Create "bare" socket */
+ client_skt = create_socket(false);
+ /* Set up connect address */
+ addr.sin_family = AF_INET;
+ inet_pton(AF_INET, rem_server_ip, &addr.sin_addr.s_addr);
+ addr.sin_port = htons(server_port);
+ /* Do TCP connect with server */
+ if (connect(client_skt, (struct sockaddr*) &addr, sizeof(addr)) != 0) {
+ perror("Unable to TCP connect to server");
+ goto exit;
+ } else {
+ printf("TCP connection to server successful\n");
+ }
+
+ /* Create client SSL structure using dedicated client socket */
+ ssl = SSL_new(ssl_ctx);
+ SSL_set_fd(ssl, client_skt);
+ /* Set host name for SNI */
+ SSL_set_tlsext_host_name(ssl, rem_server_ip);
+ /* Configure server hostname check */
+ SSL_set1_host(ssl, rem_server_ip);
+
+ /* Now do SSL connect with server */
+ if (SSL_connect(ssl) == 1) {
+
+ printf("SSL connection to server successful\n\n");
+
+ /* Loop to send input from keyboard */
+ while (true) {
+ /* Get a line of input */
+ txlen = getline(&txbuf, &txcap, stdin);
+ /* Exit loop if just a carriage return */
+ if (txbuf[0] == '\n') {
+ break;
+ }
+
+ /* Send it to the server */
+ if ((result = SSL_write(ssl, txbuf, txlen)) <= 0) {
+ printf("Server closed connection\n");
+ ERR_print_errors_fp(stderr);
+ break;
+ }
+
+ /* Wait for the echo */
+ rxlen = SSL_read(ssl, rxbuf, rxcap);
+ if (rxlen <= 0) {
+ printf("Server closed connection\n");
+ ERR_print_errors_fp(stderr);
+ break;
+ } else {
+ /* Show it */
+ rxbuf[rxlen] = 0;
+ printf("Received: %s", rxbuf);
+ }
+ }
+ printf("Client exiting...\n");
+ } else {
+
+ printf("SSL connection to server failed\n\n");
+
+ ERR_print_errors_fp(stderr);
+ }
+ }
+ exit:
+ /* Close up */
+ if (ssl != NULL) {
+ SSL_shutdown(ssl);
+ SSL_free(ssl);
+ }
+ SSL_CTX_free(ssl_ctx);
+
+ if (client_skt != -1)
+ close(client_skt);
+ if (server_skt != -1)
+ close(server_skt);
+
+ OPENSSL_free(txbuf);
+ OPENSSL_free(rxbuf);
+
+ printf("sslecho exiting\n");
+
+ return 0;
+}
diff --git a/demos/sslecho/makefile b/demos/sslecho/makefile
new file mode 100644
index 0000000000..6e639917d4
--- /dev/null
+++ b/demos/sslecho/makefile
@@ -0,0 +1,12 @@
+PROG ?= sslecho
+
+all: $(PROG)
+
+# Debug version.
+#
+$(PROG): main.c
+
+ $(CC) -O0 -g3 -W -Wall -I../../include -L../../ -o $(PROG) main.c -lssl -lcrypto
+
+clean:
+ rm -rf $(PROG) *.o *.obj