diff options
author | Saloni Kasbekar <saloni.kasbekar@intel.com> | 2022-12-16 16:38:42 +0100 |
---|---|---|
committer | mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> | 2025-03-13 00:34:01 +0000 |
commit | f5148b126710d1e9bbbded75a72740e5cbd92617 (patch) | |
tree | 2c8ae9b5bb066134c54090c61bdafde838fb5eae | |
parent | 2880ca12cea42142a3122dabfa2857a70a51759f (diff) | |
download | edk2-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.h | 2 | ||||
-rw-r--r-- | NetworkPkg/HttpDxe/HttpDxe.inf | 1 | ||||
-rw-r--r-- | NetworkPkg/HttpDxe/HttpImpl.c | 227 | ||||
-rw-r--r-- | NetworkPkg/HttpDxe/HttpProto.c | 13 | ||||
-rw-r--r-- | NetworkPkg/HttpDxe/HttpProto.h | 8 |
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;
|