QUIC SSL: SSL_set_fd for BIO_s_datagram
authorHugo Landau <hlandau@openssl.org>
Mon, 16 Jan 2023 15:29:16 +0000 (15:29 +0000)
committerPauli <pauli@openssl.org>
Tue, 4 Jul 2023 23:02:26 +0000 (09:02 +1000)
Reviewed-by: Tomas Mraz <tomas@openssl.org>
Reviewed-by: Matt Caswell <matt@openssl.org>
Reviewed-by: Paul Dale <pauli@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/20061)

doc/man3/SSL_set_fd.pod
ssl/ssl_lib.c
test/quicapitest.c

index f519630752aac6364e8b4f8899283f957b13fbbb..6e0ab578e67311f8689366340006d2dc7f754499 100644 (file)
@@ -23,6 +23,9 @@ interface between the B<ssl> and B<fd>. The BIO and hence the SSL engine
 inherit the behaviour of B<fd>. If B<fd> is nonblocking, the B<ssl> will
 also have nonblocking behaviour.
 
+When used on a QUIC SSL object, a B<datagram BIO> is automatically created
+instead of a B<socket BIO>.
+
 If there was already a BIO connected to B<ssl>, BIO_free() will be called
 (for both the reading and writing side, if different).
 
index 97a95ce4b99b46245bdc387bb67184608ba025e9..d6edc5be1659205b90319aa9c94d2cdbb8571e7f 100644 (file)
@@ -1662,7 +1662,7 @@ int SSL_set_fd(SSL *s, int fd)
     int ret = 0;
     BIO *bio = NULL;
 
-    bio = BIO_new(BIO_s_socket());
+    bio = BIO_new(IS_QUIC_SSL(s) ? BIO_s_datagram() : BIO_s_socket());
 
     if (bio == NULL) {
         ERR_raise(ERR_LIB_SSL, ERR_R_BUF_LIB);
@@ -1687,10 +1687,11 @@ int SSL_set_fd(SSL *s, int fd)
 int SSL_set_wfd(SSL *s, int fd)
 {
     BIO *rbio = SSL_get_rbio(s);
+    int desired_type = IS_QUIC_SSL(s) ? BIO_TYPE_DGRAM : BIO_TYPE_SOCKET;
 
-    if (rbio == NULL || BIO_method_type(rbio) != BIO_TYPE_SOCKET
+    if (rbio == NULL || BIO_method_type(rbio) != desired_type
         || (int)BIO_get_fd(rbio, NULL) != fd) {
-        BIO *bio = BIO_new(BIO_s_socket());
+        BIO *bio = BIO_new(IS_QUIC_SSL(s) ? BIO_s_datagram() : BIO_s_socket());
 
         if (bio == NULL) {
             ERR_raise(ERR_LIB_SSL, ERR_R_BUF_LIB);
@@ -1717,10 +1718,11 @@ int SSL_set_wfd(SSL *s, int fd)
 int SSL_set_rfd(SSL *s, int fd)
 {
     BIO *wbio = SSL_get_wbio(s);
+    int desired_type = IS_QUIC_SSL(s) ? BIO_TYPE_DGRAM : BIO_TYPE_SOCKET;
 
-    if (wbio == NULL || BIO_method_type(wbio) != BIO_TYPE_SOCKET
+    if (wbio == NULL || BIO_method_type(wbio) != desired_type
         || ((int)BIO_get_fd(wbio, NULL) != fd)) {
-        BIO *bio = BIO_new(BIO_s_socket());
+        BIO *bio = BIO_new(IS_QUIC_SSL(s) ? BIO_s_datagram() : BIO_s_socket());
 
         if (bio == NULL) {
             ERR_raise(ERR_LIB_SSL, ERR_R_BUF_LIB);
index 1205e968da6d315c322dd7faa3e1aa830bb3de51..2784f981983976fdc2431c080a4c200be71191ae 100644 (file)
@@ -505,6 +505,62 @@ err:
     return testresult;
 }
 
+static int test_quic_set_fd(int idx)
+{
+    int testresult = 0;
+    SSL_CTX *ctx = NULL;
+    SSL *ssl = NULL;
+    int fd = -1, resfd = -1;
+    BIO *bio = NULL;
+
+    if (!TEST_ptr(ctx = SSL_CTX_new_ex(libctx, NULL, OSSL_QUIC_client_method())))
+        goto err;
+
+    if (!TEST_ptr(ssl = SSL_new(ctx)))
+        goto err;
+
+    if (!TEST_int_ge(fd = BIO_socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP, 0), 0))
+        goto err;
+
+    if (idx == 0) {
+        if (!TEST_true(SSL_set_fd(ssl, fd)))
+            goto err;
+        if (!TEST_ptr(bio = SSL_get_rbio(ssl)))
+            goto err;
+        if (!TEST_ptr_eq(bio, SSL_get_wbio(ssl)))
+            goto err;
+    } else if (idx == 1) {
+        if (!TEST_true(SSL_set_rfd(ssl, fd)))
+            goto err;
+        if (!TEST_ptr(bio = SSL_get_rbio(ssl)))
+            goto err;
+        if (!TEST_ptr_null(SSL_get_wbio(ssl)))
+            goto err;
+    } else {
+        if (!TEST_true(SSL_set_wfd(ssl, fd)))
+            goto err;
+        if (!TEST_ptr(bio = SSL_get_wbio(ssl)))
+            goto err;
+        if (!TEST_ptr_null(SSL_get_rbio(ssl)))
+            goto err;
+    }
+
+    if (!TEST_int_eq(BIO_method_type(bio), BIO_TYPE_DGRAM))
+        goto err;
+
+    if (!TEST_true(BIO_get_fd(bio, &resfd))
+        || !TEST_int_eq(resfd, fd))
+        goto err;
+
+    testresult = 1;
+err:
+    SSL_free(ssl);
+    SSL_CTX_free(ctx);
+    if (fd >= 0)
+        BIO_closesocket(fd);
+    return testresult;
+}
+
 OPT_TEST_DECLARE_USAGE("provider config certsdir datadir\n")
 
 int setup_tests(void)
@@ -569,6 +625,7 @@ int setup_tests(void)
     ADD_TEST(test_quic_forbidden_apis_ctx);
     ADD_TEST(test_quic_forbidden_apis);
     ADD_TEST(test_quic_forbidden_options);
+    ADD_ALL_TESTS(test_quic_set_fd, 3);
     return 1;
  err:
     cleanup_tests();