summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSaloni Kasbekar <saloni.kasbekar@intel.com>2022-12-16 16:38:42 +0100
committermergify[bot] <37929162+mergify[bot]@users.noreply.github.com>2025-03-13 00:34:01 +0000
commitf5148b126710d1e9bbbded75a72740e5cbd92617 (patch)
tree2c8ae9b5bb066134c54090c61bdafde838fb5eae
parent2880ca12cea42142a3122dabfa2857a70a51759f (diff)
downloadedk2-f5148b126710d1e9bbbded75a72740e5cbd92617.zip
edk2-f5148b126710d1e9bbbded75a72740e5cbd92617.tar.gz
edk2-f5148b126710d1e9bbbded75a72740e5cbd92617.tar.bz2
NetworkPkg/HttpDxe: Added support for HTTP CONNECT request.
1. Store information in HttpInstance. a) Proxy URL from last HTTP CONNECT request (ProxyUrl) and its length (ProxyUrlLen). b) State of connection to proxy server (ProxyConnected) - TRUE after HTTP CONNECT success. c) Host name extracted from endpoint URL (EndPointHostName). 2. Modified EfiHttpRequest() flow to handle HTTP CONNECT request. a) Treating request's URL as "endpoint URL". In case of HTTP CONNECT request, directing it to Proxy URL with Host set to "endpoint URL". 3. Added PrintLib instance to cover AsciiSPrint() call. Implementation based on UEFI Specification v2.11 - Section 24.7.10 to use HTTP CONNECT method to connect to Proxy Server and use it to forward the HEAD/GET request to Endpoint Server's BootURI. - Section 29.6.6 to use EFI_HTTP_CONNECT_REQUEST_DATA structure for HttpMethodConnect usage in EFI_HTTP_PROTOCOL.Request() Signed-off-by: Saloni Kasbekar <saloni.kasbekar@intel.com>
-rw-r--r--NetworkPkg/HttpDxe/HttpDriver.h2
-rw-r--r--NetworkPkg/HttpDxe/HttpDxe.inf1
-rw-r--r--NetworkPkg/HttpDxe/HttpImpl.c227
-rw-r--r--NetworkPkg/HttpDxe/HttpProto.c13
-rw-r--r--NetworkPkg/HttpDxe/HttpProto.h8
5 files changed, 198 insertions, 53 deletions
diff --git a/NetworkPkg/HttpDxe/HttpDriver.h b/NetworkPkg/HttpDxe/HttpDriver.h
index 01a6bb7..e0917f4 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 c9502d0..30b7de1 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 76f0dff..79602ec 100644
--- a/NetworkPkg/HttpDxe/HttpImpl.c
+++ b/NetworkPkg/HttpDxe/HttpImpl.c
@@ -163,6 +163,7 @@ EfiHttpConfigure (
HttpInstance->TimeOutMillisec = HttpConfigData->TimeOutMillisec;
HttpInstance->LocalAddressIsIPv6 = HttpConfigData->LocalAddressIsIPv6;
HttpInstance->ConnectionClose = FALSE;
+ HttpInstance->ProxyConnected = FALSE;
if (HttpConfigData->LocalAddressIsIPv6) {
CopyMem (
@@ -231,37 +232,49 @@ EfiHttpRequest (
IN EFI_HTTP_TOKEN *Token
)
{
- EFI_HTTP_MESSAGE *HttpMsg;
- EFI_HTTP_REQUEST_DATA *Request;
- VOID *UrlParser;
- EFI_STATUS Status;
- CHAR8 *HostName;
- UINTN HostNameSize;
- UINT16 RemotePort;
- HTTP_PROTOCOL *HttpInstance;
- BOOLEAN Configure;
- BOOLEAN ReConfigure;
- BOOLEAN TlsConfigure;
- CHAR8 *RequestMsg;
- CHAR8 *Url;
- UINTN UrlLen;
- CHAR16 *HostNameStr;
- HTTP_TOKEN_WRAP *Wrap;
- CHAR8 *FileUrl;
- UINTN RequestMsgSize;
+ EFI_HTTP_MESSAGE *HttpMsg;
+ EFI_HTTP_REQUEST_DATA *Request;
+ VOID *UrlParser;
+ VOID *EndPointUrlParser;
+ EFI_STATUS Status;
+ CHAR8 *HostName;
+ UINTN HostNameSize;
+ UINT16 RemotePort;
+ HTTP_PROTOCOL *HttpInstance;
+ BOOLEAN Configure;
+ BOOLEAN ReConfigure;
+ BOOLEAN TlsConfigure;
+ CHAR8 *RequestMsg;
+ CHAR8 *Url;
+ UINTN UrlLen;
+ CHAR8 *ProxyUrl;
+ UINTN ProxyUrlLen;
+ CHAR8 *ParseUrl;
+ CHAR16 *HostNameStr;
+ HTTP_TOKEN_WRAP *Wrap;
+ CHAR8 *FileUrl;
+ UINTN RequestMsgSize;
+ UINT16 EndPointRemotePort;
+ CHAR8 *EndPointUrlMsg;
+ EFI_HTTP_CONNECT_REQUEST_DATA *ConnRequest;
//
// Initializations
//
- Url = 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;
+ ConnRequest = NULL;
if ((This == NULL) || (Token == NULL)) {
return EFI_INVALID_PARAMETER;
@@ -275,14 +288,27 @@ 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) && (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;
+ case HttpMethodConnect:
+ ConnRequest = (EFI_HTTP_CONNECT_REQUEST_DATA *)Request;
+ if (ConnRequest->ProxyUrl == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ break;
+ default:
+ return EFI_UNSUPPORTED;
+ }
}
HttpInstance = HTTP_INSTANCE_FROM_PROTOCOL (This);
@@ -337,7 +363,7 @@ EfiHttpRequest (
}
//
- // Parse the URI of the remote host.
+ // Parse the Request URI.
//
Url = HttpInstance->Url;
UrlLen = StrLen (Request->Url) + 1;
@@ -358,6 +384,29 @@ EfiHttpRequest (
UnicodeStrToAsciiStrS (Request->Url, Url, UrlLen);
//
+ // In case of HTTP Connect, parse proxy URI from Request.
+ //
+ if (Request->Method == HttpMethodConnect) {
+ ProxyUrl = HttpInstance->ProxyUrl;
+ ProxyUrlLen = StrLen (ConnRequest->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 (ConnRequest->ProxyUrl, ProxyUrl, ProxyUrlLen);
+ }
+
+ //
// From the information in Url, the HTTP instance will
// be able to determine whether to use http or https.
//
@@ -385,13 +434,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;
}
@@ -409,7 +471,7 @@ EfiHttpRequest (
}
}
- Status = HttpUrlGetPort (Url, UrlParser, &RemotePort);
+ Status = HttpUrlGetPort (ParseUrl, UrlParser, &RemotePort);
if (EFI_ERROR (Status)) {
if (HttpInstance->UseHttps) {
RemotePort = HTTPS_DEFAULT_PORT;
@@ -505,7 +567,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)) {
@@ -603,27 +665,74 @@ EfiHttpRequest (
//
// Create request message.
//
- FileUrl = Url;
- if ((Url != NULL) && (*FileUrl != '/')) {
+ if ((Request != NULL) && (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;
@@ -659,6 +768,10 @@ EfiHttpRequest (
DispatchDpc ();
+ if (HttpInstance->Method == HttpMethodConnect) {
+ HttpInstance->ProxyConnected = TRUE;
+ }
+
if (HostName != NULL) {
FreePool (HostName);
}
@@ -704,6 +817,14 @@ Error2:
}
Error1:
+ if (EndPointUrlMsg != NULL) {
+ FreePool (EndPointUrlMsg);
+ }
+
+ if (EndPointUrlParser != NULL) {
+ HttpUrlFreeParser (EndPointUrlParser);
+ }
+
if (HostName != NULL) {
FreePool (HostName);
}
diff --git a/NetworkPkg/HttpDxe/HttpProto.c b/NetworkPkg/HttpDxe/HttpProto.c
index 75eb068..4e9da97 100644
--- a/NetworkPkg/HttpDxe/HttpProto.c
+++ b/NetworkPkg/HttpDxe/HttpProto.c
@@ -852,6 +852,19 @@ HttpCleanProtocol (
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 e49d2a2..c4a0ac1 100644
--- a/NetworkPkg/HttpDxe/HttpProto.h
+++ b/NetworkPkg/HttpDxe/HttpProto.h
@@ -168,6 +168,14 @@ typedef struct _HTTP_PROTOCOL {
UINTN UrlLen;
//
+ // Proxy support
+ //
+ CHAR8 *ProxyUrl;
+ UINTN ProxyUrlLen;
+ BOOLEAN ProxyConnected;
+ CHAR8 *EndPointHostName;
+
+ //
// Https Support
//
BOOLEAN UseHttps;