public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
* [edk2-staging/HttpProxy PATCH v3 0/7] Support HTTPS Proxy Server for HTTP Boot
@ 2022-12-02 19:12 Saloni Kasbekar
  2022-12-02 19:12 ` [edk2-staging/HttpProxy PATCH v3 1/7] MdeModulePkg/Library: Support multi-URI HTTP Boot device path Saloni Kasbekar
                   ` (6 more replies)
  0 siblings, 7 replies; 8+ messages in thread
From: Saloni Kasbekar @ 2022-12-02 19:12 UTC (permalink / raw)
  To: devel; +Cc: Saloni Kasbekar

REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3951
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4052

- Add CONNECT HTTP Method to create a tunnel through the Proxy Server
- TLS adjustments to establish handshake with the Endpoint Server
- Use multi-URI device path to support Proxy Server URI as a 
  part of the Http Boot Device Path
- Add Proxy URI field in the setup menu

Saloni Kasbekar (7):
  MdeModulePkg/Library: Support multi-URI HTTP Boot device path
  MdePkg/Include: Add Proxy Server URL in EFI_HTTP_REQUEST_DATA
  NetworkPkg/HttpBootDxe: Update HTTP Boot Driver with parsed Proxy URL
  NetworkPkg: Add Proxy Support to HTTP_PROTOCOL
  NetworkPkg: Add support for HTTP CONNECT Method
  NetworkPkg/HttpDxe: Support HTTPS EndPoint server with Proxy
  NetworkPkg/HttpBootDxe: Add Proxy URI input in setup menu

 .../Library/UefiBootManagerLib/BmBoot.c       |  28 ++
 .../UefiBootManagerLib/BmBootDescription.c    |   4 +-
 MdePkg/Include/Protocol/Http.h                |  10 +-
 NetworkPkg/HttpBootDxe/HttpBootClient.c       | 206 ++++++++++++++-
 NetworkPkg/HttpBootDxe/HttpBootClient.h       |  15 ++
 NetworkPkg/HttpBootDxe/HttpBootConfig.c       |  99 +++++--
 .../HttpBootDxe/HttpBootConfigNVDataStruc.h   |   4 +-
 .../HttpBootDxe/HttpBootConfigStrings.uni     |   2 +
 NetworkPkg/HttpBootDxe/HttpBootConfigVfr.vfr  |   9 +
 NetworkPkg/HttpBootDxe/HttpBootDxe.h          |   6 +
 NetworkPkg/HttpBootDxe/HttpBootImpl.c         | 249 ++++++++++++------
 NetworkPkg/HttpBootDxe/HttpBootImpl.h         |   8 +
 NetworkPkg/HttpBootDxe/HttpBootSupport.c      | 154 ++++++++---
 NetworkPkg/HttpBootDxe/HttpBootSupport.h      |  13 +-
 NetworkPkg/HttpDxe/HttpDriver.h               |   2 +
 NetworkPkg/HttpDxe/HttpDxe.inf                |   1 +
 NetworkPkg/HttpDxe/HttpImpl.c                 | 215 +++++++++++----
 NetworkPkg/HttpDxe/HttpProto.c                |  58 ++--
 NetworkPkg/HttpDxe/HttpProto.h                |  17 +-
 NetworkPkg/HttpDxe/HttpsSupport.c             |  16 +-
 NetworkPkg/Library/DxeHttpLib/DxeHttpLib.c    |   5 +
 21 files changed, 893 insertions(+), 228 deletions(-)

-- 
2.36.1.windows.1


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [edk2-staging/HttpProxy PATCH v3 1/7] MdeModulePkg/Library: Support multi-URI HTTP Boot device path
  2022-12-02 19:12 [edk2-staging/HttpProxy PATCH v3 0/7] Support HTTPS Proxy Server for HTTP Boot Saloni Kasbekar
@ 2022-12-02 19:12 ` Saloni Kasbekar
  2022-12-02 19:12 ` [edk2-staging/HttpProxy PATCH v3 2/7] MdePkg/Include: Add Proxy Server URL in EFI_HTTP_REQUEST_DATA Saloni Kasbekar
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Saloni Kasbekar @ 2022-12-02 19:12 UTC (permalink / raw)
  To: devel; +Cc: Saloni Kasbekar, Jian J Wang, Liming Gao, Maciej Rabeda

REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3951

Process device path with proxy server and endpoint server included.
Update comment for sample HTTP Boot device path.

Cc: Jian J Wang <jian.j.wang@intel.com>
Cc: Liming Gao <gaoliming@byosoft.com.cn>
Cc: Maciej Rabeda <maciej.rabeda@linux.intel.com>
Signed-off-by: Saloni Kasbekar <saloni.kasbekar@intel.com>
---
 .../Library/UefiBootManagerLib/BmBoot.c       | 28 +++++++++++++++++++
 .../UefiBootManagerLib/BmBootDescription.c    |  4 +--
 2 files changed, 30 insertions(+), 2 deletions(-)

diff --git a/MdeModulePkg/Library/UefiBootManagerLib/BmBoot.c b/MdeModulePkg/Library/UefiBootManagerLib/BmBoot.c
index 962892d38f..fdef1ba292 100644
--- a/MdeModulePkg/Library/UefiBootManagerLib/BmBoot.c
+++ b/MdeModulePkg/Library/UefiBootManagerLib/BmBoot.c
@@ -1513,6 +1513,9 @@ BmExpandLoadFiles (
   UINTN                     HandleCount;
   UINTN                     Index;
   EFI_DEVICE_PATH_PROTOCOL  *Node;
+  URI_DEVICE_PATH           *NullUriPath;
+
+  NullUriPath = NULL;
 
   //
   // Get file buffer from load file instance.
@@ -1545,11 +1548,36 @@ BmExpandLoadFiles (
 
     for (Index = 0; Index < HandleCount; Index++) {
       if (BmMatchHttpBootDevicePath (DevicePathFromHandle (Handles[Index]), FilePath)) {
+        //
+        // Matches HTTP Boot Device Path described as
+        //   ....../Mac(...)[/Vlan(...)][/Wi-Fi(...)]/IPv4(...)[/Dns(...)]/Uri(...)
+        //   ....../Mac(...)[/Vlan(...)][/Wi-Fi(...)]/IPv6(...)[/Dns(...)]/Uri(...)
+        //
+        Handle = Handles[Index];
+        goto Done;
+      }
+    }
+
+    NullUriPath = (URI_DEVICE_PATH *)CreateDeviceNode (
+                                       MESSAGING_DEVICE_PATH,
+                                       MSG_URI_DP,
+                                       (UINT16)(sizeof (URI_DEVICE_PATH))
+                                       );
+    for (Index = 0; Index < HandleCount; Index++) {
+      if (BmMatchHttpBootDevicePath (AppendDevicePathNode (DevicePathFromHandle (Handles[Index]), (EFI_DEVICE_PATH_PROTOCOL *)NullUriPath), FilePath)) {
+        //
+        // Matches HTTP Boot Device Path described as
+        //   ....../Mac(...)[/Vlan(...)][/Wi-Fi(...)]/IPv4(...)[/Dns(...)]/Uri(...)/Uri(...)
+        //   ....../Mac(...)[/Vlan(...)][/Wi-Fi(...)]/IPv6(...)[/Dns(...)]/Uri(...)/Uri(...)
+        //
         Handle = Handles[Index];
         break;
       }
     }
 
+    FreePool (NullUriPath);
+
+Done:
     if (Handles != NULL) {
       FreePool (Handles);
     }
diff --git a/MdeModulePkg/Library/UefiBootManagerLib/BmBootDescription.c b/MdeModulePkg/Library/UefiBootManagerLib/BmBootDescription.c
index fac33b9ee9..108efd8096 100644
--- a/MdeModulePkg/Library/UefiBootManagerLib/BmBootDescription.c
+++ b/MdeModulePkg/Library/UefiBootManagerLib/BmBootDescription.c
@@ -412,8 +412,8 @@ BmGetNetworkDescription (
   //   ....../Mac(...)[/Vlan(...)][/Wi-Fi(...)]/IPv6(...)
   //
   // The HTTP device path is like:
-  //   ....../Mac(...)[/Vlan(...)][/Wi-Fi(...)]/IPv4(...)[/Dns(...)]/Uri(...)
-  //   ....../Mac(...)[/Vlan(...)][/Wi-Fi(...)]/IPv6(...)[/Dns(...)]/Uri(...)
+  //   ....../Mac(...)[/Vlan(...)][/Wi-Fi(...)]/IPv4(...)[/Dns(...)][/Uri(...)]/Uri(...)
+  //   ....../Mac(...)[/Vlan(...)][/Wi-Fi(...)]/IPv6(...)[/Dns(...)][/Uri(...)]/Uri(...)
   //
   while (!IsDevicePathEnd (DevicePath) &&
          ((DevicePathType (DevicePath) != MESSAGING_DEVICE_PATH) ||
-- 
2.36.1.windows.1


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [edk2-staging/HttpProxy PATCH v3 2/7] MdePkg/Include: Add Proxy Server URL in EFI_HTTP_REQUEST_DATA
  2022-12-02 19:12 [edk2-staging/HttpProxy PATCH v3 0/7] Support HTTPS Proxy Server for HTTP Boot Saloni Kasbekar
  2022-12-02 19:12 ` [edk2-staging/HttpProxy PATCH v3 1/7] MdeModulePkg/Library: Support multi-URI HTTP Boot device path Saloni Kasbekar
@ 2022-12-02 19:12 ` Saloni Kasbekar
  2022-12-02 19:12 ` [edk2-staging/HttpProxy PATCH v3 3/7] NetworkPkg/HttpBootDxe: Update HTTP Boot Driver with parsed Proxy URL Saloni Kasbekar
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Saloni Kasbekar @ 2022-12-02 19:12 UTC (permalink / raw)
  To: devel
  Cc: Saloni Kasbekar, Zhiguang Liu, Michael D Kinney, Liming Gao,
	Maciej Rabeda

REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3951

Add Proxy Server URL to EFI_HTTP_REQUEST_DATA.
This will be used when a Proxy Server URL is a part of the
HTTP Boot device path.

Cc: Zhiguang Liu <zhiguang.liu@intel.com>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Liming Gao <gaoliming@byosoft.com.cn>
Cc: Maciej Rabeda <maciej.rabeda@linux.intel.com>
Signed-off-by: Saloni Kasbekar <saloni.kasbekar@intel.com>
---
 MdePkg/Include/Protocol/Http.h | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/MdePkg/Include/Protocol/Http.h b/MdePkg/Include/Protocol/Http.h
index 28e6221593..9ee08baa14 100644
--- a/MdePkg/Include/Protocol/Http.h
+++ b/MdePkg/Include/Protocol/Http.h
@@ -188,9 +188,17 @@ typedef struct {
   /// The URI of a remote host. From the information in this field, the HTTP instance
   /// will be able to determine whether to use HTTP or HTTPS and will also be able to
   /// determine the port number to use. If no port number is specified, port 80 (HTTP)
-  /// is assumed. See RFC 3986 for more details on URI syntax.
+  /// or 443 (HTTPS) is assumed. See RFC 3986 for more details on URI syntax.
   ///
   CHAR16             *Url;
+  ///
+  /// The URI of an Proxy Host. This field will be NULL if there is no Proxy Host
+  /// in the device path. From the information in this field, the HTTP instance will
+  /// be able to determine whether to use HTTP or HTTPS and will also be able to
+  /// determine the port number to use. If no port number is specified, port 80 (HTTP)
+  /// or 443 (HTTPS) is assumed. See RFC 3986 for more details on URI syntax.
+  ///
+  CHAR16             *ProxyUrl;
 } EFI_HTTP_REQUEST_DATA;
 
 ///
-- 
2.36.1.windows.1


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [edk2-staging/HttpProxy PATCH v3 3/7] NetworkPkg/HttpBootDxe: Update HTTP Boot Driver with parsed Proxy URL
  2022-12-02 19:12 [edk2-staging/HttpProxy PATCH v3 0/7] Support HTTPS Proxy Server for HTTP Boot Saloni Kasbekar
  2022-12-02 19:12 ` [edk2-staging/HttpProxy PATCH v3 1/7] MdeModulePkg/Library: Support multi-URI HTTP Boot device path Saloni Kasbekar
  2022-12-02 19:12 ` [edk2-staging/HttpProxy PATCH v3 2/7] MdePkg/Include: Add Proxy Server URL in EFI_HTTP_REQUEST_DATA Saloni Kasbekar
@ 2022-12-02 19:12 ` Saloni Kasbekar
  2022-12-02 19:12 ` [edk2-staging/HttpProxy PATCH v3 4/7] NetworkPkg: Add Proxy Support to HTTP_PROTOCOL Saloni Kasbekar
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Saloni Kasbekar @ 2022-12-02 19:12 UTC (permalink / raw)
  To: devel; +Cc: Saloni Kasbekar, Maciej Rabeda, Wu Jiaxin, Siyuan Fu

REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3951

Add ProxyUri to HTTP_BOOT_PRIVATE_DATA
Parse HTTP Boot Device path to process Proxy and EndPoint URLs

Cc: Maciej Rabeda <maciej.rabeda@linux.intel.com>
Cc: Wu Jiaxin <jiaxin.wu@intel.com>
Cc: Siyuan Fu <siyuan.fu@intel.com>
Signed-off-by: Saloni Kasbekar <saloni.kasbekar@intel.com>
---
 NetworkPkg/HttpBootDxe/HttpBootClient.c  |  30 ++++-
 NetworkPkg/HttpBootDxe/HttpBootDxe.h     |   6 +
 NetworkPkg/HttpBootDxe/HttpBootImpl.c    |  57 +++++----
 NetworkPkg/HttpBootDxe/HttpBootSupport.c | 154 +++++++++++++++++------
 NetworkPkg/HttpBootDxe/HttpBootSupport.h |  13 +-
 5 files changed, 189 insertions(+), 71 deletions(-)

diff --git a/NetworkPkg/HttpBootDxe/HttpBootClient.c b/NetworkPkg/HttpBootDxe/HttpBootClient.c
index 40f64fcb6b..b13155b576 100644
--- a/NetworkPkg/HttpBootDxe/HttpBootClient.c
+++ b/NetworkPkg/HttpBootDxe/HttpBootClient.c
@@ -678,6 +678,10 @@ HttpBootFreeCache (
         FreePool (Cache->RequestData->Url);
       }
 
+      if (Cache->RequestData->ProxyUrl != NULL) {
+        FreePool (Cache->RequestData->ProxyUrl);
+      }
+
       FreePool (Cache->RequestData);
     }
 
@@ -950,6 +954,7 @@ HttpBootGetBootFile (
   UINT8                    *Block;
   UINTN                    UrlSize;
   CHAR16                   *Url;
+  CHAR16                   *ProxyUrl;
   BOOLEAN                  IdentityMode;
   UINTN                    ReceivedSize;
   CHAR8                    BaseAuthValue[80];
@@ -989,6 +994,22 @@ HttpBootGetBootFile (
   // Not found in cache, try to download it through HTTP.
   //
 
+  //
+  // Initialize ProxyUrl - Set to NULL if connecting without Proxy
+  //
+  if (Private->ProxyUri != NULL) {
+    UrlSize  = AsciiStrSize (Private->ProxyUri);
+    ProxyUrl = AllocatePool (UrlSize * (sizeof (CHAR16)));
+    if (ProxyUrl == NULL) {
+      Status = EFI_OUT_OF_RESOURCES;
+      goto ERROR_1;
+    }
+
+    AsciiStrToUnicodeStrS (Private->ProxyUri, ProxyUrl, UrlSize);
+  } else {
+    ProxyUrl = NULL;
+  }
+
   //
   // 1. Create a temp cache item for the requested URI if caller doesn't provide buffer.
   //
@@ -1106,8 +1127,9 @@ HttpBootGetBootFile (
     goto ERROR_3;
   }
 
-  RequestData->Method = HeaderOnly ? HttpMethodHead : HttpMethodGet;
-  RequestData->Url    = Url;
+  RequestData->Method   = HeaderOnly ? HttpMethodHead : HttpMethodGet;
+  RequestData->Url      = Url;
+  RequestData->ProxyUrl = ProxyUrl;
 
   //
   // 2.3 Record the request info in a temp cache item.
@@ -1441,6 +1463,10 @@ ERROR_2:
   }
 
 ERROR_1:
+  if (ProxyUrl != NULL) {
+    FreePool (ProxyUrl);
+  }
+
   if (Url != NULL) {
     FreePool (Url);
   }
diff --git a/NetworkPkg/HttpBootDxe/HttpBootDxe.h b/NetworkPkg/HttpBootDxe/HttpBootDxe.h
index 5ff8ad4698..8caf2e9a45 100644
--- a/NetworkPkg/HttpBootDxe/HttpBootDxe.h
+++ b/NetworkPkg/HttpBootDxe/HttpBootDxe.h
@@ -223,6 +223,12 @@ struct _HTTP_BOOT_PRIVATE_DATA {
   CHAR8                                        *FilePathUri;
   VOID                                         *FilePathUriParser;
 
+  //
+  // URI string for the Proxy host if BootFileUri contains a Proxy
+  // URI in the path
+  //
+  CHAR8                                        *ProxyUri;
+
   //
   // Cached HTTP data
   //
diff --git a/NetworkPkg/HttpBootDxe/HttpBootImpl.c b/NetworkPkg/HttpBootDxe/HttpBootImpl.c
index b4c61925b9..5735b96d9e 100644
--- a/NetworkPkg/HttpBootDxe/HttpBootImpl.c
+++ b/NetworkPkg/HttpBootDxe/HttpBootImpl.c
@@ -115,19 +115,21 @@ HttpBootStart (
 {
   UINTN       Index;
   EFI_STATUS  Status;
-  CHAR8       *Uri;
+  CHAR8       *ProxyUri;
+  CHAR8       *EndPointUri;
 
-  Uri = NULL;
+  ProxyUri    = NULL;
+  EndPointUri = NULL;
 
   if ((Private == NULL) || (FilePath == NULL)) {
     return EFI_INVALID_PARAMETER;
   }
 
   //
-  // Check the URI in the input FilePath, in order to see whether it is
+  // Check the URIs in the input FilePath, in order to see whether it is
   // required to boot from a new specified boot file.
   //
-  Status = HttpBootParseFilePath (FilePath, &Uri);
+  Status = HttpBootParseFilePath (FilePath, &ProxyUri, &EndPointUri);
   if (EFI_ERROR (Status)) {
     return EFI_INVALID_PARAMETER;
   }
@@ -143,28 +145,21 @@ HttpBootStart (
     // recorded before.
     //
     if ((UsingIpv6 != Private->UsingIpv6) ||
-        ((Uri != NULL) && (AsciiStrCmp (Private->BootFileUri, Uri) != 0)))
+        ((EndPointUri != NULL) && (AsciiStrCmp (Private->BootFileUri, EndPointUri) != 0)))
     {
       //
       // Restart is required, first stop then continue this start function.
       //
       Status = HttpBootStop (Private);
       if (EFI_ERROR (Status)) {
-        if (Uri != NULL) {
-          FreePool (Uri);
-        }
-
-        return Status;
+        goto ERROR;
       }
     } else {
       //
       // Restart is not required.
       //
-      if (Uri != NULL) {
-        FreePool (Uri);
-      }
-
-      return EFI_ALREADY_STARTED;
+      Status = EFI_ALREADY_STARTED;
+      goto ERROR;
     }
   }
 
@@ -176,17 +171,16 @@ HttpBootStart (
   } else if (!UsingIpv6 && (Private->Ip4Nic != NULL)) {
     Private->UsingIpv6 = FALSE;
   } else {
-    if (Uri != NULL) {
-      FreePool (Uri);
-    }
-
-    return EFI_UNSUPPORTED;
+    Status = EFI_UNSUPPORTED;
+    goto ERROR;
   }
 
   //
-  // Record the specified URI and prepare the URI parser if needed.
+  // Record the specified URIs and prepare the URI parser if needed.
   //
-  Private->FilePathUri = Uri;
+  Private->ProxyUri    = ProxyUri;
+  Private->FilePathUri = EndPointUri;
+
   if (Private->FilePathUri != NULL) {
     Status = HttpParseUrl (
                Private->FilePathUri,
@@ -195,8 +189,7 @@ HttpBootStart (
                &Private->FilePathUriParser
                );
     if (EFI_ERROR (Status)) {
-      FreePool (Private->FilePathUri);
-      return Status;
+      goto ERROR;
     }
   }
 
@@ -228,6 +221,17 @@ HttpBootStart (
   Print (L"\n>>Start HTTP Boot over IPv%d", Private->UsingIpv6 ? 6 : 4);
 
   return EFI_SUCCESS;
+
+ERROR:
+  if (ProxyUri != NULL) {
+    FreePool (ProxyUri);
+  }
+
+  if (EndPointUri != NULL) {
+    FreePool (EndPointUri);
+  }
+
+  return Status;
 }
 
 /**
@@ -522,6 +526,11 @@ HttpBootStop (
     Private->FilePathUriParser = NULL;
   }
 
+  if (Private->ProxyUri != NULL) {
+    FreePool (Private->ProxyUri);
+    Private->ProxyUri = NULL;
+  }
+
   ZeroMem (Private->OfferBuffer, sizeof (Private->OfferBuffer));
   Private->OfferNum = 0;
   ZeroMem (Private->OfferCount, sizeof (Private->OfferCount));
diff --git a/NetworkPkg/HttpBootDxe/HttpBootSupport.c b/NetworkPkg/HttpBootDxe/HttpBootSupport.c
index 236ef25931..9af6cf0c69 100644
--- a/NetworkPkg/HttpBootDxe/HttpBootSupport.c
+++ b/NetworkPkg/HttpBootDxe/HttpBootSupport.c
@@ -551,71 +551,145 @@ HttpBootCheckUriScheme (
   return Status;
 }
 
+/**
+  Get the URI address string from the URI device path node.
+
+  Caller need to free the buffer in the Uri pointer.
+
+  @param[in]   Node               Pointer to the URI device path node.
+  @param[out]  Uri                URI string extracted from the device path.
+
+  @retval EFI_SUCCESS            The URI string is returned.
+  @retval EFI_INVALID_PARAMETER  Parameters are NULL or invalid URI node.
+  @retval EFI_OUT_OF_RESOURCES   Failed to allocate memory.
+
+**/
+EFI_STATUS
+HttpBootUriFromDevicePath (
+  IN    URI_DEVICE_PATH  *Node,
+  OUT   CHAR8            **Uri
+  )
+{
+  UINTN  UriStrLength;
+
+  if ((Node == NULL) || (Uri == NULL)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  UriStrLength = DevicePathNodeLength (Node) - sizeof (EFI_DEVICE_PATH_PROTOCOL);
+
+  if (UriStrLength == 0) {
+    // Invalid URI, return.
+    return EFI_INVALID_PARAMETER;
+  }
+
+  *Uri = AllocatePool (UriStrLength + 1);
+  if (*Uri == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  CopyMem (*Uri, Node->Uri, UriStrLength);
+  (*Uri)[UriStrLength] = '\0';
+
+  return EFI_SUCCESS;
+}
+
 /**
   Get the URI address string from the input device path.
 
-  Caller need to free the buffer in the UriAddress pointer.
+  Caller needs to free the buffers returned by this function.
 
-  @param[in]   FilePath         Pointer to the device path which contains a URI device path node.
-  @param[out]  UriAddress       The URI address string extract from the device path.
+  @param[in]   FilePath           Pointer to the device path which contains a URI device path node.
+  @param[out]  ProxyUriAddress    The proxy URI address string extract from the device path (if it exists)
+  @param[out]  EndPointUriAddress The endpoint URI address string for the endpoint host.
 
   @retval EFI_SUCCESS            The URI string is returned.
+  @retval EFI_INVALID_PARAMETER  Parameters are NULL or device path is invalid.
   @retval EFI_OUT_OF_RESOURCES   Failed to allocate memory.
 
 **/
 EFI_STATUS
 HttpBootParseFilePath (
-  IN     EFI_DEVICE_PATH_PROTOCOL  *FilePath,
-  OUT CHAR8                        **UriAddress
+  IN  EFI_DEVICE_PATH_PROTOCOL  *FilePath,
+  OUT CHAR8                     **ProxyUriAddress,
+  OUT CHAR8                     **EndPointUriAddress
   )
 {
-  EFI_DEVICE_PATH_PROTOCOL  *TempDevicePath;
-  URI_DEVICE_PATH           *UriDevicePath;
-  CHAR8                     *Uri;
-  UINTN                     UriStrLength;
-
-  if (FilePath == NULL) {
+  EFI_STATUS                Status;
+  EFI_DEVICE_PATH_PROTOCOL  *Node[2];
+  EFI_DEVICE_PATH_PROTOCOL  *TempNode;
+  BOOLEAN                   NodeIsUri[2];
+  UINTN                     Index;
+
+  if ((FilePath == NULL) ||
+      (ProxyUriAddress == NULL) ||
+      (EndPointUriAddress == NULL))
+  {
     return EFI_INVALID_PARAMETER;
   }
 
-  *UriAddress = NULL;
+  *ProxyUriAddress    = NULL;
+  *EndPointUriAddress = NULL;
+  ZeroMem (Node, sizeof (Node));
 
+  // Obtain last 2 device path nodes.
+  // Looking for sequences:
+  // 1) //....../Mac(...)[/Vlan(...)][/Wi-Fi(...)]/IPv6(...)[/Dns(...)]/Uri(ProxyServer)/Uri(EndPointServer/FilePath)
+  // 2) //....../Mac(...)[/Vlan(...)][/Wi-Fi(...)]/IPv6(...)[/Dns(...)]/Uri(EndPointServer/FilePath)
   //
-  // Extract the URI address from the FilePath
-  //
-  TempDevicePath = FilePath;
-  while (!IsDevicePathEnd (TempDevicePath)) {
-    if ((DevicePathType (TempDevicePath) == MESSAGING_DEVICE_PATH) &&
-        (DevicePathSubType (TempDevicePath) == MSG_URI_DP))
-    {
-      UriDevicePath = (URI_DEVICE_PATH *)TempDevicePath;
-      //
-      // UEFI Spec doesn't require the URI to be a NULL-terminated string
-      // So we allocate a new buffer and always append a '\0' to it.
-      //
-      UriStrLength = DevicePathNodeLength (UriDevicePath) - sizeof (EFI_DEVICE_PATH_PROTOCOL);
-      if (UriStrLength == 0) {
-        //
-        // return a NULL UriAddress if it's a empty URI device path node.
-        //
-        break;
-      }
-
-      Uri = AllocatePool (UriStrLength + 1);
-      if (Uri == NULL) {
-        return EFI_OUT_OF_RESOURCES;
-      }
+  // Expected:
+  // Node[1] - Uri(EndPointServer/FilePath)
+  // Node[0] - Either Uri(EndPointServer/FilePath) or other.
+  TempNode = FilePath;
+
+  while (!IsDevicePathEnd (TempNode)) {
+    Node[0]  = Node[1];
+    Node[1]  = TempNode;
+    TempNode = NextDevicePathNode (TempNode);
+  }
+
+  // Verify if device path nodes are of type MESSAGING + URI.
+  for (Index = 0; Index < 2; Index++) {
+    if (Node[Index] == NULL) {
+      NodeIsUri[Index] = FALSE;
+    } else {
+      NodeIsUri[Index] = ((DevicePathType (Node[Index]) == MESSAGING_DEVICE_PATH) &&
+                          (DevicePathSubType (Node[Index]) == MSG_URI_DP));
+    }
+  }
 
-      CopyMem (Uri, UriDevicePath->Uri, DevicePathNodeLength (UriDevicePath) - sizeof (EFI_DEVICE_PATH_PROTOCOL));
-      Uri[DevicePathNodeLength (UriDevicePath) - sizeof (EFI_DEVICE_PATH_PROTOCOL)] = '\0';
+  // If exists, obtain endpoint URI string.
+  if (NodeIsUri[1]) {
+    Status = HttpBootUriFromDevicePath (
+               (URI_DEVICE_PATH *)Node[1],
+               EndPointUriAddress
+               );
 
-      *UriAddress = Uri;
+    if (EFI_ERROR (Status)) {
+      return Status;
     }
 
-    TempDevicePath = NextDevicePathNode (TempDevicePath);
+    // If exists, obtain proxy URI string.
+    if (NodeIsUri[0]) {
+      Status = HttpBootUriFromDevicePath (
+                 (URI_DEVICE_PATH *)Node[0],
+                 ProxyUriAddress
+                 );
+
+      if (EFI_ERROR (Status)) {
+        goto ErrorExit;
+      }
+    }
   }
 
   return EFI_SUCCESS;
+
+ErrorExit:
+  ASSERT (*EndPointUriAddress != NULL);
+  FreePool (*EndPointUriAddress);
+  *EndPointUriAddress = NULL;
+
+  return Status;
 }
 
 /**
diff --git a/NetworkPkg/HttpBootDxe/HttpBootSupport.h b/NetworkPkg/HttpBootDxe/HttpBootSupport.h
index 3698e55936..5a46894517 100644
--- a/NetworkPkg/HttpBootDxe/HttpBootSupport.h
+++ b/NetworkPkg/HttpBootDxe/HttpBootSupport.h
@@ -136,19 +136,22 @@ HttpBootCheckUriScheme (
 /**
   Get the URI address string from the input device path.
 
-  Caller need to free the buffer in the UriAddress pointer.
+  Caller needs to free the buffers returned by this function.
 
-  @param[in]   FilePath         Pointer to the device path which contains a URI device path node.
-  @param[out]  UriAddress       The URI address string extract from the device path.
+  @param[in]   FilePath           Pointer to the device path which contains a URI device path node.
+  @param[out]  ProxyUriAddress    The proxy URI address string extract from the device path (if it exists)
+  @param[out]  EndPointUriAddress The endpoint URI address string for the endpoint host.
 
   @retval EFI_SUCCESS            The URI string is returned.
+  @retval EFI_INVALID_PARAMETER  Parameters are NULL or device path is invalid.
   @retval EFI_OUT_OF_RESOURCES   Failed to allocate memory.
 
 **/
 EFI_STATUS
 HttpBootParseFilePath (
-  IN     EFI_DEVICE_PATH_PROTOCOL  *FilePath,
-  OUT CHAR8                        **UriAddress
+  IN  EFI_DEVICE_PATH_PROTOCOL  *FilePath,
+  OUT CHAR8                     **ProxyUriAddress,
+  OUT CHAR8                     **EndPointUriAddress
   );
 
 /**
-- 
2.36.1.windows.1


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [edk2-staging/HttpProxy PATCH v3 4/7] NetworkPkg: Add Proxy Support to HTTP_PROTOCOL
  2022-12-02 19:12 [edk2-staging/HttpProxy PATCH v3 0/7] Support HTTPS Proxy Server for HTTP Boot Saloni Kasbekar
                   ` (2 preceding siblings ...)
  2022-12-02 19:12 ` [edk2-staging/HttpProxy PATCH v3 3/7] NetworkPkg/HttpBootDxe: Update HTTP Boot Driver with parsed Proxy URL Saloni Kasbekar
@ 2022-12-02 19:12 ` Saloni Kasbekar
  2022-12-02 19:12 ` [edk2-staging/HttpProxy PATCH v3 5/7] NetworkPkg: Add support for HTTP CONNECT Method Saloni Kasbekar
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Saloni Kasbekar @ 2022-12-02 19:12 UTC (permalink / raw)
  To: devel; +Cc: Saloni Kasbekar, Maciej Rabeda, Wu Jiaxin, Siyuan Fu

REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3951

Update HTTP Protocol with variables to support Proxy
Use state machine to call HttpBootGetBootFile()
Add switch/case for EfiHttpRequest request method

Cc: Maciej Rabeda <maciej.rabeda@linux.intel.com>
Cc: Wu Jiaxin <jiaxin.wu@intel.com>
Cc: Siyuan Fu <siyuan.fu@intel.com>
Signed-off-by: Saloni Kasbekar <saloni.kasbekar@intel.com>
---
 NetworkPkg/HttpBootDxe/HttpBootImpl.c | 178 +++++++++++++++++---------
 NetworkPkg/HttpBootDxe/HttpBootImpl.h |   7 +
 NetworkPkg/HttpDxe/HttpImpl.c         |  59 +++++++--
 NetworkPkg/HttpDxe/HttpProto.c        |  18 ++-
 NetworkPkg/HttpDxe/HttpProto.h        |   9 ++
 5 files changed, 199 insertions(+), 72 deletions(-)

diff --git a/NetworkPkg/HttpBootDxe/HttpBootImpl.c b/NetworkPkg/HttpBootDxe/HttpBootImpl.c
index 5735b96d9e..4748de0603 100644
--- a/NetworkPkg/HttpBootDxe/HttpBootImpl.c
+++ b/NetworkPkg/HttpBootDxe/HttpBootImpl.c
@@ -278,6 +278,122 @@ HttpBootDhcp (
   return Status;
 }
 
+/**
+  Issue calls to HttpBootGetBootFile() based on current Boot File State
+
+  @param[in]          Private         The pointer to the driver's private data.
+  @param[in, out]     BufferSize      On input the size of Buffer in bytes. On output with a return
+                                      code of EFI_SUCCESS, the amount of data transferred to
+                                      Buffer. On output with a return code of EFI_BUFFER_TOO_SMALL,
+                                      the size of Buffer required to retrieve the requested file.
+  @param[in]          Buffer          The memory buffer to transfer the file to. If Buffer is NULL,
+                                      then the size of the requested file is returned in
+                                      BufferSize.
+  @param[out]         ImageType       The image type of the downloaded file.
+
+  @retval EFI_SUCCESS              The file was loaded.
+  @retval EFI_INVALID_PARAMETER    BufferSize is NULL or Buffer Size is not NULL but Buffer is NULL.
+  @retval EFI_OUT_OF_RESOURCES     Could not allocate needed resources
+  @retval EFI_BUFFER_TOO_SMALL     The BufferSize is too small to read the current directory entry.
+                                   BufferSize has been updated with the size needed to complete
+                                   the request.
+  @retval EFI_ACCESS_DENIED        Server authentication failed.
+  @retval Others                   Unexpected error happened.
+
+**/
+EFI_STATUS
+HttpBootGetBootFileCaller (
+  IN     HTTP_BOOT_PRIVATE_DATA  *Private,
+  IN OUT UINTN                   *BufferSize,
+  IN     VOID                    *Buffer        OPTIONAL,
+  OUT HTTP_BOOT_IMAGE_TYPE       *ImageType
+  )
+{
+  HTTP_GET_BOOT_FILE_STATE  State;
+  EFI_STATUS                Status;
+
+  if (Private->BootFileSize == 0) {
+    State = GetBootFileHead;
+  } else {
+    State = LoadBootFile;
+  }
+
+  for ( ; ;) {
+    switch (State) {
+      case GetBootFileHead:
+        //
+        // Try to use HTTP HEAD method.
+        //
+        Status = HttpBootGetBootFile (
+                   Private,
+                   TRUE,
+                   &Private->BootFileSize,
+                   NULL,
+                   &Private->ImageType
+                   );
+        if ((EFI_ERROR (Status)) && (Status != EFI_BUFFER_TOO_SMALL)) {
+          if ((Private->AuthData != NULL) && (Status == EFI_ACCESS_DENIED)) {
+            //
+            // Try to use HTTP HEAD method again since the Authentication information is provided.
+            //
+            State = GetBootFileHead;
+          } else {
+            State = GetBootFileGet;
+          }
+        } else {
+          State = LoadBootFile;
+        }
+
+        break;
+
+      case GetBootFileGet:
+        //
+        // Failed to get file size by HEAD method, may be trunked encoding, try HTTP GET method.
+        //
+        ASSERT (Private->BootFileSize == 0);
+        Status = HttpBootGetBootFile (
+                   Private,
+                   FALSE,
+                   &Private->BootFileSize,
+                   NULL,
+                   &Private->ImageType
+                   );
+        if (EFI_ERROR (Status) && (Status != EFI_BUFFER_TOO_SMALL)) {
+          State = GetBootFileError;
+        } else {
+          State = LoadBootFile;
+        }
+
+        break;
+
+      case LoadBootFile:
+        if (*BufferSize < Private->BootFileSize) {
+          *BufferSize = Private->BootFileSize;
+          *ImageType  = Private->ImageType;
+          Status      = EFI_BUFFER_TOO_SMALL;
+          return Status;
+        }
+
+        //
+        // Load the boot file into Buffer
+        //
+        Status = HttpBootGetBootFile (
+                   Private,
+                   FALSE,
+                   BufferSize,
+                   Buffer,
+                   ImageType
+                   );
+        return Status;
+
+      case GetBootFileError:
+      default:
+        AsciiPrint ("\n  Error: Could not retrieve NBP file size from HTTP server.\n");
+        return Status;
+    }
+  }
+}
+
 /**
   Attempt to download the boot file through HTTP message exchange.
 
@@ -349,68 +465,10 @@ HttpBootLoadFile (
     }
   }
 
-  if (Private->BootFileSize == 0) {
-    //
-    // Discover the information about the bootfile if we haven't.
-    //
-
-    //
-    // Try to use HTTP HEAD method.
-    //
-    Status = HttpBootGetBootFile (
-               Private,
-               TRUE,
-               &Private->BootFileSize,
-               NULL,
-               &Private->ImageType
-               );
-    if ((Private->AuthData != NULL) && (Status == EFI_ACCESS_DENIED)) {
-      //
-      // Try to use HTTP HEAD method again since the Authentication information is provided.
-      //
-      Status = HttpBootGetBootFile (
-                 Private,
-                 TRUE,
-                 &Private->BootFileSize,
-                 NULL,
-                 &Private->ImageType
-                 );
-    } else if ((EFI_ERROR (Status)) && (Status != EFI_BUFFER_TOO_SMALL)) {
-      //
-      // Failed to get file size by HEAD method, may be trunked encoding, try HTTP GET method.
-      //
-      ASSERT (Private->BootFileSize == 0);
-      Status = HttpBootGetBootFile (
-                 Private,
-                 FALSE,
-                 &Private->BootFileSize,
-                 NULL,
-                 &Private->ImageType
-                 );
-      if (EFI_ERROR (Status) && (Status != EFI_BUFFER_TOO_SMALL)) {
-        AsciiPrint ("\n  Error: Could not retrieve NBP file size from HTTP server.\n");
-        goto ON_EXIT;
-      }
-    }
-  }
-
-  if (*BufferSize < Private->BootFileSize) {
-    *BufferSize = Private->BootFileSize;
-    *ImageType  = Private->ImageType;
-    Status      = EFI_BUFFER_TOO_SMALL;
-    goto ON_EXIT;
-  }
-
   //
-  // Load the boot file into Buffer
+  // Load the Boot File
   //
-  Status = HttpBootGetBootFile (
-             Private,
-             FALSE,
-             BufferSize,
-             Buffer,
-             ImageType
-             );
+  Status = HttpBootGetBootFileCaller (Private, BufferSize, Buffer, ImageType);
 
 ON_EXIT:
   HttpBootUninstallCallback (Private);
diff --git a/NetworkPkg/HttpBootDxe/HttpBootImpl.h b/NetworkPkg/HttpBootDxe/HttpBootImpl.h
index 55adc9cb50..33da4fec51 100644
--- a/NetworkPkg/HttpBootDxe/HttpBootImpl.h
+++ b/NetworkPkg/HttpBootDxe/HttpBootImpl.h
@@ -11,6 +11,13 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
 
 #define HTTP_BOOT_CHECK_MEDIA_WAITING_TIME  EFI_TIMER_PERIOD_SECONDS(20)
 
+typedef enum {
+  GetBootFileHead,
+  GetBootFileGet,
+  LoadBootFile,
+  GetBootFileError
+} HTTP_GET_BOOT_FILE_STATE;
+
 /**
   Attempt to complete a DHCPv4 D.O.R.A or DHCPv6 S.R.A.A sequence to retrieve the boot resource information.
 
diff --git a/NetworkPkg/HttpDxe/HttpImpl.c b/NetworkPkg/HttpDxe/HttpImpl.c
index 7c5c925cf7..a761ce3d5d 100644
--- a/NetworkPkg/HttpDxe/HttpImpl.c
+++ b/NetworkPkg/HttpDxe/HttpImpl.c
@@ -162,6 +162,7 @@ EfiHttpConfigure (
     HttpInstance->TimeOutMillisec    = HttpConfigData->TimeOutMillisec;
     HttpInstance->LocalAddressIsIPv6 = HttpConfigData->LocalAddressIsIPv6;
     HttpInstance->ConnectionClose    = FALSE;
+    HttpInstance->ProxyConnected     = FALSE;
 
     if (HttpConfigData->LocalAddressIsIPv6) {
       CopyMem (
@@ -244,6 +245,8 @@ EfiHttpRequest (
   CHAR8                  *RequestMsg;
   CHAR8                  *Url;
   UINTN                  UrlLen;
+  CHAR8                  *ProxyUrl;
+  UINTN                  ProxyUrlLen;
   CHAR16                 *HostNameStr;
   HTTP_TOKEN_WRAP        *Wrap;
   CHAR8                  *FileUrl;
@@ -254,6 +257,7 @@ EfiHttpRequest (
   // Initializations
   //
   Url          = NULL;
+  ProxyUrl     = NULL;
   UrlParser    = NULL;
   RemotePort   = 0;
   HostName     = NULL;
@@ -277,12 +281,18 @@ EfiHttpRequest (
   //
   // Only support GET, HEAD, DELETE, PATCH, PUT and POST method in current implementation.
   //
-  if ((Request != NULL) && (Request->Method != HttpMethodGet) &&
-      (Request->Method != HttpMethodHead) && (Request->Method != HttpMethodDelete) &&
-      (Request->Method != HttpMethodPut) && (Request->Method != HttpMethodPost) &&
-      (Request->Method != HttpMethodPatch))
-  {
-    return EFI_UNSUPPORTED;
+  if (Request != NULL) {
+    switch (Request->Method) {
+      case HttpMethodGet:
+      case HttpMethodHead:
+      case HttpMethodDelete:
+      case HttpMethodPut:
+      case HttpMethodPost:
+      case HttpMethodPatch:
+        break;
+      default:
+        return EFI_UNSUPPORTED;
+    }
   }
 
   HttpInstance = HTTP_INSTANCE_FROM_PROTOCOL (This);
@@ -337,22 +347,49 @@ EfiHttpRequest (
     }
 
     //
-    // Parse the URI of the remote host.
+    // Parse the Request URI.
     //
     Url    = HttpInstance->Url;
     UrlLen = StrLen (Request->Url) + 1;
-    if (UrlLen > HTTP_URL_BUFFER_LEN) {
+    if (UrlLen > HttpInstance->UrlLen) {
       Url = AllocateZeroPool (UrlLen);
       if (Url == NULL) {
         return EFI_OUT_OF_RESOURCES;
       }
 
-      FreePool (HttpInstance->Url);
-      HttpInstance->Url = Url;
+      if (HttpInstance->Url != NULL) {
+        FreePool (HttpInstance->Url);
+      }
+
+      HttpInstance->Url    = Url;
+      HttpInstance->UrlLen = UrlLen;
     }
 
     UnicodeStrToAsciiStrS (Request->Url, Url, UrlLen);
 
+    //
+    // In case of HTTP Connect, parse proxy URI from Request.
+    //
+    if (Request->Method == HttpMethodConnect) {
+      ProxyUrl    = HttpInstance->ProxyUrl;
+      ProxyUrlLen = StrLen (Request->ProxyUrl) + 1;
+      if (ProxyUrlLen > HttpInstance->ProxyUrlLen) {
+        ProxyUrl = AllocateZeroPool (ProxyUrlLen);
+        if (ProxyUrl == NULL) {
+          return EFI_OUT_OF_RESOURCES;
+        }
+
+        if (HttpInstance->ProxyUrl != NULL) {
+          FreePool (HttpInstance->ProxyUrl);
+        }
+
+        HttpInstance->ProxyUrl    = ProxyUrl;
+        HttpInstance->ProxyUrlLen = ProxyUrlLen;
+      }
+
+      UnicodeStrToAsciiStrS (Request->ProxyUrl, ProxyUrl, ProxyUrlLen);
+    }
+
     //
     // From the information in Url, the HTTP instance will
     // be able to determine whether to use http or https.
@@ -395,7 +432,7 @@ EfiHttpRequest (
     }
 
     UrlParser = NULL;
-    Status    = HttpParseUrl (Url, (UINT32)AsciiStrLen (Url), FALSE, &UrlParser);
+    Status = HttpParseUrl (Url, (UINT32)AsciiStrLen (Url), FALSE, &UrlParser);
     if (EFI_ERROR (Status)) {
       goto Error1;
     }
diff --git a/NetworkPkg/HttpDxe/HttpProto.c b/NetworkPkg/HttpDxe/HttpProto.c
index 33ae622c3f..6767d90c7d 100644
--- a/NetworkPkg/HttpDxe/HttpProto.c
+++ b/NetworkPkg/HttpDxe/HttpProto.c
@@ -737,6 +737,8 @@ HttpInitProtocol (
     goto ON_ERROR;
   }
 
+  HttpInstance->UrlLen = HTTP_URL_BUFFER_LEN;
+
   return EFI_SUCCESS;
 
 ON_ERROR:
@@ -846,9 +848,23 @@ HttpCleanProtocol (
 
   if (HttpInstance->Url != NULL) {
     FreePool (HttpInstance->Url);
-    HttpInstance->Url = NULL;
+    HttpInstance->Url    = NULL;
+    HttpInstance->UrlLen = 0;
+  }
+
+  if (HttpInstance->ProxyUrl != NULL) {
+    FreePool (HttpInstance->ProxyUrl);
+    HttpInstance->ProxyUrl    = NULL;
+    HttpInstance->ProxyUrlLen = 0;
   }
 
+  if (HttpInstance->EndPointHostName != NULL) {
+    FreePool (HttpInstance->EndPointHostName);
+    HttpInstance->EndPointHostName = NULL;
+  }
+
+  HttpInstance->ProxyConnected = FALSE;
+
   NetMapClean (&HttpInstance->TxTokens);
   NetMapClean (&HttpInstance->RxTokens);
 
diff --git a/NetworkPkg/HttpDxe/HttpProto.h b/NetworkPkg/HttpDxe/HttpProto.h
index 620eb39158..3e4e86dad9 100644
--- a/NetworkPkg/HttpDxe/HttpProto.h
+++ b/NetworkPkg/HttpDxe/HttpProto.h
@@ -164,6 +164,15 @@ typedef struct _HTTP_PROTOCOL {
   NET_MAP                           RxTokens;
 
   CHAR8                             *Url;
+  UINTN                             UrlLen;
+
+  //
+  // Proxy support
+  //
+  CHAR8                             *ProxyUrl;
+  UINTN                             ProxyUrlLen;
+  BOOLEAN                           ProxyConnected;
+  CHAR8                             *EndPointHostName;
 
   //
   // Https Support
-- 
2.36.1.windows.1


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [edk2-staging/HttpProxy PATCH v3 5/7] NetworkPkg: Add support for HTTP CONNECT Method
  2022-12-02 19:12 [edk2-staging/HttpProxy PATCH v3 0/7] Support HTTPS Proxy Server for HTTP Boot Saloni Kasbekar
                   ` (3 preceding siblings ...)
  2022-12-02 19:12 ` [edk2-staging/HttpProxy PATCH v3 4/7] NetworkPkg: Add Proxy Support to HTTP_PROTOCOL Saloni Kasbekar
@ 2022-12-02 19:12 ` Saloni Kasbekar
  2022-12-02 19:12 ` [edk2-staging/HttpProxy PATCH v3 6/7] NetworkPkg/HttpDxe: Support HTTPS EndPoint server with Proxy Saloni Kasbekar
  2022-12-02 19:12 ` [edk2-staging/HttpProxy PATCH v3 7/7] NetworkPkg/HttpBootDxe: Add Proxy URI input in setup menu Saloni Kasbekar
  6 siblings, 0 replies; 8+ messages in thread
From: Saloni Kasbekar @ 2022-12-02 19:12 UTC (permalink / raw)
  To: devel; +Cc: Saloni Kasbekar, Maciej Rabeda, Wu Jiaxin, Siyuan Fu

REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3951

Add support for the HTTP CONNECT method to request the Proxy Server
to open a tunnel to the EndPoint Server

Cc: Maciej Rabeda <maciej.rabeda@linux.intel.com>
Cc: Wu Jiaxin <jiaxin.wu@intel.com>
Cc: Siyuan Fu <siyuan.fu@intel.com>
Signed-off-by: Saloni Kasbekar <saloni.kasbekar@intel.com>
---
 NetworkPkg/HttpBootDxe/HttpBootClient.c    | 176 +++++++++++++++++++++
 NetworkPkg/HttpBootDxe/HttpBootClient.h    |  15 ++
 NetworkPkg/HttpBootDxe/HttpBootImpl.c      |  16 +-
 NetworkPkg/HttpBootDxe/HttpBootImpl.h      |   1 +
 NetworkPkg/HttpDxe/HttpDriver.h            |   2 +
 NetworkPkg/HttpDxe/HttpDxe.inf             |   1 +
 NetworkPkg/HttpDxe/HttpImpl.c              | 151 ++++++++++++++----
 NetworkPkg/Library/DxeHttpLib/DxeHttpLib.c |   5 +
 8 files changed, 335 insertions(+), 32 deletions(-)

diff --git a/NetworkPkg/HttpBootDxe/HttpBootClient.c b/NetworkPkg/HttpBootDxe/HttpBootClient.c
index b13155b576..b4d02eaff2 100644
--- a/NetworkPkg/HttpBootDxe/HttpBootClient.c
+++ b/NetworkPkg/HttpBootDxe/HttpBootClient.c
@@ -905,6 +905,182 @@ HttpBootGetBootFileCallback (
   return EFI_SUCCESS;
 }
 
+/**
+  This function establishes a connection through a proxy server
+
+  @param[in]       Private         The pointer to the driver's private data.
+
+  @retval EFI_SUCCESS              Connection successful.
+  @retval EFI_OUT_OF_RESOURCES     Could not allocate needed resources
+  @retval Others                   Unexpected error happened.
+
+**/
+EFI_STATUS
+HttpBootConnectProxy (
+  IN     HTTP_BOOT_PRIVATE_DATA  *Private
+  )
+{
+  EFI_STATUS             Status;
+  EFI_HTTP_STATUS_CODE   StatusCode;
+  CHAR8                  *HostName;
+  EFI_HTTP_REQUEST_DATA  *RequestData;
+  HTTP_IO_RESPONSE_DATA  *ResponseData;
+  HTTP_IO                *HttpIo;
+  HTTP_IO_HEADER         *HttpIoHeader;
+  CHAR16                 *Url;
+  CHAR16                 *ProxyUrl;
+  UINTN                  UrlSize;
+
+  Url          = NULL;
+  ProxyUrl     = NULL;
+  RequestData  = NULL;
+  ResponseData = NULL;
+  HttpIoHeader = NULL;
+
+  UrlSize = AsciiStrSize (Private->BootFileUri);
+  Url     = AllocatePool (UrlSize * sizeof (CHAR16));
+  if (Url == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  AsciiStrToUnicodeStrS (Private->BootFileUri, Url, UrlSize);
+
+  UrlSize  = AsciiStrSize (Private->ProxyUri);
+  ProxyUrl = AllocatePool (UrlSize * (sizeof (CHAR16)));
+  if (ProxyUrl == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    goto EXIT;
+  }
+
+  AsciiStrToUnicodeStrS (Private->ProxyUri, ProxyUrl, UrlSize);
+
+  //
+  // Send HTTP request message.
+  //
+
+  //
+  // Build HTTP header for the request, 2 headers are needed to send a CONNECT method:
+  //   Host
+  //   User
+  //
+  HttpIoHeader = HttpIoCreateHeader (2);
+  if (HttpIoHeader == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    goto EXIT;
+  }
+
+  //
+  // Add HTTP header field 1: Host (EndPoint URI)
+  //
+  HostName = NULL;
+  Status   = HttpUrlGetHostName (
+               Private->BootFileUri,
+               Private->BootFileUriParser,
+               &HostName
+               );
+  if (EFI_ERROR (Status)) {
+    goto EXIT;
+  }
+
+  Status = HttpIoSetHeader (
+             HttpIoHeader,
+             HTTP_HEADER_HOST,
+             HostName
+             );
+  if (EFI_ERROR (Status)) {
+    goto EXIT;
+  }
+
+  //
+  // Add HTTP header field 2: User-Agent
+  //
+  Status = HttpIoSetHeader (
+             HttpIoHeader,
+             HTTP_HEADER_USER_AGENT,
+             HTTP_USER_AGENT_EFI_HTTP_BOOT
+             );
+  if (EFI_ERROR (Status)) {
+    goto EXIT;
+  }
+
+  //
+  // Build the rest of HTTP request info.
+  //
+  RequestData = AllocatePool (sizeof (EFI_HTTP_REQUEST_DATA));
+  if (RequestData == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    goto EXIT;
+  }
+
+  RequestData->Method   = HttpMethodConnect;
+  RequestData->ProxyUrl = ProxyUrl;
+  RequestData->Url      = Url;
+
+  //
+  // Send out the request to HTTP server.
+  //
+  HttpIo = &Private->HttpIo;
+  Status = HttpIoSendRequest (
+             HttpIo,
+             RequestData,
+             HttpIoHeader->HeaderCount,
+             HttpIoHeader->Headers,
+             0,
+             NULL
+             );
+  if (EFI_ERROR (Status)) {
+    goto EXIT;
+  }
+
+  //
+  // Receive HTTP response message.
+  //
+
+  //
+  // Use zero BodyLength to only receive the response headers.
+  //
+  ResponseData = AllocateZeroPool (sizeof (HTTP_IO_RESPONSE_DATA));
+  if (ResponseData == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    goto EXIT;
+  }
+
+  Status = HttpIoRecvResponse (
+             &Private->HttpIo,
+             TRUE,
+             ResponseData
+             );
+
+  if (EFI_ERROR (Status) || EFI_ERROR (ResponseData->Status)) {
+    if (EFI_ERROR (ResponseData->Status)) {
+      StatusCode = HttpIo->RspToken.Message->Data.Response->StatusCode;
+      HttpBootPrintErrorMessage (StatusCode);
+      Status = ResponseData->Status;
+    }
+  }
+
+EXIT:
+  if (ResponseData != NULL) {
+    FreePool (ResponseData);
+  }
+
+  if (RequestData != NULL) {
+    FreePool (RequestData);
+  }
+
+  HttpIoFreeHeader (HttpIoHeader);
+
+  if (ProxyUrl != NULL) {
+    FreePool (ProxyUrl);
+  }
+
+  if (Url != NULL) {
+    FreePool (Url);
+  }
+
+  return Status;
+}
+
 /**
   This function download the boot file by using UEFI HTTP protocol.
 
diff --git a/NetworkPkg/HttpBootDxe/HttpBootClient.h b/NetworkPkg/HttpBootDxe/HttpBootClient.h
index 2fba713679..fcd624f536 100644
--- a/NetworkPkg/HttpBootDxe/HttpBootClient.h
+++ b/NetworkPkg/HttpBootDxe/HttpBootClient.h
@@ -86,6 +86,21 @@ HttpBootCreateHttpIo (
   IN     HTTP_BOOT_PRIVATE_DATA  *Private
   );
 
+/**
+  This function establishes a connection through a proxy server
+
+  @param[in]       Private         The pointer to the driver's private data.
+
+  @retval EFI_SUCCESS              Connection successful.
+  @retval EFI_OUT_OF_RESOURCES     Could not allocate needed resources
+  @retval Others                   Unexpected error happened.
+
+**/
+EFI_STATUS
+HttpBootConnectProxy (
+  IN     HTTP_BOOT_PRIVATE_DATA  *Private
+  );
+
 /**
   This function download the boot file by using UEFI HTTP protocol.
 
diff --git a/NetworkPkg/HttpBootDxe/HttpBootImpl.c b/NetworkPkg/HttpBootDxe/HttpBootImpl.c
index 4748de0603..d4a7c8385a 100644
--- a/NetworkPkg/HttpBootDxe/HttpBootImpl.c
+++ b/NetworkPkg/HttpBootDxe/HttpBootImpl.c
@@ -313,7 +313,11 @@ HttpBootGetBootFileCaller (
   EFI_STATUS                Status;
 
   if (Private->BootFileSize == 0) {
-    State = GetBootFileHead;
+    if (Private->ProxyUri != NULL) {
+      State = ConnectToProxy;
+    } else {
+      State = GetBootFileHead;
+    }
   } else {
     State = LoadBootFile;
   }
@@ -366,6 +370,16 @@ HttpBootGetBootFileCaller (
 
         break;
 
+      case ConnectToProxy:
+        Status = HttpBootConnectProxy (Private);
+        if (Status == EFI_SUCCESS) {
+          State = GetBootFileHead;
+        } else {
+          State = GetBootFileError;
+        }
+
+        break;
+
       case LoadBootFile:
         if (*BufferSize < Private->BootFileSize) {
           *BufferSize = Private->BootFileSize;
diff --git a/NetworkPkg/HttpBootDxe/HttpBootImpl.h b/NetworkPkg/HttpBootDxe/HttpBootImpl.h
index 33da4fec51..e4ffc3ed48 100644
--- a/NetworkPkg/HttpBootDxe/HttpBootImpl.h
+++ b/NetworkPkg/HttpBootDxe/HttpBootImpl.h
@@ -14,6 +14,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
 typedef enum {
   GetBootFileHead,
   GetBootFileGet,
+  ConnectToProxy,
   LoadBootFile,
   GetBootFileError
 } HTTP_GET_BOOT_FILE_STATE;
diff --git a/NetworkPkg/HttpDxe/HttpDriver.h b/NetworkPkg/HttpDxe/HttpDriver.h
index 01a6bb7f4b..e0917f431e 100644
--- a/NetworkPkg/HttpDxe/HttpDriver.h
+++ b/NetworkPkg/HttpDxe/HttpDriver.h
@@ -26,6 +26,7 @@
 #include <Library/NetLib.h>
 #include <Library/HttpLib.h>
 #include <Library/DpcLib.h>
+#include <Library/PrintLib.h>
 
 //
 // UEFI Driver Model Protocols
@@ -64,6 +65,7 @@
 // Driver Version
 //
 #define HTTP_DRIVER_VERSION  0xa
+#define URI_STR_MAX_SIZE     255
 
 //
 // Protocol instances
diff --git a/NetworkPkg/HttpDxe/HttpDxe.inf b/NetworkPkg/HttpDxe/HttpDxe.inf
index c9502d0bb6..30b7de1951 100644
--- a/NetworkPkg/HttpDxe/HttpDxe.inf
+++ b/NetworkPkg/HttpDxe/HttpDxe.inf
@@ -47,6 +47,7 @@
   NetLib
   HttpLib
   DpcLib
+  PrintLib
 
 [Protocols]
   gEfiHttpServiceBindingProtocolGuid               ## BY_START
diff --git a/NetworkPkg/HttpDxe/HttpImpl.c b/NetworkPkg/HttpDxe/HttpImpl.c
index a761ce3d5d..2a305e0864 100644
--- a/NetworkPkg/HttpDxe/HttpImpl.c
+++ b/NetworkPkg/HttpDxe/HttpImpl.c
@@ -234,6 +234,7 @@ EfiHttpRequest (
   EFI_HTTP_MESSAGE       *HttpMsg;
   EFI_HTTP_REQUEST_DATA  *Request;
   VOID                   *UrlParser;
+  VOID                   *EndPointUrlParser;
   EFI_STATUS             Status;
   CHAR8                  *HostName;
   UINTN                  HostNameSize;
@@ -247,25 +248,31 @@ EfiHttpRequest (
   UINTN                  UrlLen;
   CHAR8                  *ProxyUrl;
   UINTN                  ProxyUrlLen;
+  CHAR8                  *ParseUrl;
   CHAR16                 *HostNameStr;
   HTTP_TOKEN_WRAP        *Wrap;
   CHAR8                  *FileUrl;
   UINTN                  RequestMsgSize;
   EFI_HANDLE             ImageHandle;
+  UINT16                 EndPointRemotePort;
+  CHAR8                  *EndPointUrlMsg;
 
   //
   // Initializations
   //
-  Url          = NULL;
-  ProxyUrl     = NULL;
-  UrlParser    = NULL;
-  RemotePort   = 0;
-  HostName     = NULL;
-  RequestMsg   = NULL;
-  HostNameStr  = NULL;
-  Wrap         = NULL;
-  FileUrl      = NULL;
-  TlsConfigure = FALSE;
+  Url                = NULL;
+  ProxyUrl           = NULL;
+  UrlParser          = NULL;
+  EndPointUrlParser  = NULL;
+  RemotePort         = 0;
+  HostName           = NULL;
+  RequestMsg         = NULL;
+  HostNameStr        = NULL;
+  Wrap               = NULL;
+  FileUrl            = NULL;
+  TlsConfigure       = FALSE;
+  EndPointUrlMsg     = NULL;
+  EndPointRemotePort = 0;
 
   if ((This == NULL) || (Token == NULL)) {
     return EFI_INVALID_PARAMETER;
@@ -279,7 +286,7 @@ EfiHttpRequest (
   Request = HttpMsg->Data.Request;
 
   //
-  // Only support GET, HEAD, DELETE, PATCH, PUT and POST method in current implementation.
+  // Only support GET, HEAD, DELETE, CONNECT, PATCH, PUT and POST method in current implementation.
   //
   if (Request != NULL) {
     switch (Request->Method) {
@@ -289,6 +296,12 @@ EfiHttpRequest (
       case HttpMethodPut:
       case HttpMethodPost:
       case HttpMethodPatch:
+        break;
+      case HttpMethodConnect:
+        if (Request->ProxyUrl == NULL) {
+          return EFI_INVALID_PARAMETER;
+        }
+
         break;
       default:
         return EFI_UNSUPPORTED;
@@ -391,10 +404,14 @@ EfiHttpRequest (
     }
 
     //
-    // From the information in Url, the HTTP instance will
+    // From the information in the Urls, the HTTP instance will
     // be able to determine whether to use http or https.
     //
-    HttpInstance->UseHttps = IsHttpsUrl (Url);
+    if (Request->Method == HttpMethodConnect) {
+      HttpInstance->UseHttps = IsHttpsUrl (ProxyUrl);
+    } else {
+      HttpInstance->UseHttps = IsHttpsUrl (Url);
+    }
 
     //
     // HTTP is disabled, return directly if the URI is not HTTPS.
@@ -431,13 +448,26 @@ EfiHttpRequest (
       TlsConfigure = TRUE;
     }
 
-    UrlParser = NULL;
-    Status = HttpParseUrl (Url, (UINT32)AsciiStrLen (Url), FALSE, &UrlParser);
+    //
+    // Setup RemoteAddress and RemotePort of HttpInstance.
+    //
+    if (Request->Method == HttpMethodConnect) {
+      // Case 1: HTTP Connect request
+      ParseUrl = ProxyUrl;
+    } else if (HttpInstance->ProxyConnected == TRUE) {
+      // Case 2: Other HTTP request (proxy connected)
+      ParseUrl = HttpInstance->ProxyUrl;
+    } else {
+      // Case 3: Other HTTP request (proxy not connected)
+      ParseUrl = Url;
+    }
+
+    Status = HttpParseUrl (ParseUrl, (UINT32)AsciiStrLen (ParseUrl), FALSE, &UrlParser);
     if (EFI_ERROR (Status)) {
       goto Error1;
     }
 
-    Status = HttpUrlGetHostName (Url, UrlParser, &HostName);
+    Status = HttpUrlGetHostName (ParseUrl, UrlParser, &HostName);
     if (EFI_ERROR (Status)) {
       goto Error1;
     }
@@ -455,7 +485,7 @@ EfiHttpRequest (
       }
     }
 
-    Status = HttpUrlGetPort (Url, UrlParser, &RemotePort);
+    Status = HttpUrlGetPort (ParseUrl, UrlParser, &RemotePort);
     if (EFI_ERROR (Status)) {
       if (HttpInstance->UseHttps) {
         RemotePort = HTTPS_DEFAULT_PORT;
@@ -551,7 +581,7 @@ EfiHttpRequest (
     if (!HttpInstance->LocalAddressIsIPv6) {
       Status = NetLibAsciiStrToIp4 (HostName, &HttpInstance->RemoteAddr);
     } else {
-      Status = HttpUrlGetIp6 (Url, UrlParser, &HttpInstance->RemoteIpv6Addr);
+      Status = HttpUrlGetIp6 (ParseUrl, UrlParser, &HttpInstance->RemoteIpv6Addr);
     }
 
     if (EFI_ERROR (Status)) {
@@ -649,27 +679,74 @@ EfiHttpRequest (
   //
   // Create request message.
   //
-  FileUrl = Url;
-  if ((Url != NULL) && (*FileUrl != '/')) {
+  if (Request->Method == HttpMethodConnect) {
     //
-    // Convert the absolute-URI to the absolute-path
+    // HTTP Connect shall contain EndPoint host name in URI
     //
-    while (*FileUrl != ':') {
-      FileUrl++;
+    Status = HttpParseUrl (Url, (UINT32)AsciiStrLen (Url), FALSE, &EndPointUrlParser);
+    if (EFI_ERROR (Status)) {
+      goto Error3;
     }
 
-    if ((*(FileUrl+1) == '/') && (*(FileUrl+2) == '/')) {
-      FileUrl += 3;
-      while (*FileUrl != '/') {
-        FileUrl++;
+    Status = HttpUrlGetHostName (
+               Url,
+               EndPointUrlParser,
+               &HttpInstance->EndPointHostName
+               );
+    if (EFI_ERROR (Status)) {
+      goto Error3;
+    }
+
+    Status = HttpUrlGetPort (Url, EndPointUrlParser, &EndPointRemotePort);
+    if (EFI_ERROR (Status)) {
+      if (IsHttpsUrl (Url)) {
+        EndPointRemotePort = HTTPS_DEFAULT_PORT;
+      } else {
+        EndPointRemotePort = HTTP_DEFAULT_PORT;
       }
-    } else {
-      Status = EFI_INVALID_PARAMETER;
+    }
+
+    EndPointUrlMsg = AllocateZeroPool (URI_STR_MAX_SIZE);
+    if (EndPointUrlMsg == NULL) {
+      Status = EFI_OUT_OF_RESOURCES;
       goto Error3;
     }
-  }
 
-  Status = HttpGenRequestMessage (HttpMsg, FileUrl, &RequestMsg, &RequestMsgSize);
+    AsciiSPrint (
+      EndPointUrlMsg,
+      URI_STR_MAX_SIZE,
+      "%a:%d",
+      HttpInstance->EndPointHostName,
+      EndPointRemotePort
+      );
+
+    Status = HttpGenRequestMessage (HttpMsg, EndPointUrlMsg, &RequestMsg, &RequestMsgSize);
+
+    FreePool (EndPointUrlMsg);
+    HttpUrlFreeParser (EndPointUrlParser);
+  } else {
+    FileUrl = Url;
+    if ((Url != NULL) && (*FileUrl != '/')) {
+      //
+      // Convert the absolute-URI to the absolute-path
+      //
+      while (*FileUrl != ':') {
+        FileUrl++;
+      }
+
+      if ((*(FileUrl+1) == '/') && (*(FileUrl+2) == '/')) {
+        FileUrl += 3;
+        while (*FileUrl != '/') {
+          FileUrl++;
+        }
+      } else {
+        Status = EFI_INVALID_PARAMETER;
+        goto Error3;
+      }
+    }
+
+    Status = HttpGenRequestMessage (HttpMsg, FileUrl, &RequestMsg, &RequestMsgSize);
+  }
 
   if (EFI_ERROR (Status) || (NULL == RequestMsg)) {
     goto Error3;
@@ -705,6 +782,10 @@ EfiHttpRequest (
 
   DispatchDpc ();
 
+  if (HttpInstance->Method == HttpMethodConnect) {
+    HttpInstance->ProxyConnected = TRUE;
+  }
+
   if (HostName != NULL) {
     FreePool (HostName);
   }
@@ -750,6 +831,14 @@ Error2:
   }
 
 Error1:
+  if (EndPointUrlMsg != NULL) {
+    FreePool (EndPointUrlMsg);
+  }
+
+  if (EndPointUrlParser != NULL) {
+    HttpUrlFreeParser (EndPointUrlParser);
+  }
+
   if (HostName != NULL) {
     FreePool (HostName);
   }
diff --git a/NetworkPkg/Library/DxeHttpLib/DxeHttpLib.c b/NetworkPkg/Library/DxeHttpLib/DxeHttpLib.c
index 6a5d78629b..45087a1935 100644
--- a/NetworkPkg/Library/DxeHttpLib/DxeHttpLib.c
+++ b/NetworkPkg/Library/DxeHttpLib/DxeHttpLib.c
@@ -1927,6 +1927,11 @@ HttpGenRequestMessage (
         CopyMem (RequestPtr, HTTP_METHOD_DELETE, StrLength);
         RequestPtr += StrLength;
         break;
+      case HttpMethodConnect:
+        StrLength = sizeof (HTTP_METHOD_CONNECT) - 1;
+        CopyMem (RequestPtr, HTTP_METHOD_CONNECT, StrLength);
+        RequestPtr += StrLength;
+        break;
       default:
         ASSERT (FALSE);
         Status = EFI_INVALID_PARAMETER;
-- 
2.36.1.windows.1


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [edk2-staging/HttpProxy PATCH v3 6/7] NetworkPkg/HttpDxe: Support HTTPS EndPoint server with Proxy
  2022-12-02 19:12 [edk2-staging/HttpProxy PATCH v3 0/7] Support HTTPS Proxy Server for HTTP Boot Saloni Kasbekar
                   ` (4 preceding siblings ...)
  2022-12-02 19:12 ` [edk2-staging/HttpProxy PATCH v3 5/7] NetworkPkg: Add support for HTTP CONNECT Method Saloni Kasbekar
@ 2022-12-02 19:12 ` Saloni Kasbekar
  2022-12-02 19:12 ` [edk2-staging/HttpProxy PATCH v3 7/7] NetworkPkg/HttpBootDxe: Add Proxy URI input in setup menu Saloni Kasbekar
  6 siblings, 0 replies; 8+ messages in thread
From: Saloni Kasbekar @ 2022-12-02 19:12 UTC (permalink / raw)
  To: devel; +Cc: Saloni Kasbekar, Maciej Rabeda, Wu Jiaxin, Siyuan Fu

REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3951

Add support for Proxy server to connect to a HTTPS EndPoint server.
TLS Connection to be created during GET/HEAD after CONNECT method.

Cc: Maciej Rabeda <maciej.rabeda@linux.intel.com>
Cc: Wu Jiaxin <jiaxin.wu@intel.com>
Cc: Siyuan Fu <siyuan.fu@intel.com>
Signed-off-by: Saloni Kasbekar <saloni.kasbekar@intel.com>
---
 NetworkPkg/HttpDxe/HttpImpl.c     |  9 +++----
 NetworkPkg/HttpDxe/HttpProto.c    | 40 ++++++++++++++++++-------------
 NetworkPkg/HttpDxe/HttpProto.h    |  8 +++++--
 NetworkPkg/HttpDxe/HttpsSupport.c | 16 +++++++++----
 4 files changed, 46 insertions(+), 27 deletions(-)

diff --git a/NetworkPkg/HttpDxe/HttpImpl.c b/NetworkPkg/HttpDxe/HttpImpl.c
index 2a305e0864..f7d6a4c8f6 100644
--- a/NetworkPkg/HttpDxe/HttpImpl.c
+++ b/NetworkPkg/HttpDxe/HttpImpl.c
@@ -511,9 +511,10 @@ EfiHttpRequest (
       if ((HttpInstance->ConnectionClose == FALSE) &&
           (HttpInstance->RemotePort == RemotePort) &&
           (AsciiStrCmp (HttpInstance->RemoteHost, HostName) == 0) &&
-          (!HttpInstance->UseHttps || (HttpInstance->UseHttps &&
-                                       !TlsConfigure &&
-                                       (HttpInstance->TlsSessionState == EfiTlsSessionDataTransferring))))
+          (!HttpInstance->UseHttps ||
+           HttpInstance->ProxyConnected || (HttpInstance->UseHttps &&
+                                            !TlsConfigure &&
+                                            (HttpInstance->TlsSessionState == EfiTlsSessionDataTransferring))))
       {
         //
         // Host Name and port number of the request URL are the same with previous call to Request().
@@ -666,7 +667,7 @@ EfiHttpRequest (
     goto Error2;
   }
 
-  if (!Configure && !ReConfigure && !TlsConfigure) {
+  if ((!Configure && !ReConfigure) && ((HttpInstance->ProxyConnected && TlsConfigure) || (!TlsConfigure))) {
     //
     // For the new HTTP token, create TX TCP token events.
     //
diff --git a/NetworkPkg/HttpDxe/HttpProto.c b/NetworkPkg/HttpDxe/HttpProto.c
index 6767d90c7d..cc69401943 100644
--- a/NetworkPkg/HttpDxe/HttpProto.c
+++ b/NetworkPkg/HttpDxe/HttpProto.c
@@ -1222,6 +1222,7 @@ HttpConfigureTcp6 (
   connect one TLS session if required.
 
   @param[in]  HttpInstance       The HTTP instance private data.
+  @param[in]  TlsConfigure       The Flag indicates whether it's the new Tls session.
 
   @retval EFI_SUCCESS            The TCP connection is established.
   @retval EFI_NOT_READY          TCP4 protocol child is not created or configured.
@@ -1230,7 +1231,8 @@ HttpConfigureTcp6 (
 **/
 EFI_STATUS
 HttpConnectTcp4 (
-  IN  HTTP_PROTOCOL  *HttpInstance
+  IN  HTTP_PROTOCOL  *HttpInstance,
+  IN  BOOLEAN        TlsConfigure
   )
 {
   EFI_STATUS                 Status;
@@ -1253,16 +1255,18 @@ HttpConnectTcp4 (
     return Status;
   }
 
-  if (Tcp4State == Tcp4StateEstablished) {
+  if ((Tcp4State == Tcp4StateEstablished) && (!HttpInstance->ProxyConnected || !TlsConfigure)) {
     return EFI_SUCCESS;
-  } else if (Tcp4State > Tcp4StateEstablished ) {
+  } else if (Tcp4State > Tcp4StateEstablished) {
     HttpCloseConnection (HttpInstance);
   }
 
-  Status = HttpCreateConnection (HttpInstance);
-  if (EFI_ERROR (Status)) {
-    DEBUG ((DEBUG_ERROR, "Tcp4 Connection fail - %x\n", Status));
-    return Status;
+  if (!HttpInstance->ProxyConnected) {
+    Status = HttpCreateConnection (HttpInstance);
+    if (EFI_ERROR (Status)) {
+      DEBUG ((DEBUG_ERROR, "Tcp4 Connection fail - %x\n", Status));
+      return Status;
+    }
   }
 
   //
@@ -1314,6 +1318,7 @@ HttpConnectTcp4 (
   connect one TLS session if required.
 
   @param[in]  HttpInstance       The HTTP instance private data.
+  @param[in]  TlsConfigure       The Flag indicates whether it's the new Tls session.
 
   @retval EFI_SUCCESS            The TCP connection is established.
   @retval EFI_NOT_READY          TCP6 protocol child is not created or configured.
@@ -1322,7 +1327,8 @@ HttpConnectTcp4 (
 **/
 EFI_STATUS
 HttpConnectTcp6 (
-  IN  HTTP_PROTOCOL  *HttpInstance
+  IN  HTTP_PROTOCOL  *HttpInstance,
+  IN  BOOLEAN        TlsConfigure
   )
 {
   EFI_STATUS                 Status;
@@ -1346,16 +1352,18 @@ HttpConnectTcp6 (
     return Status;
   }
 
-  if (Tcp6State == Tcp6StateEstablished) {
+  if ((Tcp6State == Tcp6StateEstablished) && (!HttpInstance->ProxyConnected || !TlsConfigure)) {
     return EFI_SUCCESS;
-  } else if (Tcp6State > Tcp6StateEstablished ) {
+  } else if (Tcp6State > Tcp6StateEstablished) {
     HttpCloseConnection (HttpInstance);
   }
 
-  Status = HttpCreateConnection (HttpInstance);
-  if (EFI_ERROR (Status)) {
-    DEBUG ((DEBUG_ERROR, "Tcp6 Connection fail - %x\n", Status));
-    return Status;
+  if (!HttpInstance->ProxyConnected) {
+    Status = HttpCreateConnection (HttpInstance);
+    if (EFI_ERROR (Status)) {
+      DEBUG ((DEBUG_ERROR, "Tcp6 Connection fail - %x\n", Status));
+      return Status;
+    }
   }
 
   //
@@ -1450,7 +1458,7 @@ HttpInitSession (
     //
     // Connect TCP.
     //
-    Status = HttpConnectTcp4 (HttpInstance);
+    Status = HttpConnectTcp4 (HttpInstance, TlsConfigure);
     if (EFI_ERROR (Status)) {
       return Status;
     }
@@ -1468,7 +1476,7 @@ HttpInitSession (
     //
     // Connect TCP.
     //
-    Status = HttpConnectTcp6 (HttpInstance);
+    Status = HttpConnectTcp6 (HttpInstance, TlsConfigure);
     if (EFI_ERROR (Status)) {
       return Status;
     }
diff --git a/NetworkPkg/HttpDxe/HttpProto.h b/NetworkPkg/HttpDxe/HttpProto.h
index 3e4e86dad9..6fd2082e1b 100644
--- a/NetworkPkg/HttpDxe/HttpProto.h
+++ b/NetworkPkg/HttpDxe/HttpProto.h
@@ -407,6 +407,7 @@ HttpConfigureTcp6 (
   connect one TLS session if required.
 
   @param[in]  HttpInstance       The HTTP instance private data.
+  @param[in]  TlsConfigure       The Flag indicates whether it's the new Tls session.
 
   @retval EFI_SUCCESS            The TCP connection is established.
   @retval EFI_NOT_READY          TCP4 protocol child is not created or configured.
@@ -415,7 +416,8 @@ HttpConfigureTcp6 (
 **/
 EFI_STATUS
 HttpConnectTcp4 (
-  IN  HTTP_PROTOCOL  *HttpInstance
+  IN  HTTP_PROTOCOL  *HttpInstance,
+  IN  BOOLEAN        TlsConfigure
   );
 
 /**
@@ -423,6 +425,7 @@ HttpConnectTcp4 (
   connect one TLS session if required.
 
   @param[in]  HttpInstance       The HTTP instance private data.
+  @param[in]  TlsConfigure       The Flag indicates whether it's the new Tls session.
 
   @retval EFI_SUCCESS            The TCP connection is established.
   @retval EFI_NOT_READY          TCP6 protocol child is not created or configured.
@@ -431,7 +434,8 @@ HttpConnectTcp4 (
 **/
 EFI_STATUS
 HttpConnectTcp6 (
-  IN  HTTP_PROTOCOL  *HttpInstance
+  IN  HTTP_PROTOCOL  *HttpInstance,
+  IN  BOOLEAN        TlsConfigure
   );
 
 /**
diff --git a/NetworkPkg/HttpDxe/HttpsSupport.c b/NetworkPkg/HttpDxe/HttpsSupport.c
index ad611e7c38..81c65758d3 100644
--- a/NetworkPkg/HttpDxe/HttpsSupport.c
+++ b/NetworkPkg/HttpDxe/HttpsSupport.c
@@ -644,11 +644,17 @@ TlsConfigureSession (
   //
   // TlsConfigData initialization
   //
-  HttpInstance->TlsConfigData.ConnectionEnd       = EfiTlsClient;
-  HttpInstance->TlsConfigData.VerifyMethod        = EFI_TLS_VERIFY_PEER;
-  HttpInstance->TlsConfigData.VerifyHost.Flags    = EFI_TLS_VERIFY_FLAG_NONE;
-  HttpInstance->TlsConfigData.VerifyHost.HostName = HttpInstance->RemoteHost;
-  HttpInstance->TlsConfigData.SessionState        = EfiTlsSessionNotStarted;
+  HttpInstance->TlsConfigData.ConnectionEnd    = EfiTlsClient;
+  HttpInstance->TlsConfigData.VerifyMethod     = EFI_TLS_VERIFY_PEER;
+  HttpInstance->TlsConfigData.VerifyHost.Flags = EFI_TLS_VERIFY_FLAG_NONE;
+  HttpInstance->TlsConfigData.SessionState     = EfiTlsSessionNotStarted;
+
+  if (HttpInstance->ProxyConnected) {
+    ASSERT (HttpInstance->EndPointHostName != NULL);
+    HttpInstance->TlsConfigData.VerifyHost.HostName = HttpInstance->EndPointHostName;
+  } else {
+    HttpInstance->TlsConfigData.VerifyHost.HostName = HttpInstance->RemoteHost;
+  }
 
   //
   // EfiTlsConnectionEnd,
-- 
2.36.1.windows.1


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [edk2-staging/HttpProxy PATCH v3 7/7] NetworkPkg/HttpBootDxe: Add Proxy URI input in setup menu
  2022-12-02 19:12 [edk2-staging/HttpProxy PATCH v3 0/7] Support HTTPS Proxy Server for HTTP Boot Saloni Kasbekar
                   ` (5 preceding siblings ...)
  2022-12-02 19:12 ` [edk2-staging/HttpProxy PATCH v3 6/7] NetworkPkg/HttpDxe: Support HTTPS EndPoint server with Proxy Saloni Kasbekar
@ 2022-12-02 19:12 ` Saloni Kasbekar
  6 siblings, 0 replies; 8+ messages in thread
From: Saloni Kasbekar @ 2022-12-02 19:12 UTC (permalink / raw)
  To: devel; +Cc: Saloni Kasbekar, Maciej Rabeda, Wu Jiaxin, Siyuan Fu

REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3951

Allows users to input the Proxy Server URI in the
HTTP setup menu

Cc: Maciej Rabeda <maciej.rabeda@linux.intel.com>
Cc: Wu Jiaxin <jiaxin.wu@intel.com>
Cc: Siyuan Fu <siyuan.fu@intel.com>
Signed-off-by: Saloni Kasbekar <saloni.kasbekar@intel.com>
---
 NetworkPkg/HttpBootDxe/HttpBootConfig.c       | 99 ++++++++++++++-----
 .../HttpBootDxe/HttpBootConfigNVDataStruc.h   |  4 +-
 .../HttpBootDxe/HttpBootConfigStrings.uni     |  2 +
 NetworkPkg/HttpBootDxe/HttpBootConfigVfr.vfr  |  9 ++
 4 files changed, 88 insertions(+), 26 deletions(-)

diff --git a/NetworkPkg/HttpBootDxe/HttpBootConfig.c b/NetworkPkg/HttpBootDxe/HttpBootConfig.c
index 42d3fdc1fb..2cdd5043fe 100644
--- a/NetworkPkg/HttpBootDxe/HttpBootConfig.c
+++ b/NetworkPkg/HttpBootDxe/HttpBootConfig.c
@@ -18,6 +18,7 @@ CHAR16  mHttpBootConfigStorageName[] = L"HTTP_BOOT_CONFIG_IFR_NVDATA";
   @param[in]  UsingIpv6           Set to TRUE if creating boot option for IPv6.
   @param[in]  Description         The description text of the boot option.
   @param[in]  Uri                 The URI string of the boot file.
+  @param[in]  ProxyUri            The Proxy URI string for the boot path.
 
   @retval EFI_SUCCESS             The boot option is created successfully.
   @retval Others                  Failed to create new boot option.
@@ -28,48 +29,59 @@ HttpBootAddBootOption (
   IN   HTTP_BOOT_PRIVATE_DATA  *Private,
   IN   BOOLEAN                 UsingIpv6,
   IN   CHAR16                  *Description,
-  IN   CHAR16                  *Uri
+  IN   CHAR16                  *Uri,
+  IN   CHAR16                  *ProxyUri
   )
 {
   EFI_DEV_PATH                  *Node;
   EFI_DEVICE_PATH_PROTOCOL      *TmpDevicePath;
   EFI_DEVICE_PATH_PROTOCOL      *NewDevicePath;
+  EFI_DEVICE_PATH_PROTOCOL      *FinalDevicePath;
   UINTN                         Length;
   CHAR8                         AsciiUri[URI_STR_MAX_SIZE];
+  CHAR8                         AsciiProxyUri[URI_STR_MAX_SIZE];
+  UINTN                         AsciiProxyUriSize;
   EFI_STATUS                    Status;
-  UINTN                         Index;
   EFI_BOOT_MANAGER_LOAD_OPTION  NewOption;
 
-  NewDevicePath = NULL;
-  Node          = NULL;
-  TmpDevicePath = NULL;
+  NewDevicePath   = NULL;
+  Node            = NULL;
+  TmpDevicePath   = NULL;
+  FinalDevicePath = NULL;
 
   if (StrLen (Description) == 0) {
     return EFI_INVALID_PARAMETER;
   }
 
   //
-  // Convert the scheme to all lower case.
+  // Check the URI Scheme
   //
-  for (Index = 0; Index < StrLen (Uri); Index++) {
-    if (Uri[Index] == L':') {
-      break;
+  UnicodeStrToAsciiStrS (Uri, AsciiUri, sizeof (AsciiUri));
+  UnicodeStrToAsciiStrS (ProxyUri, AsciiProxyUri, sizeof (AsciiProxyUri));
+  Status = HttpBootCheckUriScheme (AsciiUri);
+  if (EFI_ERROR (Status)) {
+    if (Status == EFI_INVALID_PARAMETER) {
+      DEBUG ((DEBUG_ERROR, "Error: Invalid URI address.\n"));
+    } else if (Status == EFI_ACCESS_DENIED) {
+      DEBUG ((DEBUG_ERROR, "Error: Access forbidden, only HTTPS connection is allowed.\n"));
     }
 
-    if ((Uri[Index] >= L'A') && (Uri[Index] <= L'Z')) {
-      Uri[Index] -= (CHAR16)(L'A' - L'a');
-    }
+    return Status;
   }
 
-  //
-  // Only accept empty URI, or http and https URI.
-  //
-  if ((StrLen (Uri) != 0) && (StrnCmp (Uri, L"http://", 7) != 0) && (StrnCmp (Uri, L"https://", 8) != 0)) {
-    return EFI_INVALID_PARAMETER;
+  Status = HttpBootCheckUriScheme (AsciiProxyUri);
+  if (EFI_ERROR (Status)) {
+    if (Status == EFI_INVALID_PARAMETER) {
+      DEBUG ((DEBUG_ERROR, "Error: Invalid URI address.\n"));
+    } else if (Status == EFI_ACCESS_DENIED) {
+      DEBUG ((DEBUG_ERROR, "Error: Access forbidden, only HTTPS connection is allowed.\n"));
+    }
+
+    return Status;
   }
 
   //
-  // Create a new device path by appending the IP node and URI node to
+  // Create a new device path by appending the IP node, Proxy node and URI node to
   // the driver's parent device path
   //
   if (!UsingIpv6) {
@@ -100,15 +112,43 @@ HttpBootAddBootOption (
     return EFI_OUT_OF_RESOURCES;
   }
 
+  //
+  // Update the Proxy node with the input Proxy URI
+  //
+  if (StrLen (ProxyUri) != 0) {
+    AsciiProxyUriSize = AsciiStrSize (AsciiProxyUri);
+    Length            = sizeof (EFI_DEVICE_PATH_PROTOCOL) + AsciiProxyUriSize;
+    Node              = AllocatePool (Length);
+    if (Node == NULL) {
+      Status = EFI_OUT_OF_RESOURCES;
+      goto ON_EXIT;
+    }
+
+    Node->DevPath.Type    = MESSAGING_DEVICE_PATH;
+    Node->DevPath.SubType = MSG_URI_DP;
+    SetDevicePathNodeLength (Node, Length);
+    CopyMem (
+      (UINT8 *)Node + sizeof (EFI_DEVICE_PATH_PROTOCOL),
+      AsciiProxyUri,
+      AsciiProxyUriSize
+      );
+    NewDevicePath = AppendDevicePathNode (TmpDevicePath, (EFI_DEVICE_PATH_PROTOCOL *)Node);
+    FreePool (Node);
+    if (NewDevicePath == NULL) {
+      Status = EFI_OUT_OF_RESOURCES;
+      goto ON_EXIT;
+    }
+  } else {
+    NewDevicePath = TmpDevicePath;
+  }
+
   //
   // Update the URI node with the input boot file URI.
   //
-  UnicodeStrToAsciiStrS (Uri, AsciiUri, sizeof (AsciiUri));
   Length = sizeof (EFI_DEVICE_PATH_PROTOCOL) + AsciiStrSize (AsciiUri);
   Node   = AllocatePool (Length);
   if (Node == NULL) {
     Status = EFI_OUT_OF_RESOURCES;
-    FreePool (TmpDevicePath);
     goto ON_EXIT;
   }
 
@@ -116,10 +156,9 @@ HttpBootAddBootOption (
   Node->DevPath.SubType = MSG_URI_DP;
   SetDevicePathNodeLength (Node, Length);
   CopyMem ((UINT8 *)Node + sizeof (EFI_DEVICE_PATH_PROTOCOL), AsciiUri, AsciiStrSize (AsciiUri));
-  NewDevicePath = AppendDevicePathNode (TmpDevicePath, (EFI_DEVICE_PATH_PROTOCOL *)Node);
+  FinalDevicePath = AppendDevicePathNode (NewDevicePath, (EFI_DEVICE_PATH_PROTOCOL *)Node);
   FreePool (Node);
-  FreePool (TmpDevicePath);
-  if (NewDevicePath == NULL) {
+  if (FinalDevicePath == NULL) {
     Status = EFI_OUT_OF_RESOURCES;
     goto ON_EXIT;
   }
@@ -133,7 +172,7 @@ HttpBootAddBootOption (
              LoadOptionTypeBoot,
              LOAD_OPTION_ACTIVE,
              Description,
-             NewDevicePath,
+             FinalDevicePath,
              NULL,
              0
              );
@@ -146,10 +185,18 @@ HttpBootAddBootOption (
 
 ON_EXIT:
 
+  if (TmpDevicePath != NULL) {
+    FreePool (TmpDevicePath);
+  }
+
   if (NewDevicePath != NULL) {
     FreePool (NewDevicePath);
   }
 
+  if (FinalDevicePath != NULL) {
+    FreePool (FinalDevicePath);
+  }
+
   return Status;
 }
 
@@ -406,7 +453,8 @@ HttpBootFormRouteConfig (
     Private,
     (CallbackInfo->HttpBootNvData.IpVersion == HTTP_BOOT_IP_VERSION_6) ? TRUE : FALSE,
     CallbackInfo->HttpBootNvData.Description,
-    CallbackInfo->HttpBootNvData.Uri
+    CallbackInfo->HttpBootNvData.Uri,
+    CallbackInfo->HttpBootNvData.ProxyUri
     );
 
   return EFI_SUCCESS;
@@ -472,6 +520,7 @@ HttpBootFormCallback (
 
   switch (QuestionId) {
     case KEY_INITIATOR_URI:
+    case KEY_INITIATOR_PROXY_URI:
       //
       // Get user input URI string
       //
diff --git a/NetworkPkg/HttpBootDxe/HttpBootConfigNVDataStruc.h b/NetworkPkg/HttpBootDxe/HttpBootConfigNVDataStruc.h
index a24fa5cb08..f0da21e8fd 100644
--- a/NetworkPkg/HttpBootDxe/HttpBootConfigNVDataStruc.h
+++ b/NetworkPkg/HttpBootDxe/HttpBootConfigNVDataStruc.h
@@ -27,7 +27,8 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
 
 #define FORMID_MAIN_FORM  1
 
-#define KEY_INITIATOR_URI  0x101
+#define KEY_INITIATOR_URI        0x101
+#define KEY_INITIATOR_PROXY_URI  0x102
 
 #define HTTP_BOOT_DEFAULT_DESCRIPTION_STR  L"UEFI HTTP"
 
@@ -37,6 +38,7 @@ typedef struct _HTTP_BOOT_CONFIG_IFR_NVDATA {
   UINT8     Padding;
   CHAR16    Description[DESCRIPTION_STR_MAX_SIZE];
   CHAR16    Uri[URI_STR_MAX_SIZE];
+  CHAR16    ProxyUri[URI_STR_MAX_SIZE];
 } HTTP_BOOT_CONFIG_IFR_NVDATA;
 #pragma pack()
 
diff --git a/NetworkPkg/HttpBootDxe/HttpBootConfigStrings.uni b/NetworkPkg/HttpBootDxe/HttpBootConfigStrings.uni
index 40abb13d0d..28af02bc14 100644
--- a/NetworkPkg/HttpBootDxe/HttpBootConfigStrings.uni
+++ b/NetworkPkg/HttpBootDxe/HttpBootConfigStrings.uni
@@ -18,4 +18,6 @@
 #string STR_BOOT_URI_PROMPT                   #language en-US "Boot URI"
 #string STR_BOOT_URI_HELP                     #language en-US "A new Boot Option will be created according to this Boot URI."
 #string STR_BOOT_DESCRIPTION_PROMPT           #language en-US "Input the description"
+#string STR_BOOT_PROXY_URI_PROMPT             #language en-US "Proxy URI"
+#string STR_BOOT_PROXY_URI_HELP               #language en-US "Proxy URI through which to connect to Boot URI"
 #string STR_NULL_STRING                       #language en-US ""
diff --git a/NetworkPkg/HttpBootDxe/HttpBootConfigVfr.vfr b/NetworkPkg/HttpBootDxe/HttpBootConfigVfr.vfr
index 65a60216bc..6a23e57d6b 100644
--- a/NetworkPkg/HttpBootDxe/HttpBootConfigVfr.vfr
+++ b/NetworkPkg/HttpBootDxe/HttpBootConfigVfr.vfr
@@ -44,6 +44,15 @@ formset
             minsize = URI_STR_MIN_SIZE,
             maxsize = URI_STR_MAX_SIZE,
     endstring;
+
+    string  varid   = HTTP_BOOT_CONFIG_IFR_NVDATA.ProxyUri,
+            prompt  = STRING_TOKEN(STR_BOOT_PROXY_URI_PROMPT),
+            help    = STRING_TOKEN(STR_BOOT_PROXY_URI_HELP),
+            flags   = INTERACTIVE,
+            key     = KEY_INITIATOR_PROXY_URI,
+            minsize = URI_STR_MIN_SIZE,
+            maxsize = URI_STR_MAX_SIZE,
+    endstring;
   endform;
 
 endformset;
-- 
2.36.1.windows.1


^ permalink raw reply related	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2022-12-02 19:12 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2022-12-02 19:12 [edk2-staging/HttpProxy PATCH v3 0/7] Support HTTPS Proxy Server for HTTP Boot Saloni Kasbekar
2022-12-02 19:12 ` [edk2-staging/HttpProxy PATCH v3 1/7] MdeModulePkg/Library: Support multi-URI HTTP Boot device path Saloni Kasbekar
2022-12-02 19:12 ` [edk2-staging/HttpProxy PATCH v3 2/7] MdePkg/Include: Add Proxy Server URL in EFI_HTTP_REQUEST_DATA Saloni Kasbekar
2022-12-02 19:12 ` [edk2-staging/HttpProxy PATCH v3 3/7] NetworkPkg/HttpBootDxe: Update HTTP Boot Driver with parsed Proxy URL Saloni Kasbekar
2022-12-02 19:12 ` [edk2-staging/HttpProxy PATCH v3 4/7] NetworkPkg: Add Proxy Support to HTTP_PROTOCOL Saloni Kasbekar
2022-12-02 19:12 ` [edk2-staging/HttpProxy PATCH v3 5/7] NetworkPkg: Add support for HTTP CONNECT Method Saloni Kasbekar
2022-12-02 19:12 ` [edk2-staging/HttpProxy PATCH v3 6/7] NetworkPkg/HttpDxe: Support HTTPS EndPoint server with Proxy Saloni Kasbekar
2022-12-02 19:12 ` [edk2-staging/HttpProxy PATCH v3 7/7] NetworkPkg/HttpBootDxe: Add Proxy URI input in setup menu Saloni Kasbekar

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox