From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mga18.intel.com (mga18.intel.com [134.134.136.126]) by mx.groups.io with SMTP id smtpd.web11.262.1665178478972669259 for ; Fri, 07 Oct 2022 14:34:44 -0700 Authentication-Results: mx.groups.io; dkim=fail reason="unable to parse pub key" header.i=@intel.com header.s=intel header.b=GQJ/GlZn; spf=pass (domain: intel.com, ip: 134.134.136.126, 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=1665178484; x=1696714484; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=eNAcR/GuQbC/WphvKr4zmcsCXpR6Jb/Ic7KysR6VXYw=; b=GQJ/GlZna4gkc6Rglax67IxIRmEcPMfyd2GPdep08ZKLbV156UoStQZK GWQRHoBzWvWWHfZjheGgOuR0dGZiQUhtcFlbZJEoRlftaIIeqgwvRPrMM gCpWdaMYfX6U4ezsD8Q7iEoeiue45OX1KHB5nO20y2sOWRXPnVwlWflq9 640PJBy1fzWOfgCNwLoaaeEafKFLovbGL+M0WzYlzsbh8bwiYjzSWgd8i ZIGDjx80IsuGaEe5u/sByG0wsIrEniNHg9rkhd7cuHv8LWyVyYECdlXcA dsh38EgAHpG8zeAKCQ77PME3Bks7ZVA5PDrGNq2arLjDpR66uupd25PHS g==; X-IronPort-AV: E=McAfee;i="6500,9779,10493"; a="287069102" X-IronPort-AV: E=Sophos;i="5.95,167,1661842800"; d="scan'208";a="287069102" Received: from orsmga001.jf.intel.com ([10.7.209.18]) by orsmga106.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 07 Oct 2022 14:34:44 -0700 X-IronPort-AV: E=McAfee;i="6500,9779,10493"; a="658479385" X-IronPort-AV: E=Sophos;i="5.95,167,1661842800"; d="scan'208";a="658479385" Received: from fmbiosdev02.amr.corp.intel.com ([10.80.127.10]) by orsmga001-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 07 Oct 2022 14:34:43 -0700 From: "Saloni Kasbekar" To: devel@edk2.groups.io Cc: Saloni Kasbekar , Maciej Rabeda , Wu Jiaxin , Siyuan Fu Subject: [[edk2-staging/HttpProxy PATCH v2] 4/6] NetworkPkg: Add Proxy Support to HTTP_PROTOCOL Date: Fri, 7 Oct 2022 14:34:28 -0700 Message-Id: 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 Update HTTP Protocol with variables to support Proxy Use state machine to call HttpBootGetBootFile() Add switch/case for EfiHttpRequest request method Cc: Maciej Rabeda Cc: Wu Jiaxin Cc: Siyuan Fu Signed-off-by: Saloni Kasbekar --- 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