* [PATCH v4 1/1] NetworkPkg/HttpBootDxe: Add Support for HTTP Boot Basic Authentication [not found] <cover.1658238840.git.saloni.kasbekar@intel.com> @ 2022-07-19 13:54 ` Saloni Kasbekar 2022-07-19 15:46 ` Maciej Rabeda [not found] ` <17034596F49CEB72.9127@groups.io> 0 siblings, 2 replies; 3+ messages in thread From: Saloni Kasbekar @ 2022-07-19 13:54 UTC (permalink / raw) To: devel; +Cc: Saloni Kasbekar, Maciej Rabeda, Wu Jiaxin, Siyuan Fu REF:https://bugzilla.tianocore.org/show_bug.cgi?id=2504 Add support for TLS Client Authentication using Basic Authentication for HTTP Boot 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> --- MdePkg/Include/IndustryStandard/Http11.h | 8 ++ MdePkg/Include/Protocol/HttpBootCallback.h | 6 +- NetworkPkg/HttpBootDxe/HttpBootClient.c | 99 +++++++++++++++++++++- NetworkPkg/HttpBootDxe/HttpBootClient.h | 6 +- NetworkPkg/HttpBootDxe/HttpBootDxe.h | 6 ++ NetworkPkg/HttpBootDxe/HttpBootImpl.c | 23 ++++- 6 files changed, 143 insertions(+), 5 deletions(-) diff --git a/MdePkg/Include/IndustryStandard/Http11.h b/MdePkg/Include/IndustryStandard/Http11.h index f1f113e04b69..2137ef1f1ac3 100644 --- a/MdePkg/Include/IndustryStandard/Http11.h +++ b/MdePkg/Include/IndustryStandard/Http11.h @@ -204,6 +204,14 @@ /// #define HTTP_HEADER_IF_NONE_MATCH "If-None-Match" +/// +/// The WWW-Authenticate Response Header +/// If a server receives a request for an access-protected object, and an +/// acceptable Authorization header is not sent, the server responds with +/// a "401 Unauthorized" status code, and a WWW-Authenticate header. +/// +#define HTTP_HEADER_WWW_AUTHENTICATE "WWW-Authenticate" + /// /// Authorization Request Header /// The Authorization field value consists of credentials diff --git a/MdePkg/Include/Protocol/HttpBootCallback.h b/MdePkg/Include/Protocol/HttpBootCallback.h index 926f6c1b3076..b56c631b1f4f 100644 --- a/MdePkg/Include/Protocol/HttpBootCallback.h +++ b/MdePkg/Include/Protocol/HttpBootCallback.h @@ -32,7 +32,7 @@ typedef enum { /// HttpBootDhcp6, /// - /// Data points to an EFI_HTTP_MESSAGE structure, whichcontians a HTTP request message + /// Data points to an EFI_HTTP_MESSAGE structure, which contains a HTTP request message /// to be transmitted. /// HttpBootHttpRequest, @@ -46,6 +46,10 @@ typedef enum { /// buffer of the entity body data. /// HttpBootHttpEntityBody, + /// + /// Data points to the authentication information to provide to the HTTP server. + /// + HttpBootHttpAuthInfo, HttpBootTypeMax } EFI_HTTP_BOOT_CALLBACK_DATA_TYPE; diff --git a/NetworkPkg/HttpBootDxe/HttpBootClient.c b/NetworkPkg/HttpBootDxe/HttpBootClient.c index 62e87238fef7..40f64fcb6bf8 100644 --- a/NetworkPkg/HttpBootDxe/HttpBootClient.c +++ b/NetworkPkg/HttpBootDxe/HttpBootClient.c @@ -922,6 +922,7 @@ HttpBootGetBootFileCallback ( @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 The server needs to authenticate the client. @retval Others Unexpected error happened. **/ @@ -951,6 +952,9 @@ HttpBootGetBootFile ( CHAR16 *Url; BOOLEAN IdentityMode; UINTN ReceivedSize; + CHAR8 BaseAuthValue[80]; + EFI_HTTP_HEADER *HttpHeader; + CHAR8 *Data; ASSERT (Private != NULL); ASSERT (Private->HttpCreated); @@ -1009,8 +1013,9 @@ HttpBootGetBootFile ( // Host // Accept // User-Agent + // [Authorization] // - HttpIoHeader = HttpIoCreateHeader (3); + HttpIoHeader = HttpIoCreateHeader ((Private->AuthData != NULL) ? 4 : 3); if (HttpIoHeader == NULL) { Status = EFI_OUT_OF_RESOURCES; goto ERROR_2; @@ -1063,6 +1068,35 @@ HttpBootGetBootFile ( goto ERROR_3; } + // + // Add HTTP header field 4: Authorization + // + if (Private->AuthData != NULL) { + ASSERT (HttpIoHeader->MaxHeaderCount == 4); + + if ((Private->AuthScheme != NULL) && (CompareMem (Private->AuthScheme, "Basic", 5) != 0)) { + Status = EFI_UNSUPPORTED; + goto ERROR_3; + } + + AsciiSPrint ( + BaseAuthValue, + sizeof (BaseAuthValue), + "%a %a", + "Basic", + Private->AuthData + ); + + Status = HttpIoSetHeader ( + HttpIoHeader, + HTTP_HEADER_AUTHORIZATION, + BaseAuthValue + ); + if (EFI_ERROR (Status)) { + goto ERROR_3; + } + } + // // 2.2 Build the rest of HTTP request info. // @@ -1111,6 +1145,7 @@ HttpBootGetBootFile ( goto ERROR_4; } + Data = NULL; Status = HttpIoRecvResponse ( &Private->HttpIo, TRUE, @@ -1121,6 +1156,68 @@ HttpBootGetBootFile ( StatusCode = HttpIo->RspToken.Message->Data.Response->StatusCode; HttpBootPrintErrorMessage (StatusCode); Status = ResponseData->Status; + if ((StatusCode == HTTP_STATUS_401_UNAUTHORIZED) || \ + (StatusCode == HTTP_STATUS_407_PROXY_AUTHENTICATION_REQUIRED)) + { + if ((Private->AuthData != NULL) || (Private->AuthScheme != NULL)) { + if (Private->AuthData != NULL) { + FreePool (Private->AuthData); + Private->AuthData = NULL; + } + + if (Private->AuthScheme != NULL) { + FreePool (Private->AuthScheme); + Private->AuthScheme = NULL; + } + + Status = EFI_ACCESS_DENIED; + goto ERROR_4; + } + + // + // Server indicates the user has to provide a user-id and password as a means of identification. + // + if (Private->HttpBootCallback != NULL) { + Data = AllocateZeroPool (sizeof (CHAR8) * HTTP_BOOT_AUTHENTICATION_INFO_MAX_LEN); + if (Data == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto ERROR_4; + } + + Status = Private->HttpBootCallback->Callback ( + Private->HttpBootCallback, + HttpBootHttpAuthInfo, + TRUE, + HTTP_BOOT_AUTHENTICATION_INFO_MAX_LEN, + Data + ); + if (EFI_ERROR (Status)) { + if (Data != NULL) { + FreePool (Data); + } + + goto ERROR_5; + } + + Private->AuthData = (CHAR8 *)Data; + } + + HttpHeader = HttpFindHeader ( + ResponseData->HeaderCount, + ResponseData->Headers, + HTTP_HEADER_WWW_AUTHENTICATE + ); + if (HttpHeader != NULL) { + Private->AuthScheme = AllocateZeroPool (AsciiStrLen (HttpHeader->FieldValue) + 1); + if (Private->AuthScheme == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + CopyMem (Private->AuthScheme, HttpHeader->FieldValue, AsciiStrLen (HttpHeader->FieldValue)); + } + + Status = EFI_ACCESS_DENIED; + } } goto ERROR_5; diff --git a/NetworkPkg/HttpBootDxe/HttpBootClient.h b/NetworkPkg/HttpBootDxe/HttpBootClient.h index 406529dfd927..2fba71367950 100644 --- a/NetworkPkg/HttpBootDxe/HttpBootClient.h +++ b/NetworkPkg/HttpBootDxe/HttpBootClient.h @@ -10,8 +10,9 @@ SPDX-License-Identifier: BSD-2-Clause-Patent #ifndef __EFI_HTTP_BOOT_HTTP_H__ #define __EFI_HTTP_BOOT_HTTP_H__ -#define HTTP_BOOT_BLOCK_SIZE 1500 -#define HTTP_USER_AGENT_EFI_HTTP_BOOT "UefiHttpBoot/1.0" +#define HTTP_BOOT_BLOCK_SIZE 1500 +#define HTTP_USER_AGENT_EFI_HTTP_BOOT "UefiHttpBoot/1.0" +#define HTTP_BOOT_AUTHENTICATION_INFO_MAX_LEN 255 // // Record the data length and start address of a data block. @@ -106,6 +107,7 @@ HttpBootCreateHttpIo ( @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 The server needs to authenticate the client. @retval Others Unexpected error happened. **/ diff --git a/NetworkPkg/HttpBootDxe/HttpBootDxe.h b/NetworkPkg/HttpBootDxe/HttpBootDxe.h index 5acbae9bfa76..5ff8ad4698b2 100644 --- a/NetworkPkg/HttpBootDxe/HttpBootDxe.h +++ b/NetworkPkg/HttpBootDxe/HttpBootDxe.h @@ -183,6 +183,12 @@ struct _HTTP_BOOT_PRIVATE_DATA { UINT64 ReceivedSize; UINT32 Percentage; + // + // Data for the server to authenticate the client + // + CHAR8 *AuthData; + CHAR8 *AuthScheme; + // // HII callback info block // diff --git a/NetworkPkg/HttpBootDxe/HttpBootImpl.c b/NetworkPkg/HttpBootDxe/HttpBootImpl.c index 3da585a29164..b4c61925b94f 100644 --- a/NetworkPkg/HttpBootDxe/HttpBootImpl.c +++ b/NetworkPkg/HttpBootDxe/HttpBootImpl.c @@ -360,7 +360,18 @@ HttpBootLoadFile ( 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. + // + 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. // @@ -489,6 +500,16 @@ HttpBootStop ( } } + if (Private->AuthData != NULL) { + FreePool (Private->AuthData); + Private->AuthData = NULL; + } + + if (Private->AuthScheme != NULL) { + FreePool (Private->AuthScheme); + Private->AuthScheme = NULL; + } + if (Private->DnsServerIp != NULL) { FreePool (Private->DnsServerIp); Private->DnsServerIp = NULL; -- 2.36.1.windows.1 ^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [PATCH v4 1/1] NetworkPkg/HttpBootDxe: Add Support for HTTP Boot Basic Authentication 2022-07-19 13:54 ` [PATCH v4 1/1] NetworkPkg/HttpBootDxe: Add Support for HTTP Boot Basic Authentication Saloni Kasbekar @ 2022-07-19 15:46 ` Maciej Rabeda [not found] ` <17034596F49CEB72.9127@groups.io> 1 sibling, 0 replies; 3+ messages in thread From: Maciej Rabeda @ 2022-07-19 15:46 UTC (permalink / raw) To: Saloni Kasbekar, devel; +Cc: Wu Jiaxin, Siyuan Fu Thank you for the patch. Reviewed-by: Maciej Rabeda <maciej.rabeda@linux.intel.com> On 19 lip 2022 15:54, Saloni Kasbekar wrote: > REF:https://bugzilla.tianocore.org/show_bug.cgi?id=2504 > > Add support for TLS Client Authentication using Basic Authentication > for HTTP Boot > > 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> > --- > MdePkg/Include/IndustryStandard/Http11.h | 8 ++ > MdePkg/Include/Protocol/HttpBootCallback.h | 6 +- > NetworkPkg/HttpBootDxe/HttpBootClient.c | 99 +++++++++++++++++++++- > NetworkPkg/HttpBootDxe/HttpBootClient.h | 6 +- > NetworkPkg/HttpBootDxe/HttpBootDxe.h | 6 ++ > NetworkPkg/HttpBootDxe/HttpBootImpl.c | 23 ++++- > 6 files changed, 143 insertions(+), 5 deletions(-) > > diff --git a/MdePkg/Include/IndustryStandard/Http11.h b/MdePkg/Include/IndustryStandard/Http11.h > index f1f113e04b69..2137ef1f1ac3 100644 > --- a/MdePkg/Include/IndustryStandard/Http11.h > +++ b/MdePkg/Include/IndustryStandard/Http11.h > @@ -204,6 +204,14 @@ > /// > #define HTTP_HEADER_IF_NONE_MATCH "If-None-Match" > > +/// > +/// The WWW-Authenticate Response Header > +/// If a server receives a request for an access-protected object, and an > +/// acceptable Authorization header is not sent, the server responds with > +/// a "401 Unauthorized" status code, and a WWW-Authenticate header. > +/// > +#define HTTP_HEADER_WWW_AUTHENTICATE "WWW-Authenticate" > + > /// > /// Authorization Request Header > /// The Authorization field value consists of credentials > diff --git a/MdePkg/Include/Protocol/HttpBootCallback.h b/MdePkg/Include/Protocol/HttpBootCallback.h > index 926f6c1b3076..b56c631b1f4f 100644 > --- a/MdePkg/Include/Protocol/HttpBootCallback.h > +++ b/MdePkg/Include/Protocol/HttpBootCallback.h > @@ -32,7 +32,7 @@ typedef enum { > /// > HttpBootDhcp6, > /// > - /// Data points to an EFI_HTTP_MESSAGE structure, whichcontians a HTTP request message > + /// Data points to an EFI_HTTP_MESSAGE structure, which contains a HTTP request message > /// to be transmitted. > /// > HttpBootHttpRequest, > @@ -46,6 +46,10 @@ typedef enum { > /// buffer of the entity body data. > /// > HttpBootHttpEntityBody, > + /// > + /// Data points to the authentication information to provide to the HTTP server. > + /// > + HttpBootHttpAuthInfo, > HttpBootTypeMax > } EFI_HTTP_BOOT_CALLBACK_DATA_TYPE; > > diff --git a/NetworkPkg/HttpBootDxe/HttpBootClient.c b/NetworkPkg/HttpBootDxe/HttpBootClient.c > index 62e87238fef7..40f64fcb6bf8 100644 > --- a/NetworkPkg/HttpBootDxe/HttpBootClient.c > +++ b/NetworkPkg/HttpBootDxe/HttpBootClient.c > @@ -922,6 +922,7 @@ HttpBootGetBootFileCallback ( > @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 The server needs to authenticate the client. > @retval Others Unexpected error happened. > > **/ > @@ -951,6 +952,9 @@ HttpBootGetBootFile ( > CHAR16 *Url; > BOOLEAN IdentityMode; > UINTN ReceivedSize; > + CHAR8 BaseAuthValue[80]; > + EFI_HTTP_HEADER *HttpHeader; > + CHAR8 *Data; > > ASSERT (Private != NULL); > ASSERT (Private->HttpCreated); > @@ -1009,8 +1013,9 @@ HttpBootGetBootFile ( > // Host > // Accept > // User-Agent > + // [Authorization] > // > - HttpIoHeader = HttpIoCreateHeader (3); > + HttpIoHeader = HttpIoCreateHeader ((Private->AuthData != NULL) ? 4 : 3); > if (HttpIoHeader == NULL) { > Status = EFI_OUT_OF_RESOURCES; > goto ERROR_2; > @@ -1063,6 +1068,35 @@ HttpBootGetBootFile ( > goto ERROR_3; > } > > + // > + // Add HTTP header field 4: Authorization > + // > + if (Private->AuthData != NULL) { > + ASSERT (HttpIoHeader->MaxHeaderCount == 4); > + > + if ((Private->AuthScheme != NULL) && (CompareMem (Private->AuthScheme, "Basic", 5) != 0)) { > + Status = EFI_UNSUPPORTED; > + goto ERROR_3; > + } > + > + AsciiSPrint ( > + BaseAuthValue, > + sizeof (BaseAuthValue), > + "%a %a", > + "Basic", > + Private->AuthData > + ); > + > + Status = HttpIoSetHeader ( > + HttpIoHeader, > + HTTP_HEADER_AUTHORIZATION, > + BaseAuthValue > + ); > + if (EFI_ERROR (Status)) { > + goto ERROR_3; > + } > + } > + > // > // 2.2 Build the rest of HTTP request info. > // > @@ -1111,6 +1145,7 @@ HttpBootGetBootFile ( > goto ERROR_4; > } > > + Data = NULL; > Status = HttpIoRecvResponse ( > &Private->HttpIo, > TRUE, > @@ -1121,6 +1156,68 @@ HttpBootGetBootFile ( > StatusCode = HttpIo->RspToken.Message->Data.Response->StatusCode; > HttpBootPrintErrorMessage (StatusCode); > Status = ResponseData->Status; > + if ((StatusCode == HTTP_STATUS_401_UNAUTHORIZED) || \ > + (StatusCode == HTTP_STATUS_407_PROXY_AUTHENTICATION_REQUIRED)) > + { > + if ((Private->AuthData != NULL) || (Private->AuthScheme != NULL)) { > + if (Private->AuthData != NULL) { > + FreePool (Private->AuthData); > + Private->AuthData = NULL; > + } > + > + if (Private->AuthScheme != NULL) { > + FreePool (Private->AuthScheme); > + Private->AuthScheme = NULL; > + } > + > + Status = EFI_ACCESS_DENIED; > + goto ERROR_4; > + } > + > + // > + // Server indicates the user has to provide a user-id and password as a means of identification. > + // > + if (Private->HttpBootCallback != NULL) { > + Data = AllocateZeroPool (sizeof (CHAR8) * HTTP_BOOT_AUTHENTICATION_INFO_MAX_LEN); > + if (Data == NULL) { > + Status = EFI_OUT_OF_RESOURCES; > + goto ERROR_4; > + } > + > + Status = Private->HttpBootCallback->Callback ( > + Private->HttpBootCallback, > + HttpBootHttpAuthInfo, > + TRUE, > + HTTP_BOOT_AUTHENTICATION_INFO_MAX_LEN, > + Data > + ); > + if (EFI_ERROR (Status)) { > + if (Data != NULL) { > + FreePool (Data); > + } > + > + goto ERROR_5; > + } > + > + Private->AuthData = (CHAR8 *)Data; > + } > + > + HttpHeader = HttpFindHeader ( > + ResponseData->HeaderCount, > + ResponseData->Headers, > + HTTP_HEADER_WWW_AUTHENTICATE > + ); > + if (HttpHeader != NULL) { > + Private->AuthScheme = AllocateZeroPool (AsciiStrLen (HttpHeader->FieldValue) + 1); > + if (Private->AuthScheme == NULL) { > + return EFI_OUT_OF_RESOURCES; > + } > + > + CopyMem (Private->AuthScheme, HttpHeader->FieldValue, AsciiStrLen (HttpHeader->FieldValue)); > + } > + > + Status = EFI_ACCESS_DENIED; > + } > } > > goto ERROR_5; > diff --git a/NetworkPkg/HttpBootDxe/HttpBootClient.h b/NetworkPkg/HttpBootDxe/HttpBootClient.h > index 406529dfd927..2fba71367950 100644 > --- a/NetworkPkg/HttpBootDxe/HttpBootClient.h > +++ b/NetworkPkg/HttpBootDxe/HttpBootClient.h > @@ -10,8 +10,9 @@ SPDX-License-Identifier: BSD-2-Clause-Patent > #ifndef __EFI_HTTP_BOOT_HTTP_H__ > #define __EFI_HTTP_BOOT_HTTP_H__ > > -#define HTTP_BOOT_BLOCK_SIZE 1500 > -#define HTTP_USER_AGENT_EFI_HTTP_BOOT "UefiHttpBoot/1.0" > +#define HTTP_BOOT_BLOCK_SIZE 1500 > +#define HTTP_USER_AGENT_EFI_HTTP_BOOT "UefiHttpBoot/1.0" > +#define HTTP_BOOT_AUTHENTICATION_INFO_MAX_LEN 255 > > // > // Record the data length and start address of a data block. > @@ -106,6 +107,7 @@ HttpBootCreateHttpIo ( > @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 The server needs to authenticate the client. > @retval Others Unexpected error happened. > > **/ > diff --git a/NetworkPkg/HttpBootDxe/HttpBootDxe.h b/NetworkPkg/HttpBootDxe/HttpBootDxe.h > index 5acbae9bfa76..5ff8ad4698b2 100644 > --- a/NetworkPkg/HttpBootDxe/HttpBootDxe.h > +++ b/NetworkPkg/HttpBootDxe/HttpBootDxe.h > @@ -183,6 +183,12 @@ struct _HTTP_BOOT_PRIVATE_DATA { > UINT64 ReceivedSize; > UINT32 Percentage; > > + // > + // Data for the server to authenticate the client > + // > + CHAR8 *AuthData; > + CHAR8 *AuthScheme; > + > // > // HII callback info block > // > diff --git a/NetworkPkg/HttpBootDxe/HttpBootImpl.c b/NetworkPkg/HttpBootDxe/HttpBootImpl.c > index 3da585a29164..b4c61925b94f 100644 > --- a/NetworkPkg/HttpBootDxe/HttpBootImpl.c > +++ b/NetworkPkg/HttpBootDxe/HttpBootImpl.c > @@ -360,7 +360,18 @@ HttpBootLoadFile ( > 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. > + // > + 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. > // > @@ -489,6 +500,16 @@ HttpBootStop ( > } > } > > + if (Private->AuthData != NULL) { > + FreePool (Private->AuthData); > + Private->AuthData = NULL; > + } > + > + if (Private->AuthScheme != NULL) { > + FreePool (Private->AuthScheme); > + Private->AuthScheme = NULL; > + } > + > if (Private->DnsServerIp != NULL) { > FreePool (Private->DnsServerIp); > Private->DnsServerIp = NULL; ^ permalink raw reply [flat|nested] 3+ messages in thread
[parent not found: <17034596F49CEB72.9127@groups.io>]
* Re: [edk2-devel] [PATCH v4 1/1] NetworkPkg/HttpBootDxe: Add Support for HTTP Boot Basic Authentication [not found] ` <17034596F49CEB72.9127@groups.io> @ 2022-07-19 19:29 ` Maciej Rabeda 0 siblings, 0 replies; 3+ messages in thread From: Maciej Rabeda @ 2022-07-19 19:29 UTC (permalink / raw) To: Saloni Kasbekar, devel; +Cc: Wu Jiaxin, Siyuan Fu Change merged. PR: https://github.com/tianocore/edk2/pull/3103 Commit: https://github.com/tianocore/edk2/commit/671b0cea510ad6de02ee9d6dbdf8f9bbb881f35d On 19 lip 2022 17:46, Maciej Rabeda wrote: > Thank you for the patch. > > Reviewed-by: Maciej Rabeda <maciej.rabeda@linux.intel.com> > > On 19 lip 2022 15:54, Saloni Kasbekar wrote: >> REF:https://bugzilla.tianocore.org/show_bug.cgi?id=2504 >> >> Add support for TLS Client Authentication using Basic Authentication >> for HTTP Boot >> >> 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> >> --- >> MdePkg/Include/IndustryStandard/Http11.h | 8 ++ >> MdePkg/Include/Protocol/HttpBootCallback.h | 6 +- >> NetworkPkg/HttpBootDxe/HttpBootClient.c | 99 +++++++++++++++++++++- >> NetworkPkg/HttpBootDxe/HttpBootClient.h | 6 +- >> NetworkPkg/HttpBootDxe/HttpBootDxe.h | 6 ++ >> NetworkPkg/HttpBootDxe/HttpBootImpl.c | 23 ++++- >> 6 files changed, 143 insertions(+), 5 deletions(-) >> >> diff --git a/MdePkg/Include/IndustryStandard/Http11.h >> b/MdePkg/Include/IndustryStandard/Http11.h >> index f1f113e04b69..2137ef1f1ac3 100644 >> --- a/MdePkg/Include/IndustryStandard/Http11.h >> +++ b/MdePkg/Include/IndustryStandard/Http11.h >> @@ -204,6 +204,14 @@ >> /// >> #define HTTP_HEADER_IF_NONE_MATCH "If-None-Match" >> +/// >> +/// The WWW-Authenticate Response Header >> +/// If a server receives a request for an access-protected object, >> and an >> +/// acceptable Authorization header is not sent, the server responds >> with >> +/// a "401 Unauthorized" status code, and a WWW-Authenticate header. >> +/// >> +#define HTTP_HEADER_WWW_AUTHENTICATE "WWW-Authenticate" >> + >> /// >> /// Authorization Request Header >> /// The Authorization field value consists of credentials >> diff --git a/MdePkg/Include/Protocol/HttpBootCallback.h >> b/MdePkg/Include/Protocol/HttpBootCallback.h >> index 926f6c1b3076..b56c631b1f4f 100644 >> --- a/MdePkg/Include/Protocol/HttpBootCallback.h >> +++ b/MdePkg/Include/Protocol/HttpBootCallback.h >> @@ -32,7 +32,7 @@ typedef enum { >> /// >> HttpBootDhcp6, >> /// >> - /// Data points to an EFI_HTTP_MESSAGE structure, whichcontians a >> HTTP request message >> + /// Data points to an EFI_HTTP_MESSAGE structure, which contains a >> HTTP request message >> /// to be transmitted. >> /// >> HttpBootHttpRequest, >> @@ -46,6 +46,10 @@ typedef enum { >> /// buffer of the entity body data. >> /// >> HttpBootHttpEntityBody, >> + /// >> + /// Data points to the authentication information to provide to >> the HTTP server. >> + /// >> + HttpBootHttpAuthInfo, >> HttpBootTypeMax >> } EFI_HTTP_BOOT_CALLBACK_DATA_TYPE; >> diff --git a/NetworkPkg/HttpBootDxe/HttpBootClient.c >> b/NetworkPkg/HttpBootDxe/HttpBootClient.c >> index 62e87238fef7..40f64fcb6bf8 100644 >> --- a/NetworkPkg/HttpBootDxe/HttpBootClient.c >> +++ b/NetworkPkg/HttpBootDxe/HttpBootClient.c >> @@ -922,6 +922,7 @@ HttpBootGetBootFileCallback ( >> @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 The server needs to authenticate >> the client. >> @retval Others Unexpected error happened. >> **/ >> @@ -951,6 +952,9 @@ HttpBootGetBootFile ( >> CHAR16 *Url; >> BOOLEAN IdentityMode; >> UINTN ReceivedSize; >> + CHAR8 BaseAuthValue[80]; >> + EFI_HTTP_HEADER *HttpHeader; >> + CHAR8 *Data; >> ASSERT (Private != NULL); >> ASSERT (Private->HttpCreated); >> @@ -1009,8 +1013,9 @@ HttpBootGetBootFile ( >> // Host >> // Accept >> // User-Agent >> + // [Authorization] >> // >> - HttpIoHeader = HttpIoCreateHeader (3); >> + HttpIoHeader = HttpIoCreateHeader ((Private->AuthData != NULL) ? 4 >> : 3); >> if (HttpIoHeader == NULL) { >> Status = EFI_OUT_OF_RESOURCES; >> goto ERROR_2; >> @@ -1063,6 +1068,35 @@ HttpBootGetBootFile ( >> goto ERROR_3; >> } >> + // >> + // Add HTTP header field 4: Authorization >> + // >> + if (Private->AuthData != NULL) { >> + ASSERT (HttpIoHeader->MaxHeaderCount == 4); >> + >> + if ((Private->AuthScheme != NULL) && (CompareMem >> (Private->AuthScheme, "Basic", 5) != 0)) { >> + Status = EFI_UNSUPPORTED; >> + goto ERROR_3; >> + } >> + >> + AsciiSPrint ( >> + BaseAuthValue, >> + sizeof (BaseAuthValue), >> + "%a %a", >> + "Basic", >> + Private->AuthData >> + ); >> + >> + Status = HttpIoSetHeader ( >> + HttpIoHeader, >> + HTTP_HEADER_AUTHORIZATION, >> + BaseAuthValue >> + ); >> + if (EFI_ERROR (Status)) { >> + goto ERROR_3; >> + } >> + } >> + >> // >> // 2.2 Build the rest of HTTP request info. >> // >> @@ -1111,6 +1145,7 @@ HttpBootGetBootFile ( >> goto ERROR_4; >> } >> + Data = NULL; >> Status = HttpIoRecvResponse ( >> &Private->HttpIo, >> TRUE, >> @@ -1121,6 +1156,68 @@ HttpBootGetBootFile ( >> StatusCode = >> HttpIo->RspToken.Message->Data.Response->StatusCode; >> HttpBootPrintErrorMessage (StatusCode); >> Status = ResponseData->Status; >> + if ((StatusCode == HTTP_STATUS_401_UNAUTHORIZED) || \ >> + (StatusCode == >> HTTP_STATUS_407_PROXY_AUTHENTICATION_REQUIRED)) >> + { >> + if ((Private->AuthData != NULL) || (Private->AuthScheme != >> NULL)) { >> + if (Private->AuthData != NULL) { >> + FreePool (Private->AuthData); >> + Private->AuthData = NULL; >> + } >> + >> + if (Private->AuthScheme != NULL) { >> + FreePool (Private->AuthScheme); >> + Private->AuthScheme = NULL; >> + } >> + >> + Status = EFI_ACCESS_DENIED; >> + goto ERROR_4; >> + } >> + >> + // >> + // Server indicates the user has to provide a user-id and >> password as a means of identification. >> + // >> + if (Private->HttpBootCallback != NULL) { >> + Data = AllocateZeroPool (sizeof (CHAR8) * >> HTTP_BOOT_AUTHENTICATION_INFO_MAX_LEN); >> + if (Data == NULL) { >> + Status = EFI_OUT_OF_RESOURCES; >> + goto ERROR_4; >> + } >> + >> + Status = Private->HttpBootCallback->Callback ( >> + Private->HttpBootCallback, >> + HttpBootHttpAuthInfo, >> + TRUE, >> + HTTP_BOOT_AUTHENTICATION_INFO_MAX_LEN, >> + Data >> + ); >> + if (EFI_ERROR (Status)) { >> + if (Data != NULL) { >> + FreePool (Data); >> + } >> + >> + goto ERROR_5; >> + } >> + >> + Private->AuthData = (CHAR8 *)Data; >> + } >> + >> + HttpHeader = HttpFindHeader ( >> + ResponseData->HeaderCount, >> + ResponseData->Headers, >> + HTTP_HEADER_WWW_AUTHENTICATE >> + ); >> + if (HttpHeader != NULL) { >> + Private->AuthScheme = AllocateZeroPool (AsciiStrLen >> (HttpHeader->FieldValue) + 1); >> + if (Private->AuthScheme == NULL) { >> + return EFI_OUT_OF_RESOURCES; >> + } >> + >> + CopyMem (Private->AuthScheme, HttpHeader->FieldValue, >> AsciiStrLen (HttpHeader->FieldValue)); >> + } >> + >> + Status = EFI_ACCESS_DENIED; >> + } >> } >> goto ERROR_5; >> diff --git a/NetworkPkg/HttpBootDxe/HttpBootClient.h >> b/NetworkPkg/HttpBootDxe/HttpBootClient.h >> index 406529dfd927..2fba71367950 100644 >> --- a/NetworkPkg/HttpBootDxe/HttpBootClient.h >> +++ b/NetworkPkg/HttpBootDxe/HttpBootClient.h >> @@ -10,8 +10,9 @@ SPDX-License-Identifier: BSD-2-Clause-Patent >> #ifndef __EFI_HTTP_BOOT_HTTP_H__ >> #define __EFI_HTTP_BOOT_HTTP_H__ >> -#define HTTP_BOOT_BLOCK_SIZE 1500 >> -#define HTTP_USER_AGENT_EFI_HTTP_BOOT "UefiHttpBoot/1.0" >> +#define HTTP_BOOT_BLOCK_SIZE 1500 >> +#define HTTP_USER_AGENT_EFI_HTTP_BOOT "UefiHttpBoot/1.0" >> +#define HTTP_BOOT_AUTHENTICATION_INFO_MAX_LEN 255 >> // >> // Record the data length and start address of a data block. >> @@ -106,6 +107,7 @@ HttpBootCreateHttpIo ( >> @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 The server needs to authenticate >> the client. >> @retval Others Unexpected error happened. >> **/ >> diff --git a/NetworkPkg/HttpBootDxe/HttpBootDxe.h >> b/NetworkPkg/HttpBootDxe/HttpBootDxe.h >> index 5acbae9bfa76..5ff8ad4698b2 100644 >> --- a/NetworkPkg/HttpBootDxe/HttpBootDxe.h >> +++ b/NetworkPkg/HttpBootDxe/HttpBootDxe.h >> @@ -183,6 +183,12 @@ struct _HTTP_BOOT_PRIVATE_DATA { >> UINT64 ReceivedSize; >> UINT32 Percentage; >> + // >> + // Data for the server to authenticate the client >> + // >> + CHAR8 *AuthData; >> + CHAR8 *AuthScheme; >> + >> // >> // HII callback info block >> // >> diff --git a/NetworkPkg/HttpBootDxe/HttpBootImpl.c >> b/NetworkPkg/HttpBootDxe/HttpBootImpl.c >> index 3da585a29164..b4c61925b94f 100644 >> --- a/NetworkPkg/HttpBootDxe/HttpBootImpl.c >> +++ b/NetworkPkg/HttpBootDxe/HttpBootImpl.c >> @@ -360,7 +360,18 @@ HttpBootLoadFile ( >> 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. >> + // >> + 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. >> // >> @@ -489,6 +500,16 @@ HttpBootStop ( >> } >> } >> + if (Private->AuthData != NULL) { >> + FreePool (Private->AuthData); >> + Private->AuthData = NULL; >> + } >> + >> + if (Private->AuthScheme != NULL) { >> + FreePool (Private->AuthScheme); >> + Private->AuthScheme = NULL; >> + } >> + >> if (Private->DnsServerIp != NULL) { >> FreePool (Private->DnsServerIp); >> Private->DnsServerIp = NULL; > > > > > ^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2022-07-19 19:29 UTC | newest] Thread overview: 3+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- [not found] <cover.1658238840.git.saloni.kasbekar@intel.com> 2022-07-19 13:54 ` [PATCH v4 1/1] NetworkPkg/HttpBootDxe: Add Support for HTTP Boot Basic Authentication Saloni Kasbekar 2022-07-19 15:46 ` Maciej Rabeda [not found] ` <17034596F49CEB72.9127@groups.io> 2022-07-19 19:29 ` [edk2-devel] " Maciej Rabeda
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox