Ensure the max_early_data option to s_server can be 0
[openssl.git] / apps / s_server.c
index cc910bc9a9df45626d0a96103ab91bf4cd1e9c4e..6e5c945e712b57ed472cee434a873c93bf528ab2 100644 (file)
@@ -147,6 +147,8 @@ static int dtlslisten = 0;
 static char *psk_identity = "Client_identity";
 char *psk_key = NULL;           /* by default PSK is not used */
 
+int early_data = 0;
+
 static unsigned int psk_server_cb(SSL *ssl, const char *identity,
                                   unsigned char *psk,
                                   unsigned int max_psk_len)
@@ -719,7 +721,7 @@ typedef enum OPTION_choice {
     OPT_ID_PREFIX, OPT_RAND, OPT_SERVERNAME, OPT_SERVERNAME_FATAL,
     OPT_CERT2, OPT_KEY2, OPT_NEXTPROTONEG, OPT_ALPN,
     OPT_SRTP_PROFILES, OPT_KEYMATEXPORT, OPT_KEYMATEXPORTLEN,
-    OPT_KEYLOG_FILE, OPT_MAX_EARLY,
+    OPT_KEYLOG_FILE, OPT_MAX_EARLY, OPT_EARLY_DATA,
     OPT_S_ENUM,
     OPT_V_ENUM,
     OPT_X_ENUM
@@ -916,8 +918,9 @@ const OPTIONS s_server_options[] = {
     {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
 #endif
     {"keylogfile", OPT_KEYLOG_FILE, '>', "Write TLS secrets to file"},
-    {"max_early_data", OPT_MAX_EARLY, 'p',
+    {"max_early_data", OPT_MAX_EARLY, 'n',
      "The maximum number of bytes of early data"},
+    {"early_data", OPT_EARLY_DATA, '-', "Attempt to read early data"},
     {NULL, OPT_EOF, 0, NULL}
 };
 
@@ -994,7 +997,7 @@ int s_server_main(int argc, char *argv[])
     unsigned int split_send_fragment = 0, max_pipelines = 0;
     const char *s_serverinfo_file = NULL;
     const char *keylog_file = NULL;
-    uint32_t max_early_data = 0;
+    int max_early_data = -1;
 
     /* Init of few remaining global variables */
     local_argc = argc;
@@ -1505,6 +1508,13 @@ int s_server_main(int argc, char *argv[])
             break;
         case OPT_MAX_EARLY:
             max_early_data = atoi(opt_arg());
+            if (max_early_data < 0) {
+                BIO_printf(bio_err, "Invalid value for max_early_data\n");
+                goto end;
+            }
+            break;
+        case OPT_EARLY_DATA:
+            early_data = 1;
             break;
         }
     }
@@ -1996,7 +2006,7 @@ int s_server_main(int argc, char *argv[])
     if (set_keylog_file(ctx, keylog_file))
         goto end;
 
-    if (max_early_data > 0)
+    if (max_early_data >= 0)
         SSL_CTX_set_max_early_data(ctx, max_early_data);
 
     BIO_printf(bio_s_out, "ACCEPT\n");
@@ -2199,6 +2209,43 @@ static int sv_body(int s, int stype, unsigned char *context)
         SSL_set_tlsext_debug_arg(con, bio_s_out);
     }
 
+    if (early_data) {
+        int write_header = 1, edret = SSL_READ_EARLY_ERROR;
+        size_t readbytes;
+
+        while (edret != SSL_READ_EARLY_FINISH) {
+            for (;;) {
+                edret = SSL_read_early(con, buf, bufsize, &readbytes);
+                if (edret != SSL_READ_EARLY_ERROR)
+                    break;
+
+                switch (SSL_get_error(con, 0)) {
+                case SSL_ERROR_WANT_WRITE:
+                case SSL_ERROR_WANT_ASYNC:
+                case SSL_ERROR_WANT_READ:
+                    /* Just keep trying - busy waiting */
+                    continue;
+                default:
+                    BIO_printf(bio_err, "Error reading early data\n");
+                    ERR_print_errors(bio_err);
+                    goto err;
+                }
+            }
+            if (readbytes > 0) {
+                if (write_header) {
+                    BIO_printf(bio_s_out, "Early data received:\n");
+                    write_header = 0;
+                }
+                raw_write_stdout(buf, (unsigned int)readbytes);
+                (void)BIO_flush(bio_s_out);
+            }
+        }
+        if (write_header)
+            BIO_printf(bio_s_out, "No early data received\n");
+        else
+            BIO_printf(bio_s_out, "\nEnd of early data\n");
+    }
+
     if (fileno_stdin() > s)
         width = fileno_stdin() + 1;
     else