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