]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[uri] Allow for relative URIs that include colons within the path 555/head
authorMichael Brown <mcb30@ipxe.org>
Thu, 13 Jan 2022 14:53:36 +0000 (14:53 +0000)
committerMichael Brown <mcb30@ipxe.org>
Thu, 13 Jan 2022 15:03:22 +0000 (15:03 +0000)
RFC3986 allows for colons to appear within the path component of a
relative URI, but iPXE will currently parse such URIs incorrectly by
interpreting the text before the colon as the URI scheme.

Fix by checking for valid characters when identifying the URI scheme.
Deliberately deviate from the RFC3986 definition of valid characters
by accepting "_" (which was incorrectly used in the iPXE-specific
"ib_srp" URI scheme and so must be accepted for compatibility with
existing deployments), and by omitting the code to check for
characters that are not used in any URI scheme supported by iPXE.

Reported-by: Ignat Korchagin <ignat@cloudflare.com>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
src/core/uri.c
src/tests/uri_test.c

index a0f79e9ec11e1fda13774df3f45e3990901389e6..b82472ef03b3fb359d121ef45e9a6e920505f5b8 100644 (file)
@@ -334,8 +334,15 @@ struct uri * parse_uri ( const char *uri_string ) {
                uri->efragment = tmp;
        }
 
-       /* Identify absolute/relative URI */
-       if ( ( tmp = strchr ( raw, ':' ) ) ) {
+       /* Identify absolute URIs */
+       epath = raw;
+       for ( tmp = raw ; ; tmp++ ) {
+               /* Possible scheme character (for our URI schemes) */
+               if ( isalpha ( *tmp ) || ( *tmp == '-' ) || ( *tmp == '_' ) )
+                       continue;
+               /* Invalid scheme character or NUL: is a relative URI */
+               if ( *tmp != ':' )
+                       break;
                /* Absolute URI: identify hierarchical/opaque */
                uri->scheme = raw;
                *(tmp++) = '\0';
@@ -347,9 +354,7 @@ struct uri * parse_uri ( const char *uri_string ) {
                        uri->opaque = tmp;
                        epath = NULL;
                }
-       } else {
-               /* Relative URI */
-               epath = raw;
+               break;
        }
 
        /* If we don't have a path (i.e. we have an absolute URI with
index 929ab3632502e0f722dc496b0049c835af492f3e..338f479cd3778d3f20e0a526c9029145f847fc03 100644 (file)
@@ -657,6 +657,15 @@ static struct uri_test uri_file_volume = {
        },
 };
 
+/** Relative URI with colons in path */
+static struct uri_test uri_colons = {
+       "/boot/52:54:00:12:34:56/boot.ipxe",
+       {
+               .path = "/boot/52:54:00:12:34:56/boot.ipxe",
+               .epath = "/boot/52:54:00:12:34:56/boot.ipxe",
+       },
+};
+
 /** URI with port number */
 static struct uri_port_test uri_explicit_port = {
        "http://192.168.0.1:8080/boot.php",
@@ -957,6 +966,7 @@ static void uri_test_exec ( void ) {
        uri_parse_format_dup_ok ( &uri_file_relative );
        uri_parse_format_dup_ok ( &uri_file_absolute );
        uri_parse_format_dup_ok ( &uri_file_volume );
+       uri_parse_format_dup_ok ( &uri_colons );
 
        /** URI port number tests */
        uri_port_ok ( &uri_explicit_port );