]> git.ipfire.org Git - thirdparty/openssl.git/commitdiff
Added Simple SSL Echo Client/Server to demos.
authorbobwirka <bobwirka@yahoo.com>
Sun, 12 Dec 2021 19:53:13 +0000 (14:53 -0500)
committerMatt Caswell <matt@openssl.org>
Tue, 12 Apr 2022 14:12:57 +0000 (15:12 +0100)
Reviewed-by: Paul Dale <pauli@openssl.org>
Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/17260)

demos/README.txt
demos/sslecho/A-SSL-Docs.txt [new file with mode: 0644]
demos/sslecho/README.md [new file with mode: 0644]
demos/sslecho/cert.pem [new file with mode: 0644]
demos/sslecho/key.pem [new file with mode: 0644]
demos/sslecho/main.c [new file with mode: 0644]
demos/sslecho/makefile [new file with mode: 0644]

index 650529572c61fa91807ac83d07877a83339ac52e..a4b8be0fe3b97c3b036176c57e93f7eecc3cca86 100644 (file)
@@ -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 (file)
index 0000000..865960e
--- /dev/null
@@ -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 (file)
index 0000000..58f7ca0
--- /dev/null
@@ -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 (file)
index 0000000..834d462
--- /dev/null
@@ -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 (file)
index 0000000..75b86c3
--- /dev/null
@@ -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 (file)
index 0000000..c6f087c
--- /dev/null
@@ -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 (file)
index 0000000..6e63991
--- /dev/null
@@ -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