1 /* 2 // Copyright (c) 2018 Intel Corporation 3 // 4 // Licensed under the Apache License, Version 2.0 (the "License"); 5 // you may not use this file except in compliance with the License. 6 // You may obtain a copy of the License at 7 // 8 // http://www.apache.org/licenses/LICENSE-2.0 9 // 10 // Unless required by applicable law or agreed to in writing, software 11 // distributed under the License is distributed on an "AS IS" BASIS, 12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 // See the License for the specific language governing permissions and 14 // limitations under the License. 15 */ 16 17 #include "usercommands.hpp" 18 19 #include "apphandler.hpp" 20 #include "channel_layer.hpp" 21 #include "user_layer.hpp" 22 23 #include <security/pam_appl.h> 24 25 #include <ipmid/api.hpp> 26 #include <phosphor-logging/log.hpp> 27 #include <regex> 28 29 namespace ipmi 30 { 31 32 using namespace phosphor::logging; 33 34 static constexpr uint8_t disableUser = 0x00; 35 static constexpr uint8_t enableUser = 0x01; 36 static constexpr uint8_t setPassword = 0x02; 37 static constexpr uint8_t testPassword = 0x03; 38 static constexpr uint8_t passwordKeySize20 = 1; 39 static constexpr uint8_t passwordKeySize16 = 0; 40 static constexpr uint8_t enableOperation = 0x00; 41 static constexpr uint8_t disableOperation = 0x01; 42 43 /** @struct SetUserNameReq 44 * 45 * Structure for set user name request command (refer spec sec 22.28) 46 */ 47 struct SetUserNameReq 48 { 49 #if BYTE_ORDER == LITTLE_ENDIAN 50 uint8_t userId : 6; 51 uint8_t reserved1 : 2; 52 #endif 53 #if BYTE_ORDER == BIG_ENDIAN 54 uint8_t reserved1 : 2; 55 uint8_t userId : 6; 56 #endif 57 uint8_t userName[16]; 58 } __attribute__((packed)); 59 60 /** @struct GetUserNameReq 61 * 62 * Structure for get user name request command (refer spec sec 22.29) 63 */ 64 struct GetUserNameReq 65 { 66 #if BYTE_ORDER == LITTLE_ENDIAN 67 uint8_t userId : 6; 68 uint8_t reserved1 : 2; 69 #endif 70 #if BYTE_ORDER == BIG_ENDIAN 71 uint8_t reserved1 : 2; 72 uint8_t userId : 6; 73 #endif 74 } __attribute__((packed)); 75 76 /** @struct GetUserNameResp 77 * 78 * Structure for get user name response command (refer spec sec 22.29) 79 */ 80 struct GetUserNameResp 81 { 82 uint8_t userName[16]; 83 } __attribute__((packed)); 84 85 /** @struct SetUserPasswordReq 86 * 87 * Structure for set user password request command (refer spec sec 22.30) 88 */ 89 struct SetUserPasswordReq 90 { 91 #if BYTE_ORDER == LITTLE_ENDIAN 92 uint8_t userId : 6; 93 uint8_t reserved1 : 1; 94 uint8_t ipmi20 : 1; 95 uint8_t operation : 2; 96 uint8_t reserved2 : 6; 97 #endif 98 #if BYTE_ORDER == BIG_ENDIAN 99 uint8_t ipmi20 : 1; 100 uint8_t reserved1 : 1; 101 uint8_t userId : 6; 102 uint8_t reserved2 : 6; 103 uint8_t operation : 2; 104 #endif 105 uint8_t userPassword[maxIpmi20PasswordSize]; 106 } __attribute__((packed)); 107 108 /** @brief implements the set user access command 109 * @param ctx - IPMI context pointer (for channel) 110 * @param channel - channel number 111 * @param ipmiEnabled - indicates ipmi messaging state 112 * @param linkAuthEnabled - indicates link authentication state 113 * @param accessCallback - indicates callback state 114 * @param bitsUpdate - indicates update request 115 * @param userId - user id 116 * @param reserved1 - skip 2 bits 117 * @param privilege - user privilege 118 * @param reserved2 - skip 4 bits 119 * @param sessionLimit - optional - unused for now 120 * 121 * @returns ipmi completion code 122 */ 123 ipmi::RspType<> ipmiSetUserAccess(ipmi::Context::ptr ctx, uint4_t channel, 124 uint1_t ipmiEnabled, uint1_t linkAuthEnabled, 125 uint1_t accessCallback, uint1_t bitsUpdate, 126 127 uint6_t userId, uint2_t reserved1, 128 129 uint4_t privilege, uint4_t reserved2, 130 131 std::optional<uint8_t> sessionLimit) 132 { 133 uint8_t sessLimit = sessionLimit.value_or(0); 134 if (reserved1 || reserved2 || sessLimit || 135 !ipmiUserIsValidPrivilege(static_cast<uint8_t>(privilege))) 136 { 137 log<level::DEBUG>("Set user access - Invalid field in request"); 138 return ipmi::responseInvalidFieldRequest(); 139 } 140 141 uint8_t chNum = 142 convertCurrentChannelNum(static_cast<uint8_t>(channel), ctx->channel); 143 if (!isValidChannel(chNum)) 144 { 145 log<level::DEBUG>("Set user access - Invalid channel request"); 146 return ipmi::response(invalidChannel); 147 } 148 if (getChannelSessionSupport(chNum) == EChannelSessSupported::none) 149 { 150 log<level::DEBUG>("Set user access - No support on channel"); 151 return ipmi::response(ccActionNotSupportedForChannel); 152 } 153 if (!ipmiUserIsValidUserId(static_cast<uint8_t>(userId))) 154 { 155 log<level::DEBUG>("Set user access - Parameter out of range"); 156 return ipmi::responseParmOutOfRange(); 157 } 158 159 PrivAccess privAccess = {0}; 160 if (bitsUpdate) 161 { 162 privAccess.ipmiEnabled = static_cast<uint8_t>(ipmiEnabled); 163 privAccess.linkAuthEnabled = static_cast<uint8_t>(linkAuthEnabled); 164 privAccess.accessCallback = static_cast<uint8_t>(accessCallback); 165 } 166 privAccess.privilege = static_cast<uint8_t>(privilege); 167 return ipmi::response( 168 ipmiUserSetPrivilegeAccess(static_cast<uint8_t>(userId), chNum, 169 privAccess, static_cast<bool>(bitsUpdate))); 170 } 171 172 /** @brief implements the set user access command 173 * @param ctx - IPMI context pointer (for channel) 174 * @param channel - channel number 175 * @param reserved1 - skip 4 bits 176 * @param userId - user id 177 * @param reserved2 - skip 2 bits 178 * 179 * @returns ipmi completion code plus response data 180 * - maxChUsers - max channel users 181 * - reserved1 - skip 2 bits 182 * - enabledUsers - enabled users count 183 * - enabledStatus - enabled status 184 * - fixedUsers - fixed users count 185 * - reserved2 - skip 2 bits 186 * - privilege - user privilege 187 * - ipmiEnabled - ipmi messaging state 188 * - linkAuthEnabled - link authenticatin state 189 * - accessCallback - callback state 190 * - reserved - skip 1 bit 191 */ 192 ipmi::RspType<uint6_t, // max channel users 193 uint2_t, // reserved1 194 195 uint6_t, // enabled users count 196 uint2_t, // enabled status 197 198 uint6_t, // fixed users count 199 uint2_t, // reserved2 200 201 uint4_t, // privilege 202 uint1_t, // ipmi messaging state 203 uint1_t, // link authentication state 204 uint1_t, // access callback state 205 uint1_t // reserved3 206 > 207 ipmiGetUserAccess(ipmi::Context::ptr ctx, uint4_t channel, 208 uint4_t reserved1, 209 210 uint6_t userId, uint2_t reserved2) 211 { 212 uint8_t chNum = 213 convertCurrentChannelNum(static_cast<uint8_t>(channel), ctx->channel); 214 215 if (reserved1 || reserved2 || !isValidChannel(chNum)) 216 { 217 log<level::DEBUG>("Get user access - Invalid field in request"); 218 return ipmi::responseInvalidFieldRequest(); 219 } 220 221 if (getChannelSessionSupport(chNum) == EChannelSessSupported::none) 222 { 223 log<level::DEBUG>("Get user access - No support on channel"); 224 return ipmi::response(ccActionNotSupportedForChannel); 225 } 226 if (!ipmiUserIsValidUserId(static_cast<uint8_t>(userId))) 227 { 228 log<level::DEBUG>("Get user access - Parameter out of range"); 229 return ipmi::responseParmOutOfRange(); 230 } 231 232 uint8_t maxChUsers = 0, enabledUsers = 0, fixedUsers = 0; 233 ipmi::Cc retStatus; 234 retStatus = ipmiUserGetAllCounts(maxChUsers, enabledUsers, fixedUsers); 235 if (retStatus != ccSuccess) 236 { 237 return ipmi::response(retStatus); 238 } 239 240 bool enabledState = false; 241 retStatus = 242 ipmiUserCheckEnabled(static_cast<uint8_t>(userId), enabledState); 243 if (retStatus != ccSuccess) 244 { 245 return ipmi::response(retStatus); 246 } 247 248 uint2_t enabledStatus = enabledState ? userIdEnabledViaSetPassword 249 : userIdDisabledViaSetPassword; 250 PrivAccess privAccess{}; 251 retStatus = ipmiUserGetPrivilegeAccess(static_cast<uint8_t>(userId), chNum, 252 privAccess); 253 if (retStatus != ccSuccess) 254 { 255 return ipmi::response(retStatus); 256 } 257 constexpr uint2_t res2Bits = 0; 258 return ipmi::responseSuccess( 259 static_cast<uint6_t>(maxChUsers), res2Bits, 260 261 static_cast<uint6_t>(enabledUsers), enabledStatus, 262 263 static_cast<uint6_t>(fixedUsers), res2Bits, 264 265 static_cast<uint4_t>(privAccess.privilege), 266 static_cast<uint1_t>(privAccess.ipmiEnabled), 267 static_cast<uint1_t>(privAccess.linkAuthEnabled), 268 static_cast<uint1_t>(privAccess.accessCallback), 269 static_cast<uint1_t>(privAccess.reserved)); 270 } 271 272 Cc ipmiSetUserName(ipmi_netfn_t netfn, ipmi_cmd_t cmd, ipmi_request_t request, 273 ipmi_response_t response, ipmi_data_len_t dataLen, 274 ipmi_context_t context) 275 { 276 const SetUserNameReq* req = static_cast<SetUserNameReq*>(request); 277 size_t reqLength = *dataLen; 278 *dataLen = 0; 279 280 if (reqLength != sizeof(*req)) 281 { 282 log<level::DEBUG>("Set user name - Invalid Length"); 283 return ccReqDataLenInvalid; 284 } 285 if (req->reserved1) 286 { 287 return ccInvalidFieldRequest; 288 } 289 if (!ipmiUserIsValidUserId(req->userId)) 290 { 291 log<level::DEBUG>("Set user name - Invalid user id"); 292 return ccParmOutOfRange; 293 } 294 295 size_t nameLen = strnlen(reinterpret_cast<const char*>(req->userName), 296 sizeof(req->userName)); 297 const std::string strUserName(reinterpret_cast<const char*>(req->userName), 298 nameLen); 299 300 return ipmiUserSetUserName(req->userId, strUserName); 301 } 302 303 /** @brief implementes the get user name command 304 * @param[in] netfn - specifies netfn. 305 * @param[in] cmd - specifies cmd number. 306 * @param[in] request - pointer to request data. 307 * @param[in, out] dataLen - specifies request data length, and returns 308 * response data length. 309 * @param[in] context - ipmi context. 310 * @returns ipmi completion code. 311 */ 312 Cc ipmiGetUserName(ipmi_netfn_t netfn, ipmi_cmd_t cmd, ipmi_request_t request, 313 ipmi_response_t response, ipmi_data_len_t dataLen, 314 ipmi_context_t context) 315 { 316 const GetUserNameReq* req = static_cast<GetUserNameReq*>(request); 317 size_t reqLength = *dataLen; 318 319 *dataLen = 0; 320 321 if (reqLength != sizeof(*req)) 322 { 323 log<level::DEBUG>("Get user name - Invalid Length"); 324 return ccReqDataLenInvalid; 325 } 326 327 std::string userName; 328 if (ipmiUserGetUserName(req->userId, userName) != ccSuccess) 329 { // Invalid User ID 330 log<level::DEBUG>("User Name not found", 331 entry("USER-ID=%d", (uint8_t)req->userId)); 332 return ccParmOutOfRange; 333 } 334 GetUserNameResp* resp = static_cast<GetUserNameResp*>(response); 335 std::fill(reinterpret_cast<uint8_t*>(resp), 336 reinterpret_cast<uint8_t*>(resp) + sizeof(*resp), 0); 337 userName.copy(reinterpret_cast<char*>(resp->userName), 338 sizeof(resp->userName), 0); 339 *dataLen = sizeof(*resp); 340 341 return ccSuccess; 342 } 343 344 /** @brief implementes the set user password command 345 * @param[in] netfn - specifies netfn. 346 * @param[in] cmd - specifies cmd number. 347 * @param[in] request - pointer to request data. 348 * @param[in, out] dataLen - specifies request data length, and returns 349 * response data length. 350 * @param[in] context - ipmi context. 351 * @returns ipmi completion code. 352 */ 353 Cc ipmiSetUserPassword(ipmi_netfn_t netfn, ipmi_cmd_t cmd, 354 ipmi_request_t request, ipmi_response_t response, 355 ipmi_data_len_t dataLen, ipmi_context_t context) 356 { 357 const SetUserPasswordReq* req = static_cast<SetUserPasswordReq*>(request); 358 size_t reqLength = *dataLen; 359 // subtract 2 bytes header to know the password length - including NULL 360 uint8_t passwordLength = *dataLen - 2; 361 *dataLen = 0; 362 if (req->reserved1 || req->reserved2) 363 { 364 log<level::DEBUG>("Invalid data field in request"); 365 return ccInvalidFieldRequest; 366 } 367 368 // verify input length based on operation. Required password size is 20 369 // bytes as we support only IPMI 2.0, but in order to be compatible with 370 // tools, accept 16 bytes of password size too. 371 if (reqLength < 2 || 372 // If enable / disable user, reqLength has to be >=2 & <= 22 373 ((req->operation == disableUser || req->operation == enableUser) && 374 ((reqLength < 2) || (reqLength > sizeof(SetUserPasswordReq))))) 375 { 376 log<level::DEBUG>("Invalid Length"); 377 return ccReqDataLenInvalid; 378 } 379 // If set / test password then password length has to be 16 or 20 bytes 380 // based on the password size bit. 381 if (((req->operation == setPassword) || (req->operation == testPassword)) && 382 (((req->ipmi20 == passwordKeySize20) && 383 (passwordLength != maxIpmi20PasswordSize)) || 384 ((req->ipmi20 == passwordKeySize16) && 385 (passwordLength != maxIpmi15PasswordSize)))) 386 { 387 log<level::DEBUG>("Invalid Length"); 388 return ccReqDataLenInvalid; 389 } 390 391 std::string userName; 392 if (ipmiUserGetUserName(req->userId, userName) != ccSuccess) 393 { 394 log<level::DEBUG>("User Name not found", 395 entry("USER-ID=%d", (uint8_t)req->userId)); 396 return ccParmOutOfRange; 397 } 398 if (req->operation == setPassword) 399 { 400 return ipmiUserSetUserPassword( 401 req->userId, reinterpret_cast<const char*>(req->userPassword)); 402 } 403 else if (req->operation == enableUser || req->operation == disableUser) 404 { 405 return ipmiUserUpdateEnabledState(req->userId, 406 static_cast<bool>(req->operation)); 407 } 408 else if (req->operation == testPassword) 409 { 410 auto password = ipmiUserGetPassword(userName); 411 std::string testPassword( 412 reinterpret_cast<const char*>(req->userPassword), 0, 413 passwordLength); 414 // Note: For security reasons password size won't be compared and 415 // wrong password size completion code will not be returned if size 416 // doesn't match as specified in IPMI specification. 417 if (password != testPassword) 418 { 419 log<level::DEBUG>("Test password failed", 420 entry("USER-ID=%d", (uint8_t)req->userId)); 421 // Clear sensitive data 422 OPENSSL_cleanse(testPassword.data(), testPassword.length()); 423 OPENSSL_cleanse(password.data(), password.length()); 424 425 return static_cast<Cc>( 426 IPMISetPasswordReturnCodes::ipmiCCPasswdFailMismatch); 427 } 428 // Clear sensitive data 429 OPENSSL_cleanse(testPassword.data(), testPassword.length()); 430 OPENSSL_cleanse(password.data(), password.length()); 431 432 return ccSuccess; 433 } 434 return ccInvalidFieldRequest; 435 } 436 437 /** @brief implements the get channel authentication command 438 * @param ctx - IPMI context pointer (for channel) 439 * @param extData - get IPMI 2.0 extended data 440 * @param reserved1 - skip 3 bits 441 * @param chNum - channel number to get info about 442 * @param reserved2 - skip 4 bits 443 * @param privLevel - requested privilege level 444 445 * @returns ipmi completion code plus response data 446 * - channel number 447 * - rmcpAuthTypes - RMCP auth types (IPMI 1.5) 448 * - reserved1 449 * - extDataSupport - true for IPMI 2.0 extensions 450 * - anonymousLogin - true for anonymous login enabled 451 * - nullUsers - true for null user names enabled 452 * - nonNullUsers - true for non-null usernames enabled 453 * - userAuth - false for user authentication enabled 454 * - perMessageAuth - false for per message authentication enabled 455 * - KGStatus - true for Kg required for authentication 456 * - reserved2 457 * - rmcp - RMCP (IPMI 1.5) connection support 458 * - rmcpp - RMCP+ (IPMI 2.0) connection support 459 * - reserved3 460 * - oemID - OEM IANA of any OEM auth support 461 * - oemAuxillary - OEM data for auth 462 */ 463 ipmi::RspType<uint8_t, // channel number 464 uint6_t, // rmcpAuthTypes 465 bool, // reserved1 466 bool, // extDataSupport 467 bool, // anonymousLogin 468 bool, // nullUsers 469 bool, // nonNullUsers 470 bool, // userAuth 471 bool, // perMessageAuth 472 bool, // KGStatus 473 uint2_t, // reserved2 474 bool, // rmcp 475 bool, // rmcpp 476 uint6_t, // reserved3 477 uint24_t, // oemID 478 uint8_t // oemAuxillary 479 > 480 ipmiGetChannelAuthenticationCapabilities(ipmi::Context::ptr ctx, 481 uint4_t chNum, uint3_t reserved1, 482 bool extData, uint4_t privLevel, 483 uint4_t reserved2) 484 { 485 uint8_t channel = 486 convertCurrentChannelNum(static_cast<uint8_t>(chNum), ctx->channel); 487 488 if (reserved1 || reserved2 || !isValidChannel(channel) || 489 !isValidPrivLimit(static_cast<uint8_t>(privLevel))) 490 { 491 log<level::DEBUG>( 492 "Get channel auth capabilities - Invalid field in request"); 493 return ipmi::responseInvalidFieldRequest(); 494 } 495 496 if (getChannelSessionSupport(channel) == EChannelSessSupported::none) 497 { 498 log<level::DEBUG>( 499 "Get channel auth capabilities - No support on channel"); 500 return ipmi::response(ccActionNotSupportedForChannel); 501 } 502 503 constexpr bool extDataSupport = true; // true for IPMI 2.0 extensions 504 constexpr bool reserved3 = false; 505 constexpr uint6_t rmcpAuthTypes = 0; // IPMI 1.5 auth types - not supported 506 constexpr uint2_t reserved4 = 0; 507 constexpr bool KGStatus = false; // Not supporting now. 508 constexpr bool perMessageAuth = false; // Per message auth - enabled 509 constexpr bool userAuth = false; // User authentication - enabled 510 constexpr bool nullUsers = false; // Null user names - not supported 511 constexpr bool anonymousLogin = false; // Anonymous login - not supported 512 constexpr uint6_t reserved5 = 0; 513 constexpr bool rmcpp = true; // IPMI 2.0 - supported 514 constexpr bool rmcp = false; // IPMI 1.5 - not supported 515 constexpr uint24_t oemID = 0; 516 constexpr uint8_t oemAuxillary = 0; 517 518 bool nonNullUsers = 0; 519 uint8_t maxChUsers = 0, enabledUsers = 0, fixedUsers = 0; 520 ipmi::ipmiUserGetAllCounts(maxChUsers, enabledUsers, fixedUsers); 521 nonNullUsers = enabledUsers > 0; 522 523 return ipmi::responseSuccess( 524 channel, rmcpAuthTypes, reserved3, extDataSupport, anonymousLogin, 525 nullUsers, nonNullUsers, userAuth, perMessageAuth, KGStatus, reserved4, 526 rmcp, rmcpp, reserved5, oemID, oemAuxillary); 527 } 528 529 /** @brief implements the set user payload access command. 530 * @param ctx - IPMI context pointer (for channel) 531 * @param channel - channel number (4 bits) 532 * @param reserved1 - skip 4 bits 533 * @param userId - user id (6 bits) 534 * @param operation - access ENABLE /DISABLE. (2 bits) 535 * @param stdPayload0 - IPMI - reserved. (1 bit) 536 * @param stdPayload1 - SOL. (1 bit) 537 * @param stdPayload2 - (1 bit) 538 * @param stdPayload3 - (1 bit) 539 * @param stdPayload4 - (1 bit) 540 * @param stdPayload5 - (1 bit) 541 * @param stdPayload6 - (1 bit) 542 * @param stdPayload7 - (1 bit) 543 * @param stdPayloadEnables2Reserved - (8 bits) 544 * @param oemPayload0 - (1 bit) 545 * @param oemPayload1 - (1 bit) 546 * @param oemPayload2 - (1 bit) 547 * @param oemPayload3 - (1 bit) 548 * @param oemPayload4 - (1 bit) 549 * @param oemPayload5 - (1 bit) 550 * @param oemPayload6 - (1 bit) 551 * @param oemPayload7 - (1 bit) 552 * @param oemPayloadEnables2Reserved - (8 bits) 553 * 554 * @returns IPMI completion code 555 */ 556 ipmi::RspType<> ipmiSetUserPayloadAccess( 557 ipmi::Context::ptr ctx, 558 559 uint4_t channel, uint4_t reserved, 560 561 uint6_t userId, uint2_t operation, 562 563 bool stdPayload0ipmiReserved, bool stdPayload1SOL, bool stdPayload2, 564 bool stdPayload3, bool stdPayload4, bool stdPayload5, bool stdPayload6, 565 bool stdPayload7, 566 567 uint8_t stdPayloadEnables2Reserved, 568 569 bool oemPayload0, bool oemPayload1, bool oemPayload2, bool oemPayload3, 570 bool oemPayload4, bool oemPayload5, bool oemPayload6, bool oemPayload7, 571 572 uint8_t oemPayloadEnables2Reserved) 573 { 574 auto chNum = 575 convertCurrentChannelNum(static_cast<uint8_t>(channel), ctx->channel); 576 // Validate the reserved args. Only SOL payload is supported as on date. 577 if (reserved || stdPayload0ipmiReserved || stdPayload2 || stdPayload3 || 578 stdPayload4 || stdPayload5 || stdPayload6 || stdPayload7 || 579 oemPayload0 || oemPayload1 || oemPayload2 || oemPayload3 || 580 oemPayload4 || oemPayload5 || oemPayload6 || oemPayload7 || 581 stdPayloadEnables2Reserved || oemPayloadEnables2Reserved || 582 !isValidChannel(chNum)) 583 { 584 return ipmi::responseInvalidFieldRequest(); 585 } 586 587 if ((operation != enableOperation && operation != disableOperation)) 588 { 589 return ipmi::responseInvalidFieldRequest(); 590 } 591 if (getChannelSessionSupport(chNum) == EChannelSessSupported::none) 592 { 593 return ipmi::response(ccActionNotSupportedForChannel); 594 } 595 if (!ipmiUserIsValidUserId(static_cast<uint8_t>(userId))) 596 { 597 return ipmi::responseParmOutOfRange(); 598 } 599 600 PayloadAccess payloadAccess = {0}; 601 payloadAccess.stdPayloadEnables1[1] = stdPayload1SOL; 602 603 return ipmi::response(ipmiUserSetUserPayloadAccess( 604 chNum, static_cast<uint8_t>(operation), static_cast<uint8_t>(userId), 605 payloadAccess)); 606 } 607 608 /** @brief implements the get user payload access command 609 * This command returns information about user payload enable settings 610 * that were set using the 'Set User Payload Access' Command. 611 * 612 * @param ctx - IPMI context pointer (for channel) 613 * @param channel - channel number 614 * @param reserved1 - skip 4 bits 615 * @param userId - user id 616 * @param reserved2 - skip 2 bits 617 * 618 * @returns IPMI completion code plus response data 619 * - stdPayload0ipmiReserved - IPMI payload (reserved). 620 * - stdPayload1SOL - SOL payload 621 * - stdPayload2 622 * - stdPayload3 623 * - stdPayload4 624 * - stdPayload5 625 * - stdPayload6 626 * - stdPayload7 627 628 * - stdPayloadEnables2Reserved - Reserved. 629 630 * - oemPayload0 631 * - oemPayload1 632 * - oemPayload2 633 * - oemPayload3 634 * - oemPayload4 635 * - oemPayload5 636 * - oemPayload6 637 * - oemPayload7 638 639 * - oemPayloadEnables2Reserved - Reserved 640 */ 641 ipmi::RspType<bool, // stdPayload0ipmiReserved 642 bool, // stdPayload1SOL 643 bool, // stdPayload2 644 bool, // stdPayload3 645 bool, // stdPayload4 646 bool, // stdPayload5 647 bool, // stdPayload6 648 bool, // stdPayload7 649 650 uint8_t, // stdPayloadEnables2Reserved 651 652 bool, // oemPayload0 653 bool, // oemPayload1 654 bool, // oemPayload2 655 bool, // oemPayload3 656 bool, // oemPayload4 657 bool, // oemPayload5 658 bool, // oemPayload6 659 bool, // oemPayload7 660 661 uint8_t // oemPayloadEnables2Reserved 662 > 663 ipmiGetUserPayloadAccess(ipmi::Context::ptr ctx, 664 665 uint4_t channel, uint4_t reserved1, 666 667 uint6_t userId, uint2_t reserved2) 668 { 669 uint8_t chNum = 670 convertCurrentChannelNum(static_cast<uint8_t>(channel), ctx->channel); 671 672 if (reserved1 || reserved2 || !isValidChannel(chNum)) 673 { 674 return ipmi::responseInvalidFieldRequest(); 675 } 676 if (getChannelSessionSupport(chNum) == EChannelSessSupported::none) 677 { 678 return ipmi::response(ccActionNotSupportedForChannel); 679 } 680 if (!ipmiUserIsValidUserId(static_cast<uint8_t>(userId))) 681 { 682 return ipmi::responseParmOutOfRange(); 683 } 684 685 ipmi::Cc retStatus; 686 PayloadAccess payloadAccess = {}; 687 retStatus = ipmiUserGetUserPayloadAccess( 688 chNum, static_cast<uint8_t>(userId), payloadAccess); 689 if (retStatus != ccSuccess) 690 { 691 return ipmi::response(retStatus); 692 } 693 constexpr uint8_t res8bits = 0; 694 return ipmi::responseSuccess(payloadAccess.stdPayloadEnables1.test(0), 695 payloadAccess.stdPayloadEnables1.test(1), 696 payloadAccess.stdPayloadEnables1.test(2), 697 payloadAccess.stdPayloadEnables1.test(3), 698 payloadAccess.stdPayloadEnables1.test(4), 699 payloadAccess.stdPayloadEnables1.test(5), 700 payloadAccess.stdPayloadEnables1.test(6), 701 payloadAccess.stdPayloadEnables1.test(7), 702 703 res8bits, 704 705 payloadAccess.oemPayloadEnables1.test(0), 706 payloadAccess.oemPayloadEnables1.test(1), 707 payloadAccess.oemPayloadEnables1.test(2), 708 payloadAccess.oemPayloadEnables1.test(3), 709 payloadAccess.oemPayloadEnables1.test(4), 710 payloadAccess.oemPayloadEnables1.test(5), 711 payloadAccess.oemPayloadEnables1.test(6), 712 payloadAccess.oemPayloadEnables1.test(7), 713 714 res8bits); 715 } 716 717 void registerUserIpmiFunctions() __attribute__((constructor)); 718 void registerUserIpmiFunctions() 719 { 720 post_work([]() { ipmiUserInit(); }); 721 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp, 722 ipmi::app::cmdSetUserAccessCommand, 723 ipmi::Privilege::Admin, ipmiSetUserAccess); 724 725 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp, 726 ipmi::app::cmdGetUserAccessCommand, 727 ipmi::Privilege::Operator, ipmiGetUserAccess); 728 729 ipmi_register_callback(NETFUN_APP, IPMI_CMD_GET_USER_NAME, NULL, 730 ipmiGetUserName, PRIVILEGE_OPERATOR); 731 732 ipmi_register_callback(NETFUN_APP, IPMI_CMD_SET_USER_NAME, NULL, 733 ipmiSetUserName, PRIVILEGE_ADMIN); 734 735 ipmi_register_callback(NETFUN_APP, IPMI_CMD_SET_USER_PASSWORD, NULL, 736 ipmiSetUserPassword, PRIVILEGE_ADMIN); 737 738 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp, 739 ipmi::app::cmdGetChannelAuthCapabilities, 740 ipmi::Privilege::Callback, 741 ipmiGetChannelAuthenticationCapabilities); 742 743 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp, 744 ipmi::app::cmdSetUserPayloadAccess, 745 ipmi::Privilege::Admin, ipmiSetUserPayloadAccess); 746 747 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp, 748 ipmi::app::cmdGetUserPayloadAccess, 749 ipmi::Privilege::Operator, ipmiGetUserPayloadAccess); 750 751 return; 752 } 753 } // namespace ipmi 754