Add the SSL_stateless() function
[openssl.git] / apps / s_socket.c
index 804ab5b05a3cc62f4d65b90f8dccf185e73b9cb1..a9e46f9949a8a12e0532a0f13b6ac5bb6cd7dd3f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the OpenSSL license (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -28,14 +28,16 @@ typedef unsigned int u_int;
 
 #ifndef OPENSSL_NO_SOCK
 
-# define USE_SOCKETS
 # include "apps.h"
-# undef USE_SOCKETS
 # include "s_apps.h"
+# include "internal/sockets.h"
 
 # include <openssl/bio.h>
 # include <openssl/err.h>
 
+/* Keep track of our peer's address for the cookie callback */
+BIO_ADDR *ourpeer = NULL;
+
 /*
  * init_client - helper routine to set up socket communication
  * @sock: pointer to storage of resulting socket.
@@ -213,8 +215,15 @@ int do_server(int *accept_sock, const char *host, const char *port,
         *accept_sock = asock;
     for (;;) {
         if (type == SOCK_STREAM) {
+            BIO_ADDR_free(ourpeer);
+            ourpeer = BIO_ADDR_new();
+            if (ourpeer == NULL) {
+                BIO_closesocket(asock);
+                ERR_print_errors(bio_err);
+                goto end;
+            }
             do {
-                sock = BIO_accept_ex(asock, NULL, 0);
+                sock = BIO_accept_ex(asock, ourpeer, 0);
             } while (sock < 0 && BIO_sock_should_retry(sock));
             if (sock < 0) {
                 ERR_print_errors(bio_err);
@@ -222,6 +231,31 @@ int do_server(int *accept_sock, const char *host, const char *port,
                 break;
             }
             i = (*cb)(sock, type, protocol, context);
+
+            /*
+             * Give the socket time to send its last data before we close it.
+             * No amount of setting SO_LINGER etc on the socket seems to
+             * persuade Windows to send the data before closing the socket...
+             * but sleeping for a short time seems to do it (units in ms)
+             * TODO: Find a better way to do this
+             */
+#if defined(OPENSSL_SYS_WINDOWS)
+            Sleep(50);
+#elif defined(OPENSSL_SYS_CYGWIN)
+            usleep(50000);
+#endif
+
+            /*
+             * If we ended with an alert being sent, but still with data in the
+             * network buffer to be read, then calling BIO_closesocket() will
+             * result in a TCP-RST being sent. On some platforms (notably
+             * Windows) then this will result in the peer immediately abandoning
+             * the connection including any buffered alert data before it has
+             * had a chance to be read. Shutting down the sending side first,
+             * and then closing the socket sends TCP-FIN first followed by
+             * TCP-RST. This seems to allow the peer to read the alert data.
+             */
+            shutdown(sock, 1); /* SHUT_WR */
             BIO_closesocket(sock);
         } else {
             i = (*cb)(asock, type, protocol, context);
@@ -240,6 +274,8 @@ int do_server(int *accept_sock, const char *host, const char *port,
     if (family == AF_UNIX)
         unlink(host);
 # endif
+    BIO_ADDR_free(ourpeer);
+    ourpeer = NULL;
     return ret;
 }