]> git.ipfire.org Git - thirdparty/openssl.git/commitdiff
s_server: Support reading HTTP request from early data
authorDaiki Ueno <dueno@redhat.com>
Wed, 11 Sep 2024 01:13:55 +0000 (10:13 +0900)
committerTomas Mraz <tomas@openssl.org>
Thu, 12 Sep 2024 12:19:44 +0000 (14:19 +0200)
This would be useful when testing with browsers / downloaders which
support 0-RTT only through HTTP.

Signed-off-by: Daiki Ueno <dueno@redhat.com>
Reviewed-by: Tom Cosgrove <tom.cosgrove@arm.com>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/16055)

apps/s_server.c
doc/man1/openssl-s_server.pod.in

index e47691655e9e7b92d9566f5c3ed30117dab6da95..888e8f62cf0a02136ba75d90d5618143f238c91c 100644 (file)
@@ -1757,9 +1757,9 @@ int s_server_main(int argc, char *argv[])
         goto end;
     }
 #endif
-    if (early_data && (www > 0 || rev)) {
+    if (early_data && rev) {
         BIO_printf(bio_err,
-                   "Can't use -early_data in combination with -www, -WWW, -HTTP, or -rev\n");
+                   "Can't use -early_data in combination with -rev\n");
         goto end;
     }
 
@@ -3156,7 +3156,7 @@ static int www_body(int s, int stype, int prot, unsigned char *context)
     int i, j, k, dot;
     SSL *con;
     const SSL_CIPHER *c;
-    BIO *io, *ssl_bio, *sbio;
+    BIO *io, *ssl_bio, *sbio, *edio;
 #ifdef RENEG
     int total_bytes = 0;
 #endif
@@ -3178,7 +3178,8 @@ static int www_body(int s, int stype, int prot, unsigned char *context)
     p = buf = app_malloc(bufsize + 1, "server www buffer");
     io = BIO_new(BIO_f_buffer());
     ssl_bio = BIO_new(BIO_f_ssl());
-    if ((io == NULL) || (ssl_bio == NULL))
+    edio = BIO_new(BIO_s_mem());
+    if ((io == NULL) || (ssl_bio == NULL) || (edio == NULL))
         goto err;
 
     if (s_nbio) {
@@ -3238,6 +3239,12 @@ static int www_body(int s, int stype, int prot, unsigned char *context)
         goto err;
 
     io = BIO_push(filter, io);
+
+    filter = BIO_new(BIO_f_ebcdic_filter());
+    if (filter == NULL)
+        goto err;
+
+    edio = BIO_push(filter, edio);
 #endif
 
     if (s_debug) {
@@ -3254,8 +3261,35 @@ static int www_body(int s, int stype, int prot, unsigned char *context)
         SSL_set_msg_callback_arg(con, bio_s_msg ? bio_s_msg : bio_s_out);
     }
 
+    if (early_data) {
+        int edret = SSL_READ_EARLY_DATA_ERROR;
+        size_t readbytes;
+
+        while (edret != SSL_READ_EARLY_DATA_FINISH) {
+            for (;;) {
+                edret = SSL_read_early_data(con, buf, bufsize, &readbytes);
+                if (edret != SSL_READ_EARLY_DATA_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)
+                BIO_write(edio, buf, (int)readbytes);
+        }
+    }
+
     for (;;) {
-        i = BIO_gets(io, buf, bufsize + 1);
+        i = BIO_gets(!BIO_eof(edio) ? edio : io, buf, bufsize + 1);
         if (i < 0) {            /* error */
             if (!BIO_should_retry(io) && !SSL_waiting_for_async(con)) {
                 if (!s_quiet)
@@ -3595,6 +3629,7 @@ static int www_body(int s, int stype, int prot, unsigned char *context)
     OPENSSL_free(buf);
     BIO_free(ssl_bio);
     BIO_free_all(io);
+    BIO_free_all(edio);
     return ret;
 }
 
index 80f8c329929b3a37f05882ebe6aed19eca1343a9..b5ec29ad5f35cef0989039a556df36346bdc65fa 100644 (file)
@@ -412,7 +412,6 @@ information about the ciphers used and various session parameters.
 The output is in HTML format so this option can be used with a web browser.
 The special URL C</renegcert> turns on client cert validation, and C</reneg>
 tells the server to request renegotiation.
-The B<-early_data> option cannot be used with this option.
 
 =item B<-WWW>, B<-HTTP>
 
@@ -428,7 +427,6 @@ Extensions of C<html>, C<htm>, and C<php> are C<text/html> and all others are
 C<text/plain>.
 In addition, the special URL C</stats> will return status
 information like the B<-www> option.
-Neither of these options can be used in conjunction with B<-early_data>.
 
 =item B<-http_server_binmode>