Add a tutorial on writing a simple blocking QUIC client
authorMatt Caswell <matt@openssl.org>
Wed, 14 Jun 2023 09:22:57 +0000 (10:22 +0100)
committerPauli <pauli@openssl.org>
Tue, 27 Jun 2023 23:53:22 +0000 (09:53 +1000)
This tutorial only covers a single stream client at this stage. A future
PR will cover adding multi-stream support.

Reviewed-by: Tomas Mraz <tomas@openssl.org>
Reviewed-by: Hugo Landau <hlandau@openssl.org>
Reviewed-by: Paul Dale <pauli@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/21204)

doc/build.info
doc/man7/ossl-guide-quic-client-block.pod [new file with mode: 0644]
doc/man7/ossl-guide-quic-introduction.pod [new file with mode: 0644]
doc/man7/ossl-guide-tls-client-block.pod
doc/man7/ossl-guide-tls-introduction.pod

index b8748d073debf5c2d1f682ebc2e1926b64866eb2..24d4050a45a7b5559b57527447cbb2161bcefee6 100644 (file)
@@ -4757,6 +4757,14 @@ DEPEND[man/man7/openssl_user_macros.7]=man7/openssl_user_macros.pod
 GENERATE[man/man7/openssl_user_macros.7]=man7/openssl_user_macros.pod
 DEPEND[man7/openssl_user_macros.pod]{pod}=man7/openssl_user_macros.pod.in
 GENERATE[man7/openssl_user_macros.pod]=man7/openssl_user_macros.pod.in
+DEPEND[html/man7/ossl-guide-quic-client-block.html]=man7/ossl-guide-quic-client-block.pod
+GENERATE[html/man7/ossl-guide-quic-client-block.html]=man7/ossl-guide-quic-client-block.pod
+DEPEND[man/man7/ossl-guide-quic-client-block.7]=man7/ossl-guide-quic-client-block.pod
+GENERATE[man/man7/ossl-guide-quic-client-block.7]=man7/ossl-guide-quic-client-block.pod
+DEPEND[html/man7/ossl-guide-quic-introduction.html]=man7/ossl-guide-quic-introduction.pod
+GENERATE[html/man7/ossl-guide-quic-introduction.html]=man7/ossl-guide-quic-introduction.pod
+DEPEND[man/man7/ossl-guide-quic-introduction.7]=man7/ossl-guide-quic-introduction.pod
+GENERATE[man/man7/ossl-guide-quic-introduction.7]=man7/ossl-guide-quic-introduction.pod
 DEPEND[html/man7/ossl-guide-tls-client-block.html]=man7/ossl-guide-tls-client-block.pod
 GENERATE[html/man7/ossl-guide-tls-client-block.html]=man7/ossl-guide-tls-client-block.pod
 DEPEND[man/man7/ossl-guide-tls-client-block.7]=man7/ossl-guide-tls-client-block.pod
@@ -4973,6 +4981,8 @@ html/man7/openssl-glossary.html \
 html/man7/openssl-quic.html \
 html/man7/openssl-threads.html \
 html/man7/openssl_user_macros.html \
+html/man7/ossl-guide-quic-client-block.html \
+html/man7/ossl-guide-quic-introduction.html \
 html/man7/ossl-guide-tls-client-block.html \
 html/man7/ossl-guide-tls-introduction.html \
 html/man7/ossl_store-file.html \
@@ -5108,6 +5118,8 @@ man/man7/openssl-glossary.7 \
 man/man7/openssl-quic.7 \
 man/man7/openssl-threads.7 \
 man/man7/openssl_user_macros.7 \
+man/man7/ossl-guide-quic-client-block.7 \
+man/man7/ossl-guide-quic-introduction.7 \
 man/man7/ossl-guide-tls-client-block.7 \
 man/man7/ossl-guide-tls-introduction.7 \
 man/man7/ossl_store-file.7 \
