TianoCore EDK2 master
Loading...
Searching...
No Matches
RedfishPlatformCredentialIpmiLib.c
Go to the documentation of this file.
1
14
15//
16// Global flag of controlling credential service
17//
18BOOLEAN mRedfishServiceStopped = FALSE;
19
37EFIAPI
41 )
42{
43 EFI_STATUS Status;
44
45 if ((ServiceStopType <= ServiceStopTypeNone) || (ServiceStopType >= ServiceStopTypeMax)) {
46 return EFI_INVALID_PARAMETER;
47 }
48
49 //
50 // Only stop credential service after leaving BIOS
51 //
52 if (ServiceStopType != ServiceStopTypeExitBootService) {
53 return EFI_UNSUPPORTED;
54 }
55
56 //
57 // Raise flag first
58 //
59 mRedfishServiceStopped = TRUE;
60
61 //
62 // Delete cached variable
63 //
65 if (EFI_ERROR (Status)) {
66 DEBUG ((DEBUG_ERROR, "%a: fail to remove bootstrap credential: %r\n", __func__, Status));
67 }
68
69 DEBUG ((DEBUG_MANAGEABILITY, "%a: bootstrap credential service stopped\n", __func__));
70
71 return EFI_SUCCESS;
72}
73
79VOID
80EFIAPI
83 )
84{
85 //
86 // Stop the credential support when system is about to enter OS.
87 //
89}
90
96VOID
97EFIAPI
100 )
101{
102 //
103 // Do nothing now.
104 // We can stop credential support when system reach end-of-dxe for security reason.
105 //
106}
107
133 IN BOOLEAN DisableBootstrapControl,
134 IN OUT CHAR8 *BootstrapUsername, OPTIONAL
135 IN UINTN BootstrapUsernameSize,
136 IN OUT CHAR8 *BootstrapPassword, OPTIONAL
137 IN UINTN BootstrapPasswordSize
138 )
139{
140 EFI_STATUS Status;
143 UINT32 ResponseSize;
144
145 //
146 // NULL buffer check
147 //
148 if (!DisableBootstrapControl && ((BootstrapUsername == NULL) || (BootstrapPassword == NULL))) {
149 return EFI_INVALID_PARAMETER;
150 }
151
152 if ((BootstrapUsernameSize != USERNAME_MAX_SIZE) || (BootstrapPasswordSize != PASSWORD_MAX_SIZE)) {
153 return EFI_INVALID_PARAMETER;
154 }
155
156 DEBUG ((DEBUG_VERBOSE, "%a: Disable bootstrap control: 0x%x\n", __func__, DisableBootstrapControl));
157
158 //
159 // IPMI callout to NetFn 2C, command 02
160 // Request data:
161 // Byte 1: REDFISH_IPMI_GROUP_EXTENSION
162 // Byte 2: DisableBootstrapControl
163 //
164 CommandData.GroupExtensionId = REDFISH_IPMI_GROUP_EXTENSION;
165 CommandData.DisableBootstrapControl = (DisableBootstrapControl ? REDFISH_IPMI_BOOTSTRAP_CREDENTIAL_DISABLE : REDFISH_IPMI_BOOTSTRAP_CREDENTIAL_ENABLE);
166
167 ResponseSize = sizeof (ResponseData);
168
169 //
170 // Response data:
171 // Byte 1 : Completion code
172 // Byte 2 : REDFISH_IPMI_GROUP_EXTENSION
173 // Byte 3-18 : Username
174 // Byte 19-34: Password
175 //
176 Status = IpmiSubmitCommand (
177 IPMI_NETFN_GROUP_EXT,
178 REDFISH_IPMI_GET_BOOTSTRAP_CREDENTIALS_CMD,
179 (UINT8 *)&CommandData,
180 sizeof (CommandData),
181 (UINT8 *)&ResponseData,
182 &ResponseSize
183 );
184
185 if (EFI_ERROR (Status)) {
186 DEBUG ((DEBUG_ERROR, "%a: IPMI transaction failure. Returning\n", __func__));
187 return Status;
188 } else {
189 if (ResponseData.CompletionCode != IPMI_COMP_CODE_NORMAL) {
190 if (ResponseData.CompletionCode == REDFISH_IPMI_COMP_CODE_BOOTSTRAP_CREDENTIAL_DISABLED) {
191 DEBUG ((DEBUG_ERROR, "%a: bootstrap credential support was disabled\n", __func__));
192 return EFI_ACCESS_DENIED;
193 }
194
195 DEBUG ((DEBUG_ERROR, "%a: Completion code = 0x%x. Returning\n", __func__, ResponseData.CompletionCode));
196 return EFI_PROTOCOL_ERROR;
197 } else if (ResponseData.GroupExtensionId != REDFISH_IPMI_GROUP_EXTENSION) {
198 DEBUG ((DEBUG_ERROR, "%a: Group Extension Response = 0x%x. Returning\n", __func__, ResponseData.GroupExtensionId));
199 return EFI_DEVICE_ERROR;
200 } else {
201 if (BootstrapUsername != NULL) {
202 CopyMem (BootstrapUsername, ResponseData.Username, USERNAME_MAX_LENGTH);
203 //
204 // Manually append null-terminator in case 16 characters username returned.
205 //
206 BootstrapUsername[USERNAME_MAX_LENGTH] = '\0';
207 }
208
209 if (BootstrapPassword != NULL) {
210 CopyMem (BootstrapPassword, ResponseData.Password, PASSWORD_MAX_LENGTH);
211 //
212 // Manually append null-terminator in case 16 characters password returned.
213 //
214 BootstrapPassword[PASSWORD_MAX_LENGTH] = '\0';
215 }
216 }
217 }
218
219 DEBUG ((DEBUG_MANAGEABILITY, "%a: get bootstrap credential via IPMI: %r\n", __func__, Status));
220
221 return Status;
222}
223
241 IN OUT CHAR8 *BootstrapUsername,
242 IN UINTN BootstrapUsernameSize,
243 IN OUT CHAR8 *BootstrapPassword,
244 IN UINTN BootstrapPasswordSize
245 )
246{
247 EFI_STATUS Status;
248 BOOTSTRAP_CREDENTIALS_VARIABLE *CredentialVariable;
249 VOID *Data;
250 UINTN DataSize;
251
252 if ((BootstrapUsername == NULL) || (BootstrapPassword == NULL)) {
253 return EFI_INVALID_PARAMETER;
254 }
255
256 if ((BootstrapUsernameSize != USERNAME_MAX_SIZE) || (BootstrapPasswordSize != PASSWORD_MAX_SIZE)) {
257 return EFI_INVALID_PARAMETER;
258 }
259
260 DataSize = 0;
261 Status = GetVariable2 (
262 CREDENTIAL_VARIABLE_NAME,
263 &gEfiRedfishVariableGuid,
264 (VOID *)&Data,
265 &DataSize
266 );
267 if (EFI_ERROR (Status)) {
268 return EFI_NOT_FOUND;
269 }
270
271 if (DataSize != sizeof (BOOTSTRAP_CREDENTIALS_VARIABLE)) {
272 DEBUG ((DEBUG_ERROR, "%a: data corruption. returned size: %d != structure size: %d\n", __func__, DataSize, sizeof (BOOTSTRAP_CREDENTIALS_VARIABLE)));
273 FreePool (Data);
274 return EFI_NOT_FOUND;
275 }
276
277 CredentialVariable = (BOOTSTRAP_CREDENTIALS_VARIABLE *)Data;
278
279 AsciiStrCpyS (BootstrapUsername, USERNAME_MAX_SIZE, CredentialVariable->Username);
280 AsciiStrCpyS (BootstrapPassword, PASSWORD_MAX_SIZE, CredentialVariable->Password);
281
282 ZeroMem (CredentialVariable->Username, USERNAME_MAX_SIZE);
283 ZeroMem (CredentialVariable->Password, PASSWORD_MAX_SIZE);
284
285 FreePool (Data);
286
287 DEBUG ((DEBUG_MANAGEABILITY, "%a: get bootstrap credential from variable\n", __func__));
288
289 return EFI_SUCCESS;
290}
291
306 IN CHAR8 *BootstrapUsername, OPTIONAL
307 IN CHAR8 *BootstrapPassword, OPTIONAL
308 IN BOOLEAN DeleteVariable
309 )
310{
311 EFI_STATUS Status;
312 BOOTSTRAP_CREDENTIALS_VARIABLE CredentialVariable;
313 VOID *Data;
314
315 if (!DeleteVariable && ((BootstrapUsername == NULL) || (BootstrapUsername[0] == '\0'))) {
316 return EFI_INVALID_PARAMETER;
317 }
318
319 if (!DeleteVariable && ((BootstrapPassword == NULL) || (BootstrapPassword[0] == '\0'))) {
320 return EFI_INVALID_PARAMETER;
321 }
322
323 //
324 // Delete variable
325 //
326 Status = GetVariable2 (
327 CREDENTIAL_VARIABLE_NAME,
328 &gEfiRedfishVariableGuid,
329 (VOID *)&Data,
330 NULL
331 );
332 if (!EFI_ERROR (Status)) {
333 FreePool (Data);
334 gRT->SetVariable (
335 CREDENTIAL_VARIABLE_NAME,
336 &gEfiRedfishVariableGuid,
337 EFI_VARIABLE_BOOTSERVICE_ACCESS,
338 0,
339 NULL
340 );
341 }
342
343 //
344 // This is request to delete credentials. We are done.
345 //
346 if (DeleteVariable) {
347 return EFI_SUCCESS;
348 }
349
350 ZeroMem (CredentialVariable.Username, USERNAME_MAX_SIZE);
351 ZeroMem (CredentialVariable.Password, PASSWORD_MAX_SIZE);
352
353 AsciiStrCpyS (CredentialVariable.Username, USERNAME_MAX_SIZE, BootstrapUsername);
354 AsciiStrCpyS (CredentialVariable.Password, PASSWORD_MAX_SIZE, BootstrapPassword);
355
356 Status = gRT->SetVariable (
357 CREDENTIAL_VARIABLE_NAME,
358 &gEfiRedfishVariableGuid,
359 EFI_VARIABLE_BOOTSERVICE_ACCESS,
361 (VOID *)&CredentialVariable
362 );
363
364 ZeroMem (CredentialVariable.Username, USERNAME_MAX_SIZE);
365 ZeroMem (CredentialVariable.Password, PASSWORD_MAX_SIZE);
366
367 return Status;
368}
369
395EFIAPI
398 OUT EDKII_REDFISH_AUTH_METHOD *AuthMethod,
399 OUT CHAR8 **UserId,
400 OUT CHAR8 **Password
401 )
402{
403 EFI_STATUS Status;
404 BOOLEAN DisableCredentialService;
405
406 if ((AuthMethod == NULL) || (UserId == NULL) || (Password == NULL)) {
407 return EFI_INVALID_PARAMETER;
408 }
409
410 *UserId = NULL;
411 *Password = NULL;
412 DisableCredentialService = PcdGetBool (PcdRedfishDisableBootstrapCredentialService);
413
414 if (mRedfishServiceStopped) {
415 DEBUG ((DEBUG_ERROR, "%a: credential service is stopped due to security reason\n", __func__));
416 return EFI_ACCESS_DENIED;
417 }
418
419 *AuthMethod = AuthMethodHttpBasic;
420
421 *UserId = AllocateZeroPool (sizeof (CHAR8) * USERNAME_MAX_SIZE);
422 if (*UserId == NULL) {
423 return EFI_OUT_OF_RESOURCES;
424 }
425
426 *Password = AllocateZeroPool (sizeof (CHAR8) * PASSWORD_MAX_SIZE);
427 if (*Password == NULL) {
428 return EFI_OUT_OF_RESOURCES;
429 }
430
431 //
432 // Get bootstrap credential from variable first
433 //
434 Status = GetBootstrapAccountCredentialsFromVariable (*UserId, USERNAME_MAX_SIZE, *Password, PASSWORD_MAX_SIZE);
435 if (!EFI_ERROR (Status)) {
436 return EFI_SUCCESS;
437 }
438
439 //
440 // Make a IPMI query
441 //
442 Status = GetBootstrapAccountCredentials (DisableCredentialService, *UserId, USERNAME_MAX_SIZE, *Password, PASSWORD_MAX_SIZE);
443 if (EFI_ERROR (Status)) {
444 DEBUG ((DEBUG_ERROR, "%a: fail to get bootstrap credential: %r\n", __func__, Status));
445 return Status;
446 }
447
448 if (DisableCredentialService) {
449 DEBUG ((DEBUG_MANAGEABILITY, "%a: credential bootstrapping control disabled\n", __func__));
450 }
451
452 Status = SetBootstrapAccountCredentialsToVariable (*UserId, *Password, FALSE);
453 if (EFI_ERROR (Status)) {
454 DEBUG ((DEBUG_ERROR, "%a: fail to cache bootstrap credential: %r\n", __func__, Status));
455 }
456
457 return EFI_SUCCESS;
458}
UINT64 UINTN
RETURN_STATUS EFIAPI AsciiStrCpyS(OUT CHAR8 *Destination, IN UINTN DestMax, IN CONST CHAR8 *Source)
Definition: SafeString.c:1797
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
VOID *EFIAPI ZeroMem(OUT VOID *Buffer, IN UINTN Length)
EDKII_REDFISH_CREDENTIAL_STOP_SERVICE_TYPE
@ ServiceStopTypeExitBootService
@ ServiceStopTypeNone
Stop Redfsih service without reason.
EDKII_REDFISH_AUTH_METHOD
@ AuthMethodHttpBasic
Basic authentication is required.
VOID *EFIAPI AllocateZeroPool(IN UINTN AllocationSize)
VOID EFIAPI FreePool(IN VOID *Buffer)
EFI_STATUS EFIAPI IpmiSubmitCommand(IN UINT8 NetFunction, IN UINT8 Command, IN UINT8 *RequestData, IN UINT32 RequestDataSize, OUT UINT8 *ResponseData, IN OUT UINT32 *ResponseDataSize)
EFI_RUNTIME_SERVICES * gRT
#define NULL
Definition: Base.h:319
#define TRUE
Definition: Base.h:301
#define FALSE
Definition: Base.h:307
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
#define DEBUG(Expression)
Definition: DebugLib.h:434
#define PcdGetBool(TokenName)
Definition: PcdLib.h:401
#define USERNAME_MAX_LENGTH
EFI_STATUS EFIAPI LibStopRedfishService(IN EDKII_REDFISH_CREDENTIAL_PROTOCOL *This, IN EDKII_REDFISH_CREDENTIAL_STOP_SERVICE_TYPE ServiceStopType)
VOID EFIAPI LibCredentialExitBootServicesNotify(IN EDKII_REDFISH_CREDENTIAL_PROTOCOL *This)
EFI_STATUS GetBootstrapAccountCredentials(IN BOOLEAN DisableBootstrapControl, IN OUT CHAR8 *BootstrapUsername, OPTIONAL IN UINTN BootstrapUsernameSize, IN OUT CHAR8 *BootstrapPassword, OPTIONAL IN UINTN BootstrapPasswordSize)
EFI_STATUS SetBootstrapAccountCredentialsToVariable(IN CHAR8 *BootstrapUsername, OPTIONAL IN CHAR8 *BootstrapPassword, OPTIONAL IN BOOLEAN DeleteVariable)
EFI_STATUS EFIAPI LibCredentialGetAuthInfo(IN EDKII_REDFISH_CREDENTIAL_PROTOCOL *This, OUT EDKII_REDFISH_AUTH_METHOD *AuthMethod, OUT CHAR8 **UserId, OUT CHAR8 **Password)
EFI_STATUS GetBootstrapAccountCredentialsFromVariable(IN OUT CHAR8 *BootstrapUsername, IN UINTN BootstrapUsernameSize, IN OUT CHAR8 *BootstrapPassword, IN UINTN BootstrapPasswordSize)
VOID EFIAPI LibCredentialEndOfDxeNotify(IN EDKII_REDFISH_CREDENTIAL_PROTOCOL *This)
EFI_STATUS EFIAPI DeleteVariable(IN CHAR16 *VariableName, IN EFI_GUID *VendorGuid)
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
EFI_STATUS EFIAPI GetVariable2(IN CONST CHAR16 *Name, IN CONST EFI_GUID *Guid, OUT VOID **Value, OUT UINTN *Size OPTIONAL)
Definition: UefiLib.c:1317