904d351
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
904d351
From: Javier Martinez Canillas <javierm@redhat.com>
904d351
Date: Thu, 5 Mar 2020 16:21:58 +0100
904d351
Subject: [PATCH] efi/http: Enclose literal IPv6 addresses in square brackets
904d351
904d351
According to RFC 2732 (https://www.ietf.org/rfc/rfc2732.txt), literal IPv6
904d351
addresses must be enclosed in square brackets. But GRUB currently does not
904d351
do this and is causing HTTP servers to send Bad Request (400) responses.
904d351
904d351
For example, the following is the HTTP stream when fetching a config file:
904d351
904d351
HEAD /EFI/BOOT/grub.cfg HTTP/1.1
904d351
Host: 2000:dead:beef:a::1
904d351
Accept: */*
904d351
User-Agent: UefiHttpBoot/1.0
904d351
904d351
HTTP/1.1 400 Bad Request
904d351
Date: Thu, 05 Mar 2020 14:46:02 GMT
904d351
Server: Apache/2.4.41 (Fedora) OpenSSL/1.1.1d
904d351
Connection: close
904d351
Content-Type: text/html; charset=iso-8859-1
904d351
904d351
and after enclosing the IPv6 address the HTTP request is successful:
904d351
904d351
HEAD /EFI/BOOT/grub.cfg HTTP/1.1
904d351
Host: [2000:dead:beef:a::1]
904d351
Accept: */*
904d351
User-Agent: UefiHttpBoot/1.0
904d351
904d351
HTTP/1.1 200 OK
904d351
Date: Thu, 05 Mar 2020 14:48:04 GMT
904d351
Server: Apache/2.4.41 (Fedora) OpenSSL/1.1.1d
904d351
Last-Modified: Thu, 27 Feb 2020 17:45:58 GMT
904d351
ETag: "206-59f924b24b1da"
904d351
Accept-Ranges: bytes
904d351
Content-Length: 518
904d351
904d351
Resolves: rhbz#1732765
904d351
904d351
Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
904d351
---
904d351
 grub-core/net/efi/http.c | 37 ++++++++++++++++++++++++++++---------
904d351
 1 file changed, 28 insertions(+), 9 deletions(-)
904d351
904d351
diff --git a/grub-core/net/efi/http.c b/grub-core/net/efi/http.c
e622855
index 755b7a6d05..fc8cb25ae0 100644
904d351
--- a/grub-core/net/efi/http.c
904d351
+++ b/grub-core/net/efi/http.c
904d351
@@ -158,13 +158,7 @@ efihttp_request (grub_efi_http_t *http, char *server, char *name, int use_https,
904d351
   grub_efi_status_t status;
904d351
   grub_efi_boot_services_t *b = grub_efi_system_table->boot_services;
904d351
   char *url = NULL;
904d351
-
904d351
-  request_headers[0].field_name = (grub_efi_char8_t *)"Host";
904d351
-  request_headers[0].field_value = (grub_efi_char8_t *)server;
904d351
-  request_headers[1].field_name = (grub_efi_char8_t *)"Accept";
904d351
-  request_headers[1].field_value = (grub_efi_char8_t *)"*/*";
904d351
-  request_headers[2].field_name = (grub_efi_char8_t *)"User-Agent";
904d351
-  request_headers[2].field_value = (grub_efi_char8_t *)"UefiHttpBoot/1.0";
904d351
+  char *hostname = NULL;
904d351
 
904d351
   {
904d351
     grub_efi_ipv6_address_t address;
904d351
@@ -174,9 +168,24 @@ efihttp_request (grub_efi_http_t *http, char *server, char *name, int use_https,
904d351
     const char *protocol = (use_https == 1) ? "https" : "http";
904d351
 
904d351
     if (grub_efi_string_to_ip6_address (server, &address, &rest) && *rest == 0)
904d351
-      url = grub_xasprintf ("%s://[%s]%s", protocol, server, name);
904d351
+      {
904d351
+        hostname = grub_xasprintf ("[%s]", server);
904d351
+        if (!hostname)
904d351
+          return GRUB_ERR_OUT_OF_MEMORY;
904d351
+
904d351
+        server = hostname;
904d351
+
904d351
+        url = grub_xasprintf ("%s://%s%s", protocol, server, name);
904d351
+        if (!url)
904d351
+          {
904d351
+            grub_free (hostname);
904d351
+            return GRUB_ERR_OUT_OF_MEMORY;
904d351
+          }
904d351
+      }
904d351
     else
904d351
-      url = grub_xasprintf ("%s://%s%s", protocol, server, name);
904d351
+      {
904d351
+        url = grub_xasprintf ("%s://%s%s", protocol, server, name);
904d351
+      }
904d351
 
904d351
     if (!url)
904d351
       {
904d351
@@ -199,6 +208,13 @@ efihttp_request (grub_efi_http_t *http, char *server, char *name, int use_https,
904d351
     request_data.url = ucs2_url;
904d351
   }
904d351
 
904d351
+  request_headers[0].field_name = (grub_efi_char8_t *)"Host";
904d351
+  request_headers[0].field_value = (grub_efi_char8_t *)server;
904d351
+  request_headers[1].field_name = (grub_efi_char8_t *)"Accept";
904d351
+  request_headers[1].field_value = (grub_efi_char8_t *)"*/*";
904d351
+  request_headers[2].field_name = (grub_efi_char8_t *)"User-Agent";
904d351
+  request_headers[2].field_value = (grub_efi_char8_t *)"UefiHttpBoot/1.0";
904d351
+
904d351
   request_data.method = (headeronly > 0) ? GRUB_EFI_HTTPMETHODHEAD : GRUB_EFI_HTTPMETHODGET;
904d351
 
904d351
   request_message.data.request = &request_data;
904d351
@@ -228,6 +244,9 @@ efihttp_request (grub_efi_http_t *http, char *server, char *name, int use_https,
904d351
 
904d351
   status = efi_call_2 (http->request, http, &request_token);
904d351
 
904d351
+  if (hostname)
904d351
+    grub_free (hostname);
904d351
+
904d351
   if (status != GRUB_EFI_SUCCESS)
904d351
     {
904d351
       efi_call_1 (b->close_event, request_token.event);