diff --git a/doc/man7/ossl-guide-quic-client-block.pod b/doc/man7/ossl-guide-quic-client-block.pod
new file mode 100644 (file)
index 0000000..4506f88
--- /dev/null
@@ -0,0 +1,294 @@
+=pod
+
+=begin comment
+
+NB: Changes to the source code samples in this file should also be reflected in
+demos/guide/quic-client-block.c
+
+=end comment
+
+=head1 NAME
+
+ossl-guide-quic-client-block
+- OpenSSL Guide: Writing a simple blocking QUIC client
+
+=head1 SIMPLE BLOCKING QUIC CLIENT EXAMPLE
+
+This page will present various source code samples demonstrating how to write
+a simple blocking QUIC client application which connects to a server, sends an
+HTTP/1.0 request to it, and reads back the response. Note that HTTP/1.0 over
+QUIC is non-standard and will not typically be supported by real world servers.
+This is for demonstration purposes only.
+
+We assume that you already have OpenSSL installed on your system; that you
+already have some fundamental understanding of OpenSSL concepts, TLS and QUIC
+(see L<crypto(7)>, L<ossl-guide-tls-introduction(7)> and
+L<ossl-guide-quic-introduction(7)>); and that you know how to
+write and build C code and link it against the libcrypto and libssl libraries
+that are provided by OpenSSL. It also assumes that you have a basic
+understanding of UDP/IP and sockets. The example code that we build in this
+tutorial will amend the blocking TLS client example that is covered in
+L<ossl-guide-tls-client-block(7)>. Only the differences between that client and
+this one will be discussed so we also assume that you have run through and
+understand that tutorial.
+
+For this tutorial our client will be using a single QUIC stream. A subsequent
+tutorial will discuss how to write a multi-stream client.
+
+The complete source code for this example blocking QUIC client is available in
+the C<demos/guide> directory of the OpenSSL source distribution in the file
+C<quic-client-block.c>. It is also available online at
+L<https://github.com/openssl/openssl/blob/master/demos/guide/quic-client-block.c>.
+
+=head2 Creating the SSL_CTX and SSL objects
+
+In the TLS tutorial (L<ossl-guide-tls-client-block(7)>) we created an B<SSL_CTX>
+object for our client and used it to create an B<SSL> object to represent the
+TLS connection. A QUIC connection works in exactly the same way. We first create
+an B<SSL_CTX> object and then use it to create an B<SSL> object to represent the
+QUIC connection.
+
+As in the TLS example the first step is to create an B<SSL_CTX> object for our
+client. This is done in the same way as before except that we use a different
+"method". OpenSSL offers two different QUIC client methods, i.e.
+L<OSSL_QUIC_client_method(3)> and L<OSSL_QUIC_client_thread_method(3)>.
+
+The first one is the equivalent of L<TLS_client_method(3)> but for the QUIC
+protocol. The second one is the same, but it will additionally create a
+background thread for handling time based events (known as "thread assisted
+mode", see L<ossl-guide-quic-introduction(7)>). For this tutorial we will be
+using L<OSSL_QUIC_client_method(3)> because we will not be leaving the QUIC
+connection idle in our application and so thread assisted mode is not needed.
+
+    /*
+     * Create an SSL_CTX which we can use to create SSL objects from. We
+     * want an SSL_CTX for creating clients so we use OSSL_QUIC_client_method()
+     * here.
+     */
+    ctx = SSL_CTX_new(OSSL_QUIC_client_method());
+    if (ctx == NULL) {
+        printf("Failed to create the SSL_CTX\n");
+        goto end;
+    }
+
+The other setup steps that we applied to the B<SSL_CTX> for TLS also apply to
+QUIC except for restricting the TLS versions that we are willing to accept. The
+QUIC protocol implementation in OpenSSL currently only supports TLSv1.3. There
+is no need to call L<SSL_CTX_set_min_proto_version(3)> or
+L<SSL_CTX_set_max_proto_version(3)> in an OpenSSL QUIC application, and any such
+call will be ignored.
+
+Once the B<SSL_CTX> is created, the B<SSL> object is constructed in exactly the
+same way as for the TLS application.
+
+=head2 Creating the socket and BIO
+
+A major difference between TLS and QUIC is the underlying transport protocol.
+TLS uses TCP while QUIC uses UDP. The way that the QUIC socket is created in our
+example code is much the same as for TLS. We use the L<BIO_lookup_ex(3)> and
+L<BIO_socket(3)> helper functions as we did in the previous tutorial except that
+we pass B<SOCK_DGRAM> as an argument to indicate UDP (instead of B<SOCK_STREAM>
+for TCP).
+
+    /*
+     * Lookup IP address info for the server.
+     */
+    if (!BIO_lookup_ex(hostname, port, BIO_LOOKUP_CLIENT, 0, SOCK_DGRAM, 0,
+                       &res))
+        return NULL;
+
+    /*
+     * Loop through all the possible addresses for the server and find one
+     * we can connect to.
+     */
+    for (ai = res; ai != NULL; ai = BIO_ADDRINFO_next(ai)) {
+        /*
+         * Create a TCP socket. We could equally use non-OpenSSL calls such
+         * as "socket" here for this and the subsequent connect and close
+         * functions. But for portability reasons and also so that we get
+         * errors on the OpenSSL stack in the event of a failure we use
+         * OpenSSL's versions of these functions.
+         */
+        sock = BIO_socket(BIO_ADDRINFO_family(ai), SOCK_DGRAM, 0, 0);
+        if (sock == -1)
+            continue;
+
+        /* Connect the socket to the server's address */
+        if (!BIO_connect(sock, BIO_ADDRINFO_address(ai), 0)) {
+            BIO_closesocket(sock);
+            sock = -1;
+            continue;
+        }
+
+        /* Set to nonblocking mode */
+        if (!BIO_socket_nbio(sock, 1)) {
+            sock = -1;
+            continue;
+        }
+
+        break;
+    }
+
+    if (sock != -1) {
+        *peer_addr = BIO_ADDR_dup(BIO_ADDRINFO_address(ai));
+        if (*peer_addr == NULL) {
+            BIO_closesocket(sock);
+            return NULL;
+        }
+    }
+
+    /* Free the address information resources we allocated earlier */
+    BIO_ADDRINFO_free(res);
+
+You may notice a couple of other differences between this code and the version
+that we used for TLS.
+
+Firstly, we set the socket into nonblocking mode. This must always be done for
+an OpenSSL QUIC application. This may be surprising considering that we are
+trying to write a blocking client. Despite this the B<SSL> object will still
+have blocking behaviour. See L<ossl-guide-quic-introduction(7)> for further
+information on this.
+
+Secondly, we take note of the IP address of the peer that we are connecting to.
+We store that information away. We will need it later.
+
+See L<BIO_lookup_ex(3)>, L<BIO_socket(3)>, L<BIO_connect(3)>,
+L<BIO_closesocket(3)>, L<BIO_ADDRINFO_next(3)>, L<BIO_ADDRINFO_address(3)>,
+L<BIO_ADDRINFO_free(3)> and L<BIO_ADDR_dup(3)> for further information on the
+functions used here. In the above example code the B<hostname> and B<port>
+variables are strings, e.g. "www.example.com" and "443".
+
+As for our TLS client, once the socket has been created and connected we need to
+associate it with a BIO object:
+
+    BIO *bio;
+
+    /* Create a BIO to wrap the socket*/
+    bio = BIO_new(BIO_s_datagram());
+    if (bio == NULL)
+        BIO_closesocket(sock);
+
+    /*
+     * Associate the newly created BIO with the underlying socket. By
+     * passing BIO_CLOSE here the socket will be automatically closed when
+     * the BIO is freed. Alternatively you can use BIO_NOCLOSE, in which
+     * case you must close the socket explicitly when it is no longer
+     * needed.
+     */
+    BIO_set_fd(bio, sock, BIO_CLOSE);
+
+Note the use of L<BIO_s_datagram(3)> here as opposed to L<BIO_s_socket(3)> that
+we used for our TLS client. This is again due to the fact that QUIC uses UDP
+instead of TCP for its transport layer. See L<BIO_new(3)>, L<BIO_s_datagram(3)>
+and L<BIO_set_fd(3)> for further information on these functions.
+
+=head2 Setting the server's hostname
+
+As in the TLS tutorial we need to set the server's hostname both for SNI (Server
+Name Indication) and for certificate validation purposes. The steps for this are
+identical to the TLS tutorial and won't be repeated here.
+
+=head2 Setting the ALPN
+
+ALPN (Application-Layer Protocol Negotiation) is a feature of TLS that enables
+the application to negotiate which protocol will be used over the connection.
+For example, if you intend to use HTTP/3 over the connection then the ALPN value
+for that is "h3" (see
+L<https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xml#alpn-protocol-ids>).
+OpenSSL provides the ability for a client to specify the ALPN to use via the
+L<SSL_set_alpn_protos(3)> function. This is optional for a TLS client and so our
+simple client that we developed in L<ossl-guide-tls-client-block(7)> did not use
+it. However QUIC mandates that the TLS handshake used in establishing a QUIC
+connection must use ALPN.
+
+    unsigned char alpn[] = { 8, 'h', 't', 't', 'p', '/', '1', '.', '0' };
+
+    /* SSL_set_alpn_protos returns 0 for success! */
+    if (SSL_set_alpn_protos(ssl, alpn, sizeof(alpn)) != 0) {
+        printf("Failed to set the ALPN for the connection\n");
+        goto end;
+    }
+
+The ALPN is specified using a length prefixed array of unsigned chars (it is not
+a NUL terminated string). Our original TLS blocking client demo was using
+HTTP/1.0. We will use the same for this example. Unlike most OpenSSL functions
+L<SSL_set_alpn_protos(3)> returns zero for success and nonzero for failure.
+
+=head2 Setting the peer address
+
+An OpenSSL QUIC application must specify the target address of the server that
+is being connected to. In L</Creating the socket and BIO> above we saved that
+address away for future use. Now we need to use it via the
+L<SSL_set_initial_peer_addr(3)> function.
+
+    if (!SSL_set_initial_peer_addr(ssl, peer_addr)) {
+        printf("Failed to set the inital peer address\n");
+        goto end;
+    }
+
+Note that we will need to free the B<peer_addr> value that we allocated via
+L<BIO_ADDR_dup(3)> earlier:
+
+    BIO_ADDR_free(peer_addr);
+
+=head2 The handshake and application data transfer
+
+Once initial setup of the B<SSL> object is complete then we perform the
+handshake via L<SSL_connect(3)> in exactly the same way as we did for the TLS
+client, so we won't repeat it here.
+
+We can also perform data transfer using a default QUIC stream that is
+automatically associated with the B<SSL> object for us. We can transmit data
+using L<SSL_write_ex(3)>, and receive data using L<SSL_read_ex(3)> in exactly
+the same way as for TLS. Again, we won't repeat it here.
+
+=head2 Shutting down the connection
+
+As in the TLS tutorial, once we have finished reading data from the server then
+we are ready to close the connection down. As before we do this via the
+L<SSL_shutdown(3)> function. This example for QUIC is very similar to the TLS
+version. However the L<SSL_shutdown(3)> function may need to be called more than
+once:
+
+    /*
+     * Repeatedly call SSL_shutdown() until the connection is fully
+     * closed.
+     */
+    do {
+        ret = SSL_shutdown(ssl);
+        if (ret < 0) {
+            printf("Error shuting down: %d\n", ret);
+            goto end;
+        }
+    } while (ret != 1);
+
+The shutdown process is in two stages. First we gracefully shutdown the
+connection for sending and secondly we shutdown the connection for receiving.
+L<SSL_shutdown(3)> returns 0 once the first stage has been completed, and 1 once
+the second stage is finished. This two stage process applies to TLS as well.
+However in our blocking TLS client example code we knew that the peer had
+already partially closed down due to the B<SSL_ERROR_ZERO_RETURN> that we had
+obtained via L<SSL_get_error(3)> after the final L<SSL_read_ex(3)> call. Due to
+that return value we knew that the connection was already closed down for
+receiving data and hence L<SSL_shutdown(3)> should only need to be called once.
+
+However, with QUIC, the B<SSL_ERROR_ZERO_RETURN> value only tells us that the
+stream (not the connection) is partially closed down. Therefore we need to call
+L<SSL_shutdown(3)> more than once to ensure that we progress through both stages
+of the shutdown process.
+
+=head1 SEE ALSO
+
+L<crypto(7)>, L<ossl-guide-tls-introduction(7)>,
+L<ossl-guide-tls-client-block(7)>, L<ossl-guide-quic-introduction(7)>
+
+=head1 COPYRIGHT
+
+Copyright 2023 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License").  You may not use
+this file except in compliance with the License.  You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man7/ossl-guide-quic-introduction.pod b/doc/man7/ossl-guide-quic-introduction.pod
new file mode 100644 (file)
index 0000000..33f9c3e
--- /dev/null
@@ -0,0 +1,135 @@
+=pod
+
+=head1 NAME
+
+ossl-guide-quic-introduction
+- OpenSSL Guide: An introduction to QUIC in OpenSSL
+
+=head1 INTRODUCTION
+
+This page will provide an introduction to some basic QUIC concepts and
+background and how it is used within OpenSSL. It assumes that you have a basic
+understanding of UDP/IP and sockets. It also assumes that you are familiar with
+some OpenSSL and TLS fundamentals (see L<crypto(7)> and
+L<ossl-guide-tls-introduction(7)>).
+
+=head1 WHAT IS QUIC?
+
+QUIC is a general purpose protocol for enabling applications to securely
+communicate over a network. It is defined in RFC9000 (see
+L<https://datatracker.ietf.org/doc/rfc9000/>). QUIC integrates parts of the
+TLS protocol for connection establishment but independently protects packets.
+It provides similar security guarantees to TLS such as confidentiality,
+integrity and authentication (see L<ossl-guide-tls-introduction(7)>). It
+additionally provides multiplexing capabilities through the use of "streams"
+(see L</QUIC STREAMS> below).
+
+=head1 QUIC TIME BASED EVENTS
+
+A key difference between the TLS implementation and the QUIC implementation in
+OpenSSL is how time is handled. The QUIC protocol requires various actions to be
+performed on a regular basis regardless of whether application data is being
+transmitted or received.
+
+OpenSSL introduces a new function L<SSL_handle_events(3)> that will
+automatically process any outstanding time based events that must be handled.
+Alternatively calling any I/O function such as L<SSL_read_ex(3)> or
+L<SSL_write_ex(3)> will also process these events. There is also
+L<SSL_get_event_timeout(3)> which tells an application the amount of time that
+remains until L<SSL_handle_events(3)> (or any I/O function) must be called.
+
+Fortunately a blocking application that does not leave the QUIC connection idle,
+and is regularly calling I/O functions does not typically need to worry about
+this. However if you are developing a nonblocking application or one that may
+leave the QUIC connection idle for a period of time then you will need to
+arrange to call these functions.
+
+OpenSSL provides an optional "thread assisted mode" that will automatically
+create a background thread and will regularly call L<SSL_handle_events(3)> in a
+thread safe manner. This provides a simple way for an application to satisfy the
+QUIC requirements for time based events without having to implement special
+logic to accomplish it.
+
+=head1 QUIC AND TLS
+
+QUIC reuses parts of the TLS protocol in its implementation. Specifically the
+TLS handshake also exists in QUIC. The TLS handshake messages are wrapped up in
+QUIC protocol messages in order to send them to the peer. Once the TLS handshake
+is complete all application data is sent entirely using QUIC protocol messages
+without using TLS - although some TLS handshake messages may still be sent in
+some circumstances.
+
+This relationship between QUIC and TLS means that many of the API functions in
+OpenSSL that apply to TLS connections also apply to QUIC connections and
+applications can use them in exactly the same way. Some functions do not apply
+to QUIC at all, and others have altered semantics. You should refer to the
+documentation pages for each function for information on how it applies to QUIC.
+Typically if QUIC is not mentioned in the manual pages then the functions apply
+to both TLS and QUIC.
+
+=head1 QUIC STREAMS
+
+QUIC introduces the concept of "streams". A stream provides a reliable
+mechanism for sending and receiving application data between the endpoints. The
+bytes transmitted are guaranteed to be received in the same order they were sent
+without any loss of data or reordering of the bytes. A TLS application
+effectively has one bi-directional stream available to it per TLS connection. A
+QUIC application can have multiple uni-directional or bi-directional streams
+available to it for each connection.
+
+In OpenSSL an B<SSL> object is used to represent both connections and streams.
+A QUIC application creates an initial B<SSL> object to represent the connection
+(known as the connection B<SSL> object). Once the connection is complete
+additional B<SSL> objects can be created to represent streams (known as stream
+B<SSL> objects). Unless configured otherwise, a "default" stream is also
+associated with the connection B<SSL> object so you can still write data and
+read data to/from it. Some OpenSSL API functions can only be used with
+connection B<SSL> objects, and some can only be used with stream B<SSL> objects.
+Check the documentation for each function to confirm what type of B<SSL> object
+can be used in any particular context. A connection B<SSL> object that has a
+default stream attached to it can be used in contexts that require a connection
+B<SSL> object or in contexts that require a stream B<SSL> object.
+
+=head1 SOCKETS AND BLOCKING
+
+TLS assumes "stream" type semantics for its underlying transport layer protocol
+(usually achieved by using TCP). However QUIC assumes "datagram" type semantics
+by using UDP. An OpenSSL application using QUIC is responsible for creating a
+BIO to represent the underlying transport layer. This BIO must support datagrams
+and is typically L<BIO_s_datagram(3)>, but other B<BIO> choices are available.
+See L<bio(7)> for an introduction to OpenSSL's B<BIO> concept.
+
+A significant difference between OpenSSL TLS applications and OpenSSL QUIC
+applications is the way that blocking is implemented. In TLS if your application
+expects blocking behaviour then you configure the underlying socket for
+blocking. Conversely if your application wants nonblocking behaviour then the
+underlying socket is configured to be nonblocking.
+
+With an OpenSSL QUIC application the underlying socket must always be configured
+to be nonblocking. Howevever the B<SSL> object will, by default, still operate
+in blocking mode. So, from an application's perspective, calls to functions such
+as L<SSL_read_ex(3)>, L<SSL_write_ex(3)> and other I/O functions will still
+block. OpenSSL itself provides that blocking capability for QUIC instead of the
+socket. If nonblocking behaviour is desired then the application must call
+L<SSL_set_blocking_mode(3)>.
+
+=head1 FURTHER READING
+
+See L<ossl-guide-quic-client-block(7)> to see an example of applying these
+concepts in order to write a simple blocking QUIC client.
+
+=head1 SEE ALSO
+
+L<crypto(7)>, L<bio(7)>, L<ossl-guide-tls-introduction(7)>,
+L<ossl-guide-tls-client-block(7)>, L<ossl-guide-quic-client-block(7)>
+
+=head1 COPYRIGHT
+
+Copyright 2023 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License").  You may not use
+this file except in compliance with the License.  You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
index aab5533f5e5e60fe70c7dd3251943a906e989bfa..c4c19a98b54562bd0f9c54d5b53e4cc19e262046 100644 (file)
@@ -135,7 +135,7 @@ to create an IPv4 TCP socket:
 
     int sock;
 
-    sock = socket(AF_INET, SOCK_STEAM, 0);
+    sock = socket(AF_INET, SOCK_STREAM, 0);
     if (sock == -1)
         return NULL;
 
@@ -543,6 +543,11 @@ of its intermediate CA certificates) in our trusted certificate store (e.g.
 because the trusted certificate store is misconfigured, or there are missing
 intermediate CAs, or the issuer is simply unrecognised).
 
+=head1 FURTHER READING
+
+See L<ossl-guide-quic-client-block(7)> to read a tutorial on how to modify the
+client developed on this page to support QUIC instead of TLS.
+
 =head1 SEE ALSO
 
 L<crypto(7)>, L<ossl-guide-tls-introduction(7)>
index 925cc69737d8aaa072f1bc30005ddad8761c56ef..307b5eec91416b90ab866051f64792b85b9d5067 100644 (file)
@@ -297,10 +297,12 @@ object.
 
 See L<ossl-guide-tls-client-block(7)> to see an example of applying these
 concepts in order to write a simple TLS client based on a blocking socket.
+See L<ossl-guide-quic-introduction(7)> for an introduction to QUIC in OpenSSL.
 
 =head1 SEE ALSO
 
-L<crypto(7)>, L<ossl-guide-tls-client-block(7)>
+L<crypto(7)>, L<ossl-guide-tls-client-block(7)>,
+L<ossl-guide-quic-introduction(7)>
 
 =head1 COPYRIGHT