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 auto password = ipmiUserGetPassword(userName); 362 std::string testPassword( 363 reinterpret_cast<const char*>(req->userPassword), 0, 364 passwordLength); 365 // Note: For security reasons password size won't be compared and 366 // wrong password size completion code will not be returned if size 367 // doesn't match as specified in IPMI specification. 368 if (password != testPassword) 369 { 370 log<level::DEBUG>("Test password failed", 371 entry("USER-ID=%d", (uint8_t)req->userId)); 372 // Clear sensitive data 373 OPENSSL_cleanse(testPassword.data(), testPassword.length()); 374 OPENSSL_cleanse(password.data(), password.length()); 375 376 return static_cast<Cc>( 377 IPMISetPasswordReturnCodes::ipmiCCPasswdFailMismatch); 378 } 379 // Clear sensitive data 380 OPENSSL_cleanse(testPassword.data(), testPassword.length()); 381 OPENSSL_cleanse(password.data(), password.length()); 382 383 return ccSuccess; 384 } 385 return ccInvalidFieldRequest; 386 } 387 388 /** @brief implements the get channel authentication command 389 * @param ctx - IPMI context pointer (for channel) 390 * @param extData - get IPMI 2.0 extended data 391 * @param reserved1 - skip 3 bits 392 * @param chNum - channel number to get info about 393 * @param reserved2 - skip 4 bits 394 * @param privLevel - requested privilege level 395 396 * @returns ipmi completion code plus response data 397 * - channel number 398 * - rmcpAuthTypes - RMCP auth types (IPMI 1.5) 399 * - reserved1 400 * - extDataSupport - true for IPMI 2.0 extensions 401 * - anonymousLogin - true for anonymous login enabled 402 * - nullUsers - true for null user names enabled 403 * - nonNullUsers - true for non-null usernames enabled 404 * - userAuth - false for user authentication enabled 405 * - perMessageAuth - false for per message authentication enabled 406 * - KGStatus - true for Kg required for authentication 407 * - reserved2 408 * - rmcp - RMCP (IPMI 1.5) connection support 409 * - rmcpp - RMCP+ (IPMI 2.0) connection support 410 * - reserved3 411 * - oemID - OEM IANA of any OEM auth support 412 * - oemAuxillary - OEM data for auth 413 */ 414 ipmi::RspType<uint8_t, // channel number 415 uint6_t, // rmcpAuthTypes 416 bool, // reserved1 417 bool, // extDataSupport 418 bool, // anonymousLogin 419 bool, // nullUsers 420 bool, // nonNullUsers 421 bool, // userAuth 422 bool, // perMessageAuth 423 bool, // KGStatus 424 uint2_t, // reserved2 425 bool, // rmcp 426 bool, // rmcpp 427 uint6_t, // reserved3 428 uint24_t, // oemID 429 uint8_t // oemAuxillary 430 > 431 ipmiGetChannelAuthenticationCapabilities(ipmi::Context::ptr ctx, 432 uint4_t chNum, uint3_t reserved1, 433 bool extData, uint4_t privLevel, 434 uint4_t reserved2) 435 { 436 uint8_t channel = 437 convertCurrentChannelNum(static_cast<uint8_t>(chNum), ctx->channel); 438 439 if (reserved1 || reserved2 || !isValidChannel(channel) || 440 !isValidPrivLimit(static_cast<uint8_t>(privLevel))) 441 { 442 log<level::DEBUG>( 443 "Get channel auth capabilities - Invalid field in request"); 444 return ipmi::responseInvalidFieldRequest(); 445 } 446 447 if (getChannelSessionSupport(channel) == EChannelSessSupported::none) 448 { 449 log<level::DEBUG>( 450 "Get channel auth capabilities - No support on channel"); 451 return ipmi::response(ccActionNotSupportedForChannel); 452 } 453 454 constexpr bool extDataSupport = true; // true for IPMI 2.0 extensions 455 constexpr bool reserved3 = false; 456 constexpr uint6_t rmcpAuthTypes = 0; // IPMI 1.5 auth types - not supported 457 constexpr uint2_t reserved4 = 0; 458 constexpr bool KGStatus = false; // Not supporting now. 459 constexpr bool perMessageAuth = false; // Per message auth - enabled 460 constexpr bool userAuth = false; // User authentication - enabled 461 constexpr bool nullUsers = false; // Null user names - not supported 462 constexpr bool anonymousLogin = false; // Anonymous login - not supported 463 constexpr uint6_t reserved5 = 0; 464 constexpr bool rmcpp = true; // IPMI 2.0 - supported 465 constexpr bool rmcp = false; // IPMI 1.5 - not supported 466 constexpr uint24_t oemID = 0; 467 constexpr uint8_t oemAuxillary = 0; 468 469 bool nonNullUsers = 0; 470 uint8_t maxChUsers = 0, enabledUsers = 0, fixedUsers = 0; 471 ipmi::ipmiUserGetAllCounts(maxChUsers, enabledUsers, fixedUsers); 472 nonNullUsers = enabledUsers > 0; 473 474 return ipmi::responseSuccess( 475 channel, rmcpAuthTypes, reserved3, extDataSupport, anonymousLogin, 476 nullUsers, nonNullUsers, userAuth, perMessageAuth, KGStatus, reserved4, 477 rmcp, rmcpp, reserved5, oemID, oemAuxillary); 478 } 479 480 /** @brief implements the set user payload access command. 481 * @param ctx - IPMI context pointer (for channel) 482 * @param channel - channel number (4 bits) 483 * @param reserved1 - skip 4 bits 484 * @param userId - user id (6 bits) 485 * @param operation - access ENABLE /DISABLE. (2 bits) 486 * @param stdPayload0 - IPMI - reserved. (1 bit) 487 * @param stdPayload1 - SOL. (1 bit) 488 * @param stdPayload2 - (1 bit) 489 * @param stdPayload3 - (1 bit) 490 * @param stdPayload4 - (1 bit) 491 * @param stdPayload5 - (1 bit) 492 * @param stdPayload6 - (1 bit) 493 * @param stdPayload7 - (1 bit) 494 * @param stdPayloadEnables2Reserved - (8 bits) 495 * @param oemPayload0 - (1 bit) 496 * @param oemPayload1 - (1 bit) 497 * @param oemPayload2 - (1 bit) 498 * @param oemPayload3 - (1 bit) 499 * @param oemPayload4 - (1 bit) 500 * @param oemPayload5 - (1 bit) 501 * @param oemPayload6 - (1 bit) 502 * @param oemPayload7 - (1 bit) 503 * @param oemPayloadEnables2Reserved - (8 bits) 504 * 505 * @returns IPMI completion code 506 */ 507 ipmi::RspType<> ipmiSetUserPayloadAccess( 508 ipmi::Context::ptr ctx, 509 510 uint4_t channel, uint4_t reserved, 511 512 uint6_t userId, uint2_t operation, 513 514 bool stdPayload0ipmiReserved, bool stdPayload1SOL, bool stdPayload2, 515 bool stdPayload3, bool stdPayload4, bool stdPayload5, bool stdPayload6, 516 bool stdPayload7, 517 518 uint8_t stdPayloadEnables2Reserved, 519 520 bool oemPayload0, bool oemPayload1, bool oemPayload2, bool oemPayload3, 521 bool oemPayload4, bool oemPayload5, bool oemPayload6, bool oemPayload7, 522 523 uint8_t oemPayloadEnables2Reserved) 524 { 525 auto chNum = 526 convertCurrentChannelNum(static_cast<uint8_t>(channel), ctx->channel); 527 // Validate the reserved args. Only SOL payload is supported as on date. 528 if (reserved || stdPayload0ipmiReserved || stdPayload2 || stdPayload3 || 529 stdPayload4 || stdPayload5 || stdPayload6 || stdPayload7 || 530 oemPayload0 || oemPayload1 || oemPayload2 || oemPayload3 || 531 oemPayload4 || oemPayload5 || oemPayload6 || oemPayload7 || 532 stdPayloadEnables2Reserved || oemPayloadEnables2Reserved || 533 !isValidChannel(chNum)) 534 { 535 return ipmi::responseInvalidFieldRequest(); 536 } 537 538 if ((operation != enableOperation && operation != disableOperation)) 539 { 540 return ipmi::responseInvalidFieldRequest(); 541 } 542 if (getChannelSessionSupport(chNum) == EChannelSessSupported::none) 543 { 544 return ipmi::response(ccActionNotSupportedForChannel); 545 } 546 if (!ipmiUserIsValidUserId(static_cast<uint8_t>(userId))) 547 { 548 return ipmi::responseParmOutOfRange(); 549 } 550 551 PayloadAccess payloadAccess = {0}; 552 payloadAccess.stdPayloadEnables1[1] = stdPayload1SOL; 553 554 return ipmi::response(ipmiUserSetUserPayloadAccess( 555 chNum, static_cast<uint8_t>(operation), static_cast<uint8_t>(userId), 556 payloadAccess)); 557 } 558 559 /** @brief implements the get user payload access command 560 * This command returns information about user payload enable settings 561 * that were set using the 'Set User Payload Access' Command. 562 * 563 * @param ctx - IPMI context pointer (for channel) 564 * @param channel - channel number 565 * @param reserved1 - skip 4 bits 566 * @param userId - user id 567 * @param reserved2 - skip 2 bits 568 * 569 * @returns IPMI completion code plus response data 570 * - stdPayload0ipmiReserved - IPMI payload (reserved). 571 * - stdPayload1SOL - SOL payload 572 * - stdPayload2 573 * - stdPayload3 574 * - stdPayload4 575 * - stdPayload5 576 * - stdPayload6 577 * - stdPayload7 578 579 * - stdPayloadEnables2Reserved - Reserved. 580 581 * - oemPayload0 582 * - oemPayload1 583 * - oemPayload2 584 * - oemPayload3 585 * - oemPayload4 586 * - oemPayload5 587 * - oemPayload6 588 * - oemPayload7 589 590 * - oemPayloadEnables2Reserved - Reserved 591 */ 592 ipmi::RspType<bool, // stdPayload0ipmiReserved 593 bool, // stdPayload1SOL 594 bool, // stdPayload2 595 bool, // stdPayload3 596 bool, // stdPayload4 597 bool, // stdPayload5 598 bool, // stdPayload6 599 bool, // stdPayload7 600 601 uint8_t, // stdPayloadEnables2Reserved 602 603 bool, // oemPayload0 604 bool, // oemPayload1 605 bool, // oemPayload2 606 bool, // oemPayload3 607 bool, // oemPayload4 608 bool, // oemPayload5 609 bool, // oemPayload6 610 bool, // oemPayload7 611 612 uint8_t // oemPayloadEnables2Reserved 613 > 614 ipmiGetUserPayloadAccess(ipmi::Context::ptr ctx, 615 616 uint4_t channel, uint4_t reserved1, 617 618 uint6_t userId, uint2_t reserved2) 619 { 620 uint8_t chNum = 621 convertCurrentChannelNum(static_cast<uint8_t>(channel), ctx->channel); 622 623 if (reserved1 || reserved2 || !isValidChannel(chNum)) 624 { 625 return ipmi::responseInvalidFieldRequest(); 626 } 627 if (getChannelSessionSupport(chNum) == EChannelSessSupported::none) 628 { 629 return ipmi::response(ccActionNotSupportedForChannel); 630 } 631 if (!ipmiUserIsValidUserId(static_cast<uint8_t>(userId))) 632 { 633 return ipmi::responseParmOutOfRange(); 634 } 635 636 ipmi::Cc retStatus; 637 PayloadAccess payloadAccess = {}; 638 retStatus = ipmiUserGetUserPayloadAccess( 639 chNum, static_cast<uint8_t>(userId), payloadAccess); 640 if (retStatus != ccSuccess) 641 { 642 return ipmi::response(retStatus); 643 } 644 constexpr uint8_t res8bits = 0; 645 return ipmi::responseSuccess(payloadAccess.stdPayloadEnables1.test(0), 646 payloadAccess.stdPayloadEnables1.test(1), 647 payloadAccess.stdPayloadEnables1.test(2), 648 payloadAccess.stdPayloadEnables1.test(3), 649 payloadAccess.stdPayloadEnables1.test(4), 650 payloadAccess.stdPayloadEnables1.test(5), 651 payloadAccess.stdPayloadEnables1.test(6), 652 payloadAccess.stdPayloadEnables1.test(7), 653 654 res8bits, 655 656 payloadAccess.oemPayloadEnables1.test(0), 657 payloadAccess.oemPayloadEnables1.test(1), 658 payloadAccess.oemPayloadEnables1.test(2), 659 payloadAccess.oemPayloadEnables1.test(3), 660 payloadAccess.oemPayloadEnables1.test(4), 661 payloadAccess.oemPayloadEnables1.test(5), 662 payloadAccess.oemPayloadEnables1.test(6), 663 payloadAccess.oemPayloadEnables1.test(7), 664 665 res8bits); 666 } 667 668 void registerUserIpmiFunctions() __attribute__((constructor)); 669 void registerUserIpmiFunctions() 670 { 671 post_work([]() { ipmiUserInit(); }); 672 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp, 673 ipmi::app::cmdSetUserAccessCommand, 674 ipmi::Privilege::Admin, ipmiSetUserAccess); 675 676 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp, 677 ipmi::app::cmdGetUserAccessCommand, 678 ipmi::Privilege::Operator, ipmiGetUserAccess); 679 680 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp, 681 ipmi::app::cmdGetUserNameCommand, 682 ipmi::Privilege::Operator, ipmiGetUserName); 683 684 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp, 685 ipmi::app::cmdSetUserName, ipmi::Privilege::Admin, 686 ipmiSetUserName); 687 688 ipmi_register_callback(NETFUN_APP, IPMI_CMD_SET_USER_PASSWORD, NULL, 689 ipmiSetUserPassword, PRIVILEGE_ADMIN); 690 691 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp, 692 ipmi::app::cmdGetChannelAuthCapabilities, 693 ipmi::Privilege::Callback, 694 ipmiGetChannelAuthenticationCapabilities); 695 696 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp, 697 ipmi::app::cmdSetUserPayloadAccess, 698 ipmi::Privilege::Admin, ipmiSetUserPayloadAccess); 699 700 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp, 701 ipmi::app::cmdGetUserPayloadAccess, 702 ipmi::Privilege::Operator, ipmiGetUserPayloadAccess); 703 704 return; 705 } 706 } // namespace ipmi 707