From 9e973eb297c8127dcaefe97619ddcd5067d12f37 Mon Sep 17 00:00:00 2001 From: Matt Caswell Date: Mon, 30 Oct 2023 12:39:37 +0000 Subject: [PATCH] Update the OpenSSL Guide tutorials with changes to the demos The demo code has changed to accept the hostname/port on the command line. We update the tutorials to keep in sync with the demo code. Reviewed-by: Paul Dale Reviewed-by: Tomas Mraz Reviewed-by: Richard Levitte Reviewed-by: Hugo Landau (Merged from https://github.com/openssl/openssl/pull/22552) --- doc/man7/ossl-guide-quic-client-non-block.pod | 19 +++++++-- doc/man7/ossl-guide-quic-multi-stream.pod | 42 ++++++++++++++----- doc/man7/ossl-guide-tls-client-block.pod | 29 +++++++++---- doc/man7/ossl-guide-tls-client-non-block.pod | 20 +++++++-- 4 files changed, 84 insertions(+), 26 deletions(-) diff --git a/doc/man7/ossl-guide-quic-client-non-block.pod b/doc/man7/ossl-guide-quic-client-non-block.pod index 0c2b916b80..f07e9cc669 100644 --- a/doc/man7/ossl-guide-quic-client-non-block.pod +++ b/doc/man7/ossl-guide-quic-client-non-block.pod @@ -341,13 +341,26 @@ data on a retry. An optional mode does exist the buffer being written to change from one retry to the next. However, in this case, you must still retry exactly the same data - even though the buffer that contains that data may change location. See L for further -details. +details. As in the TLS tutorials (L) we write +the request in three chunks. /* Write an HTTP GET request to the peer */ - while (!SSL_write_ex(ssl, request, strlen(request), &written)) { + while (!SSL_write_ex(ssl, request_start, strlen(request_start), &written)) { if (handle_io_failure(ssl, 0) == 1) continue; /* Retry */ - printf("Failed to write HTTP request\n"); + printf("Failed to write start of HTTP request\n"); + goto end; /* Cannot retry: error */ + } + while (!SSL_write_ex(ssl, hostname, strlen(hostname), &written)) { + if (handle_io_failure(ssl, 0) == 1) + continue; /* Retry */ + printf("Failed to write hostname in HTTP request\n"); + goto end; /* Cannot retry: error */ + } + while (!SSL_write_ex(ssl, request_end, strlen(request_end), &written)) { + if (handle_io_failure(ssl, 0) == 1) + continue; /* Retry */ + printf("Failed to write end of HTTP request\n"); goto end; /* Cannot retry: error */ } diff --git a/doc/man7/ossl-guide-quic-multi-stream.pod b/doc/man7/ossl-guide-quic-multi-stream.pod index 5b78409d61..1493d1c2b2 100644 --- a/doc/man7/ossl-guide-quic-multi-stream.pod +++ b/doc/man7/ossl-guide-quic-multi-stream.pod @@ -213,23 +213,43 @@ uni-directional one: =head2 Writing data to the streams Once the streams are successfully created we can start writing data to them. In -this example we will be sending a different HTTP request on each stream. We -assume the strings B and B hold the appropriate HTTP -requests. For the sake of simplicity this example does this sequentially, -writing to B first and, when this is successful, writing to B -second. Remember that our client is blocking so these calls will only return -once they have been successfully completed. A real application would not need to -do these writes sequentially or in any particular order. For example we could -start two threads (one for each stream) and write the requests to each stream -simultaneously. +this example we will be sending a different HTTP request on each stream. To +avoid repeating too much code we write a simple helper function to send an HTTP +request to a stream: + + int write_a_request(SSL *stream, const char *request_start, + const char *hostname) + { + const char *request_end = "\r\n\r\n"; + size_t written; + + if (!SSL_write_ex(stream, request_start, strlen(request_start), &written)) + return 0; + if (!SSL_write_ex(stream, hostname, strlen(hostname), &written)) + return 0; + if (!SSL_write_ex(stream, request_end, strlen(request_end), &written)) + return 0; + + return 1; + } + +We assume the strings B and B hold the +appropriate HTTP requests. We can then call our helper function above to send +the requests on the two streams. For the sake of simplicity this example does +this sequentially, writing to B first and, when this is successful, +writing to B second. Remember that our client is blocking so these +calls will only return once they have been successfully completed. A real +application would not need to do these writes sequentially or in any particular +order. For example we could start two threads (one for each stream) and write +the requests to each stream simultaneously. /* Write an HTTP GET request on each of our streams to the peer */ - if (!SSL_write_ex(stream1, request1, strlen(request1), &written)) { + if (!write_a_request(stream1, request1_start, hostname)) { printf("Failed to write HTTP request on stream 1\n"); goto end; } - if (!SSL_write_ex(stream2, request2, strlen(request2), &written)) { + if (!write_a_request(stream2, request2_start, hostname)) { printf("Failed to write HTTP request on stream 2\n"); goto end; } diff --git a/doc/man7/ossl-guide-tls-client-block.pod b/doc/man7/ossl-guide-tls-client-block.pod index 646b58081a..cb67bf8fa9 100644 --- a/doc/man7/ossl-guide-tls-client-block.pod +++ b/doc/man7/ossl-guide-tls-client-block.pod @@ -272,13 +272,13 @@ like this: * Tell the server during the handshake which hostname we are attempting * to connect to in case the server supports multiple hosts. */ - if (!SSL_set_tlsext_host_name(ssl, HOSTNAME)) { + if (!SSL_set_tlsext_host_name(ssl, hostname)) { printf("Failed to set the SNI hostname\n"); goto end; } -Here the HOSTNAME argument is a string representing the hostname of the server, -e.g. "www.example.com". +Here the C argument is a string representing the hostname of the +server, e.g. "www.example.com". Secondly, we need to tell OpenSSL what hostname we expect to see in the certificate coming back from the server. This is almost always the same one that @@ -293,7 +293,7 @@ itself. We do this via the L function: * Virtually all clients should do this unless you really know what you * are doing. */ - if (!SSL_set1_host(ssl, HOSTNAME)) { + if (!SSL_set1_host(ssl, hostname)) { printf("Failed to set the certificate verification hostname"); goto end; } @@ -345,15 +345,26 @@ connection. To send data to the server we use the L function and to receive data from the server we use the L function. In HTTP 1.0 the -client always writes data first. +client always writes data first. Our HTTP request will include the hostname that +we are connecting to. For simplicitly, we write the HTTP request in three +chunks. First we write the start of the request. Secondly we write the hostname +we are sending the request to. Finally we send the end of the request. size_t written; - const char *request = - "GET / HTTP/1.0\r\nConnection: close\r\nHost: "HOSTNAME"\r\n\r\n"; + const char *request_start = "GET / HTTP/1.0\r\nConnection: close\r\nHost: "; + const char *request_end = "\r\n\r\n"; /* Write an HTTP GET request to the peer */ - if (!SSL_write_ex(ssl, request, strlen(request), &written)) { - printf("Failed to write HTTP request\n"); + if (!SSL_write_ex(ssl, request_start, strlen(request_start), &written)) { + printf("Failed to write start of HTTP request\n"); + goto end; + } + if (!SSL_write_ex(ssl, hostname, strlen(hostname), &written)) { + printf("Failed to write hostname in HTTP request\n"); + goto end; + } + if (!SSL_write_ex(ssl, request_end, strlen(request_end), &written)) { + printf("Failed to write end of HTTP request\n"); goto end; } diff --git a/doc/man7/ossl-guide-tls-client-non-block.pod b/doc/man7/ossl-guide-tls-client-non-block.pod index 1eabcc0b57..ee03f6624b 100644 --- a/doc/man7/ossl-guide-tls-client-non-block.pod +++ b/doc/man7/ossl-guide-tls-client-non-block.pod @@ -252,13 +252,27 @@ retry. An optional mode does exist (B) which will configure OpenSSL to allow the buffer being written to change from one retry to the next. However, in this case, you must still retry exactly the same data - even though the buffer that contains that data may change location. -See L for further details. +See L for further details. As in the TLS client +blocking tutorial (L) we write the request +in three chunks. /* Write an HTTP GET request to the peer */ - while (!SSL_write_ex(ssl, request, strlen(request), &written)) { + while (!SSL_write_ex(ssl, request_start, strlen(request_start), &written)) { if (handle_io_failure(ssl, 0) == 1) continue; /* Retry */ - printf("Failed to write HTTP request\n"); + printf("Failed to write start of HTTP request\n"); + goto end; /* Cannot retry: error */ + } + while (!SSL_write_ex(ssl, hostname, strlen(hostname), &written)) { + if (handle_io_failure(ssl, 0) == 1) + continue; /* Retry */ + printf("Failed to write hostname in HTTP request\n"); + goto end; /* Cannot retry: error */ + } + while (!SSL_write_ex(ssl, request_end, strlen(request_end), &written)) { + if (handle_io_failure(ssl, 0) == 1) + continue; /* Retry */ + printf("Failed to write end of HTTP request\n"); goto end; /* Cannot retry: error */ } -- 2.34.1