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