1 | /** @file
|
---|
2 | RestExDxe support functions implementation.
|
---|
3 |
|
---|
4 | Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
|
---|
5 | (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
|
---|
6 |
|
---|
7 | SPDX-License-Identifier: BSD-2-Clause-Patent
|
---|
8 |
|
---|
9 | **/
|
---|
10 | #include <Uefi.h>
|
---|
11 | #include "RedfishRestExInternal.h"
|
---|
12 |
|
---|
13 | /**
|
---|
14 | Create a new TLS session becuase the previous on is closed.
|
---|
15 | status.
|
---|
16 |
|
---|
17 | @param[in] Instance Pointer to EFI_REST_EX_PROTOCOL instance for a particular
|
---|
18 | REST service.
|
---|
19 | @retval EFI_SUCCESS operation succeeded.
|
---|
20 | @retval EFI_ERROR Other errors.
|
---|
21 |
|
---|
22 | **/
|
---|
23 | EFI_STATUS
|
---|
24 | ResetHttpTslSession (
|
---|
25 | IN RESTEX_INSTANCE *Instance
|
---|
26 | )
|
---|
27 | {
|
---|
28 | EFI_STATUS Status;
|
---|
29 |
|
---|
30 | DEBUG ((DEBUG_INFO, "%a: TCP connection is finished. Could be TSL session closure, reset HTTP instance for the new TLS session.\n", __FUNCTION__));
|
---|
31 |
|
---|
32 | Status = Instance->HttpIo.Http->Configure (Instance->HttpIo.Http, NULL);
|
---|
33 | if (EFI_ERROR (Status)) {
|
---|
34 | DEBUG ((DEBUG_ERROR, "%a: Error to reset HTTP instance.\n", __FUNCTION__));
|
---|
35 | return Status;
|
---|
36 | }
|
---|
37 | Status = Instance->HttpIo.Http->Configure(Instance->HttpIo.Http, &((EFI_REST_EX_HTTP_CONFIG_DATA *)Instance->ConfigData)->HttpConfigData);
|
---|
38 | if (EFI_ERROR (Status)) {
|
---|
39 | DEBUG ((DEBUG_ERROR, "%a: Error to re-initiate HTTP instance.\n", __FUNCTION__));
|
---|
40 | }
|
---|
41 | return Status;
|
---|
42 | }
|
---|
43 | /**
|
---|
44 | This function check
|
---|
45 |
|
---|
46 | @param[in] Instance Pointer to EFI_REST_EX_PROTOCOL instance for a particular
|
---|
47 | REST service.
|
---|
48 | @param[in] HttpIoReceiveStatus This is the status return from HttpIoRecvResponse
|
---|
49 |
|
---|
50 | @retval EFI_SUCCESS The payload receive from Redfish service in sucessfully.
|
---|
51 | @retval EFI_NOT_READY May need to resend the HTTP request.
|
---|
52 | @retval EFI_DEVICE_ERROR Something wrong and can't be resolved.
|
---|
53 | @retval Others Other errors as indicated.
|
---|
54 |
|
---|
55 | **/
|
---|
56 | EFI_STATUS
|
---|
57 | RedfishCheckHttpReceiveStatus (
|
---|
58 | IN RESTEX_INSTANCE *Instance,
|
---|
59 | IN EFI_STATUS HttpIoReceiveStatus
|
---|
60 | )
|
---|
61 | {
|
---|
62 | EFI_STATUS Status;
|
---|
63 | EFI_STATUS ReturnStatus;
|
---|
64 |
|
---|
65 | if (!EFI_ERROR (HttpIoReceiveStatus)){
|
---|
66 | ReturnStatus = EFI_SUCCESS;
|
---|
67 | } else if (EFI_ERROR (HttpIoReceiveStatus) && HttpIoReceiveStatus != EFI_CONNECTION_FIN) {
|
---|
68 | if ((Instance->Flags & RESTEX_INSTANCE_FLAGS_TCP_ERROR_RETRY) == 0) {
|
---|
69 | DEBUG ((DEBUG_ERROR, "%a: TCP error, reset HTTP session.\n", __FUNCTION__));
|
---|
70 | Instance->Flags |= RESTEX_INSTANCE_FLAGS_TCP_ERROR_RETRY;
|
---|
71 | gBS->Stall (500);
|
---|
72 | Status = ResetHttpTslSession (Instance);
|
---|
73 | if (EFI_ERROR (Status)) {
|
---|
74 | DEBUG ((DEBUG_ERROR, "%a: Reset HTTP instance fail.\n", __FUNCTION__));
|
---|
75 | ReturnStatus = EFI_DEVICE_ERROR;
|
---|
76 | } else {
|
---|
77 | return EFI_NOT_READY;
|
---|
78 | }
|
---|
79 | } else {
|
---|
80 | ReturnStatus = EFI_DEVICE_ERROR;
|
---|
81 | }
|
---|
82 | } else {
|
---|
83 | if (HttpIoReceiveStatus == EFI_CONNECTION_FIN) {
|
---|
84 | if ((Instance->Flags & RESTEX_INSTANCE_FLAGS_TLS_RETRY) != 0) {
|
---|
85 | DEBUG ((DEBUG_ERROR, "%a: REST_EX Send and receive fail even with a new TLS session.\n", __FUNCTION__));
|
---|
86 | ReturnStatus = EFI_DEVICE_ERROR;
|
---|
87 | }
|
---|
88 | Instance->Flags |= RESTEX_INSTANCE_FLAGS_TLS_RETRY;
|
---|
89 | Status = ResetHttpTslSession (Instance);
|
---|
90 | if (EFI_ERROR (Status)) {
|
---|
91 | DEBUG ((DEBUG_ERROR, "%a: Reset HTTP instance fail.\n", __FUNCTION__));
|
---|
92 | ReturnStatus = EFI_DEVICE_ERROR;
|
---|
93 | }
|
---|
94 | return EFI_NOT_READY;
|
---|
95 | }
|
---|
96 | }
|
---|
97 | //
|
---|
98 | // Clean TLS new session retry and error try flags.
|
---|
99 | //
|
---|
100 | Instance->Flags &= ~ (RESTEX_INSTANCE_FLAGS_TLS_RETRY | RESTEX_INSTANCE_FLAGS_TCP_ERROR_RETRY);
|
---|
101 | return ReturnStatus;
|
---|
102 | }
|
---|
103 |
|
---|
104 | /**
|
---|
105 | This function send the HTTP request without body to see
|
---|
106 | if the write to URL is permitted by Redfish service. This function
|
---|
107 | checks if the HTTP request has Content-length in HTTP header. If yes,
|
---|
108 | set HTTP body to NULL and then send to service. Check the HTTP status
|
---|
109 | for the firther actions.
|
---|
110 |
|
---|
111 | @param[in] This Pointer to EFI_REST_EX_PROTOCOL instance for a particular
|
---|
112 | REST service.
|
---|
113 | @param[in] RequestMessage Pointer to the HTTP request data for this resource
|
---|
114 | @param[in] PreservedRequestHeaders The pointer to save the request headers
|
---|
115 | @param[in] ItsWrite This is write method to URL.
|
---|
116 |
|
---|
117 | @retval EFI_INVALID_PARAMETER Improper given parameters.
|
---|
118 | @retval EFI_SUCCESS This HTTP request is free to send to Redfish service.
|
---|
119 | @retval EFI_OUT_OF_RESOURCES NOt enough memory to process.
|
---|
120 | @retval EFI_ACCESS_DENIED Not allowed to write to this URL.
|
---|
121 |
|
---|
122 | @retval Others Other errors as indicated.
|
---|
123 |
|
---|
124 | **/
|
---|
125 | EFI_STATUS
|
---|
126 | RedfishHttpAddExpectation (
|
---|
127 | IN EFI_REST_EX_PROTOCOL *This,
|
---|
128 | IN EFI_HTTP_MESSAGE *RequestMessage,
|
---|
129 | IN EFI_HTTP_HEADER **PreservedRequestHeaders,
|
---|
130 | IN BOOLEAN *ItsWrite
|
---|
131 | )
|
---|
132 | {
|
---|
133 | EFI_HTTP_HEADER *NewHeaders;
|
---|
134 |
|
---|
135 | if (This == NULL || RequestMessage == NULL) {
|
---|
136 | return EFI_INVALID_PARAMETER;
|
---|
137 | }
|
---|
138 |
|
---|
139 | *ItsWrite = FALSE;
|
---|
140 | if (PreservedRequestHeaders != NULL) {
|
---|
141 | *PreservedRequestHeaders = RequestMessage->Headers;
|
---|
142 | }
|
---|
143 |
|
---|
144 | if ((RequestMessage->Data.Request->Method != HttpMethodPut) && (RequestMessage->Data.Request->Method != HttpMethodPost) &&
|
---|
145 | (RequestMessage->Data.Request->Method != HttpMethodPatch)) {
|
---|
146 | return EFI_SUCCESS;
|
---|
147 | }
|
---|
148 | *ItsWrite = TRUE;
|
---|
149 |
|
---|
150 | NewHeaders = AllocateZeroPool((RequestMessage->HeaderCount + 1) * sizeof(EFI_HTTP_HEADER));
|
---|
151 | CopyMem ((VOID*)NewHeaders, (VOID *)RequestMessage->Headers, RequestMessage->HeaderCount * sizeof (EFI_HTTP_HEADER));
|
---|
152 | HttpSetFieldNameAndValue (NewHeaders + RequestMessage->HeaderCount, HTTP_HEADER_EXPECT, HTTP_EXPECT_100_CONTINUE);
|
---|
153 | RequestMessage->HeaderCount ++;
|
---|
154 | RequestMessage->Headers = NewHeaders;
|
---|
155 | return EFI_SUCCESS;
|
---|
156 | }
|
---|
157 |
|
---|