public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
* [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

* 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