From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mga17.intel.com (mga17.intel.com [192.55.52.151]) by mx.groups.io with SMTP id smtpd.web11.84900.1670008354257768666 for ; Fri, 02 Dec 2022 11:12:37 -0800 Authentication-Results: mx.groups.io; dkim=fail reason="unable to parse pub key" header.i=@intel.com header.s=intel header.b=d4/+w9S2; spf=pass (domain: intel.com, ip: 192.55.52.151, mailfrom: saloni.kasbekar@intel.com) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1670008357; x=1701544357; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=S8MkRXOmvH06nqywdfxRF3cPeYu6PLX3iAVFpDVQstg=; b=d4/+w9S2iOHSttODl6bsKxunFZj5OQ43Dq8YrmdhkD4XAdESf12n2uCp HP6HP2FNx+ZVvqiRLXrNi2BARy6Qq34srmn+XDn7u8Si1gPZRYZKBNCvy b2uw/AAaDubjOs8xPGirZHrdnJkLZHWbprrXCdmrjYfjPycFi31/oOnH6 lASwsHYuHujRhoW6Ko65I0qM53XQA67PXO9Bn6EP/czCHflGVwrWDrrDA gApo/Qqz7e6iNIddLSV+6g6i7Kn+K11NV4ggjJdF28QEVBUobPotu28s8 HcpMhL+n0zeDp4d9s0M85wnmSlo2rpMGPCXeRSm2JXWNMFuK0bMr6wXSm w==; X-IronPort-AV: E=McAfee;i="6500,9779,10549"; a="296382579" X-IronPort-AV: E=Sophos;i="5.96,213,1665471600"; d="scan'208";a="296382579" Received: from fmsmga003.fm.intel.com ([10.253.24.29]) by fmsmga107.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 02 Dec 2022 11:12:37 -0800 X-IronPort-AV: E=McAfee;i="6500,9779,10549"; a="733916670" X-IronPort-AV: E=Sophos;i="5.96,213,1665471600"; d="scan'208";a="733916670" Received: from fmbiosdev02.amr.corp.intel.com ([10.80.127.10]) by fmsmga003-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 02 Dec 2022 11:12:37 -0800 From: "Saloni Kasbekar" To: devel@edk2.groups.io Cc: Saloni Kasbekar , Maciej Rabeda , Wu Jiaxin , Siyuan Fu Subject: [edk2-staging/HttpProxy PATCH v3 3/7] NetworkPkg/HttpBootDxe: Update HTTP Boot Driver with parsed Proxy URL Date: Fri, 2 Dec 2022 11:12:22 -0800 Message-Id: <40249646b0fd9e44940b3a001589c1d22e53e076.1670008048.git.saloni.kasbekar@intel.com> X-Mailer: git-send-email 2.36.1.windows.1 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit 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 Cc: Wu Jiaxin Cc: Siyuan Fu Signed-off-by: Saloni Kasbekar --- 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