xref: /openbmc/phosphor-host-ipmid/user_channel/usercommands.cpp (revision 82844ef677e97757881b43052e7c67691e8d377c)
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(ipmi::Context::ptr ctx, uint4_t channel,
52                                   uint1_t ipmiEnabled, uint1_t linkAuthEnabled,
53                                   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 = convertCurrentChannelNum(static_cast<uint8_t>(channel),
70                                              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 = convertCurrentChannelNum(static_cast<uint8_t>(channel),
141                                              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 = ipmiUserCheckEnabled(static_cast<uint8_t>(userId),
170                                      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<>
209     ipmiSetUserName([[maybe_unused]] ipmi::Context::ptr ctx, uint6_t id,
210                     uint2_t reserved,
211                     const std::array<uint8_t, ipmi::ipmiMaxUserName>& name)
212 {
213     if (reserved)
214     {
215         return ipmi::responseInvalidFieldRequest();
216     }
217     uint8_t userId = static_cast<uint8_t>(id);
218     if (!ipmiUserIsValidUserId(userId))
219     {
220         lg2::debug("Set user name - Invalid user id");
221         return ipmi::responseParmOutOfRange();
222     }
223 
224     size_t nameLen = strnlen(reinterpret_cast<const char*>(name.data()),
225                              ipmi::ipmiMaxUserName);
226     const std::string strUserName(reinterpret_cast<const char*>(name.data()),
227                                   nameLen);
228 
229     ipmi::Cc res = ipmiUserSetUserName(userId, strUserName);
230     return ipmi::response(res);
231 }
232 
233 /** @brief implementes the get user name command
234  *  @param[in] ctx - ipmi command context
235  *  @param[in] userId - 6-bit user ID
236  *  @param[in] reserved - 2-bits reserved
237 
238  *  @returns ipmi response with 16-byte username
239  */
240 ipmi::RspType<std::array<uint8_t, ipmi::ipmiMaxUserName>> // user name
241     ipmiGetUserName([[maybe_unused]] ipmi::Context::ptr ctx, uint6_t id,
242                     uint2_t reserved)
243 {
244     if (reserved)
245     {
246         return ipmi::responseInvalidFieldRequest();
247     }
248 
249     uint8_t userId = static_cast<uint8_t>(id);
250     std::string userName;
251     if (ipmiUserGetUserName(userId, userName) != ccSuccess)
252     { // Invalid User ID
253         lg2::debug("User Name not found, user Id: {USER_ID}", "USER_ID",
254                    userId);
255         return ipmi::responseParmOutOfRange();
256     }
257     // copy the std::string into a fixed array
258     if (userName.size() > ipmi::ipmiMaxUserName)
259     {
260         return ipmi::responseUnspecifiedError();
261     }
262     std::array<uint8_t, ipmi::ipmiMaxUserName> userNameFixed;
263     std::fill(userNameFixed.begin(), userNameFixed.end(), 0);
264     std::copy(userName.begin(), userName.end(), userNameFixed.begin());
265     return ipmi::responseSuccess(std::move(userNameFixed));
266 }
267 
268 /** @brief implementes the get user name command
269  *  @param[in] ctx - ipmi command context
270  *  @param[in] userId - 6-bit user ID
271  *  @param[in] reserved - 2-bits reserved
272 
273  *  @returns ipmi response with 16-byte username
274  */
275 ipmi::RspType<> // user name
276     ipmiSetUserPassword([[maybe_unused]] ipmi::Context::ptr ctx, uint6_t id,
277                         bool reserved1, bool pwLen20, uint2_t operation,
278                         uint6_t reserved2, SecureBuffer& userPassword)
279 {
280     if (reserved1 || reserved2)
281     {
282         lg2::debug("Invalid data field in request");
283         return ipmi::responseInvalidFieldRequest();
284     }
285 
286     static constexpr uint2_t opDisableUser = 0x00;
287     static constexpr uint2_t opEnableUser = 0x01;
288     static constexpr uint2_t opSetPassword = 0x02;
289     static constexpr uint2_t opTestPassword = 0x03;
290 
291     // If set / test password operation then password size has to be 16 or 20
292     // bytes based on the password size bit
293     if (((operation == opSetPassword) || (operation == opTestPassword)) &&
294         ((pwLen20 && (userPassword.size() != maxIpmi20PasswordSize)) ||
295          (!pwLen20 && (userPassword.size() != maxIpmi15PasswordSize))))
296     {
297         lg2::debug("Invalid Length");
298         return ipmi::responseReqDataLenInvalid();
299     }
300 
301     size_t passwordLength = userPassword.size();
302 
303     uint8_t userId = static_cast<uint8_t>(id);
304     std::string userName;
305     if (ipmiUserGetUserName(userId, userName) != ccSuccess)
306     {
307         lg2::debug("User Name not found, user Id: {USER_ID}", "USER_ID",
308                    userId);
309         return ipmi::responseParmOutOfRange();
310     }
311 
312     if (operation == opSetPassword)
313     {
314         // turn the non-nul terminated SecureBuffer into a SecureString
315         SecureString password(
316             reinterpret_cast<const char*>(userPassword.data()), passwordLength);
317         ipmi::Cc res = ipmiUserSetUserPassword(userId, password.data());
318         return ipmi::response(res);
319     }
320     else if (operation == opEnableUser || operation == opDisableUser)
321     {
322         ipmi::Cc res = ipmiUserUpdateEnabledState(userId,
323                                                   static_cast<bool>(operation));
324         return ipmi::response(res);
325     }
326     else if (operation == opTestPassword)
327     {
328         SecureString password = ipmiUserGetPassword(userName);
329         // extend with zeros, if needed
330         if (password.size() < passwordLength)
331         {
332             password.resize(passwordLength, '\0');
333         }
334         SecureString testPassword(
335             reinterpret_cast<const char*>(userPassword.data()), passwordLength);
336         // constant time string compare: always compare exactly as many bytes
337         // as the length of the input, resizing the actual password to match,
338         // maintaining a knowledge if the sizes differed originally
339         static const std::array<char, maxIpmi20PasswordSize> empty = {'\0'};
340         size_t cmpLen = testPassword.size();
341         bool pwLenDiffers = password.size() != cmpLen;
342         const char* cmpPassword = nullptr;
343         if (pwLenDiffers)
344         {
345             cmpPassword = empty.data();
346         }
347         else
348         {
349             cmpPassword = password.data();
350         }
351         bool pwBad = CRYPTO_memcmp(cmpPassword, testPassword.data(), cmpLen);
352         pwBad |= pwLenDiffers;
353         if (pwBad)
354         {
355             lg2::debug("Test password failed, user Id: {USER_ID}", "USER_ID",
356                        userId);
357             static constexpr ipmi::Cc ipmiCCPasswdFailMismatch = 0x80;
358             return ipmi::response(ipmiCCPasswdFailMismatch);
359         }
360         return ipmi::responseSuccess();
361     }
362     return ipmi::responseInvalidFieldRequest();
363 }
364 
365 /** @brief implements the get channel authentication command
366  *  @param ctx - IPMI context pointer (for channel)
367  *  @param extData - get IPMI 2.0 extended data
368  *  @param reserved1 - skip 3 bits
369  *  @param chNum - channel number to get info about
370  *  @param reserved2 - skip 4 bits
371  *  @param privLevel - requested privilege level
372 
373  *  @returns ipmi completion code plus response data
374  *   - channel number
375  *   - rmcpAuthTypes - RMCP auth types (IPMI 1.5)
376  *   - reserved1
377  *   - extDataSupport - true for IPMI 2.0 extensions
378  *   - anonymousLogin - true for anonymous login enabled
379  *   - nullUsers - true for null user names enabled
380  *   - nonNullUsers - true for non-null usernames enabled
381  *   - userAuth - false for user authentication enabled
382  *   - perMessageAuth - false for per message authentication enabled
383  *   - KGStatus - true for Kg required for authentication
384  *   - reserved2
385  *   - rmcp - RMCP (IPMI 1.5) connection support
386  *   - rmcpp - RMCP+ (IPMI 2.0) connection support
387  *   - reserved3
388  *   - oemID - OEM IANA of any OEM auth support
389  *   - oemAuxillary - OEM data for auth
390  */
391 ipmi::RspType<uint8_t,  // channel number
392               uint6_t,  // rmcpAuthTypes
393               bool,     // reserved1
394               bool,     // extDataSupport
395               bool,     // anonymousLogin
396               bool,     // nullUsers
397               bool,     // nonNullUsers
398               bool,     // userAuth
399               bool,     // perMessageAuth
400               bool,     // KGStatus
401               uint2_t,  // reserved2
402               bool,     // rmcp
403               bool,     // rmcpp
404               uint6_t,  // reserved3
405               uint24_t, // oemID
406               uint8_t   // oemAuxillary
407               >
408     ipmiGetChannelAuthenticationCapabilities(ipmi::Context::ptr ctx,
409                                              uint4_t chNum, uint3_t reserved1,
410                                              [[maybe_unused]] bool extData,
411                                              uint4_t privLevel,
412                                              uint4_t reserved2)
413 {
414     uint8_t channel = convertCurrentChannelNum(static_cast<uint8_t>(chNum),
415                                                ctx->channel);
416 
417     if (reserved1 || reserved2 || !isValidChannel(channel) ||
418         !isValidPrivLimit(static_cast<uint8_t>(privLevel)))
419     {
420         lg2::debug("Get channel auth capabilities - Invalid field in request");
421         return ipmi::responseInvalidFieldRequest();
422     }
423 
424     if (getChannelSessionSupport(channel) == EChannelSessSupported::none)
425     {
426         lg2::debug("Get channel auth capabilities - No support on channel");
427         return ipmi::response(ccActionNotSupportedForChannel);
428     }
429 
430     constexpr bool extDataSupport = true; // true for IPMI 2.0 extensions
431     constexpr bool reserved3 = false;
432     constexpr uint6_t rmcpAuthTypes = 0;  // IPMI 1.5 auth types - not supported
433     constexpr uint2_t reserved4 = 0;
434     constexpr bool KGStatus = false;      // Not supporting now.
435     constexpr bool perMessageAuth = false; // Per message auth - enabled
436     constexpr bool userAuth = false;       // User authentication - enabled
437     constexpr bool nullUsers = false;      // Null user names - not supported
438     constexpr bool anonymousLogin = false; // Anonymous login - not supported
439     constexpr uint6_t reserved5 = 0;
440     constexpr bool rmcpp = true;           // IPMI 2.0 - supported
441     constexpr bool rmcp = false;           // IPMI 1.5 - not supported
442     constexpr uint24_t oemID = 0;
443     constexpr uint8_t oemAuxillary = 0;
444 
445     bool nonNullUsers = 0;
446     uint8_t maxChUsers = 0, enabledUsers = 0, fixedUsers = 0;
447     ipmi::ipmiUserGetAllCounts(maxChUsers, enabledUsers, fixedUsers);
448     nonNullUsers = enabledUsers > 0;
449 
450     return ipmi::responseSuccess(
451         channel, rmcpAuthTypes, reserved3, extDataSupport, anonymousLogin,
452         nullUsers, nonNullUsers, userAuth, perMessageAuth, KGStatus, reserved4,
453         rmcp, rmcpp, reserved5, oemID, oemAuxillary);
454 }
455 
456 /** @brief implements the set user payload access command.
457  *  @param ctx - IPMI context pointer (for channel)
458  *  @param channel - channel number (4 bits)
459  *  @param reserved1 - skip 4 bits
460  *  @param userId - user id (6 bits)
461  *  @param operation - access ENABLE /DISABLE. (2 bits)
462  *  @param stdPayload0 - IPMI - reserved. (1 bit)
463  *  @param stdPayload1 - SOL.             (1 bit)
464  *  @param stdPayload2 -                  (1 bit)
465  *  @param stdPayload3 -                  (1 bit)
466  *  @param stdPayload4 -                  (1 bit)
467  *  @param stdPayload5 -                  (1 bit)
468  *  @param stdPayload6 -                  (1 bit)
469  *  @param stdPayload7 -                  (1 bit)
470  *  @param stdPayloadEnables2Reserved -   (8 bits)
471  *  @param oemPayload0 -                  (1 bit)
472  *  @param oemPayload1 -                  (1 bit)
473  *  @param oemPayload2 -                  (1 bit)
474  *  @param oemPayload3 -                  (1 bit)
475  *  @param oemPayload4 -                  (1 bit)
476  *  @param oemPayload5 -                  (1 bit)
477  *  @param oemPayload6 -                  (1 bit)
478  *  @param oemPayload7 -                  (1 bit)
479  *  @param oemPayloadEnables2Reserved -   (8 bits)
480  *
481  *  @returns IPMI completion code
482  */
483 ipmi::RspType<> ipmiSetUserPayloadAccess(
484     ipmi::Context::ptr ctx,
485 
486     uint4_t channel, uint4_t reserved,
487 
488     uint6_t userId, uint2_t operation,
489 
490     bool stdPayload0ipmiReserved, bool stdPayload1SOL, bool stdPayload2,
491     bool stdPayload3, bool stdPayload4, bool stdPayload5, bool stdPayload6,
492     bool stdPayload7,
493 
494     uint8_t stdPayloadEnables2Reserved,
495 
496     bool oemPayload0, bool oemPayload1, bool oemPayload2, bool oemPayload3,
497     bool oemPayload4, bool oemPayload5, bool oemPayload6, bool oemPayload7,
498 
499     uint8_t oemPayloadEnables2Reserved)
500 {
501     auto chNum = convertCurrentChannelNum(static_cast<uint8_t>(channel),
502                                           ctx->channel);
503     // Validate the reserved args. Only SOL payload is supported as on date.
504     if (reserved || stdPayload0ipmiReserved || stdPayload2 || stdPayload3 ||
505         stdPayload4 || stdPayload5 || stdPayload6 || stdPayload7 ||
506         oemPayload0 || oemPayload1 || oemPayload2 || oemPayload3 ||
507         oemPayload4 || oemPayload5 || oemPayload6 || oemPayload7 ||
508         stdPayloadEnables2Reserved || oemPayloadEnables2Reserved ||
509         !isValidChannel(chNum))
510     {
511         return ipmi::responseInvalidFieldRequest();
512     }
513 
514     if ((operation != enableOperation && operation != disableOperation))
515     {
516         return ipmi::responseInvalidFieldRequest();
517     }
518     if (getChannelSessionSupport(chNum) == EChannelSessSupported::none)
519     {
520         return ipmi::response(ccActionNotSupportedForChannel);
521     }
522     if (!ipmiUserIsValidUserId(static_cast<uint8_t>(userId)))
523     {
524         return ipmi::responseParmOutOfRange();
525     }
526 
527     PayloadAccess payloadAccess = {};
528     payloadAccess.stdPayloadEnables1[1] = stdPayload1SOL;
529 
530     return ipmi::response(ipmiUserSetUserPayloadAccess(
531         chNum, static_cast<uint8_t>(operation), static_cast<uint8_t>(userId),
532         payloadAccess));
533 }
534 
535 /** @brief implements the get user payload access command
536  *  This command returns information about user payload enable settings
537  *  that were set using the 'Set User Payload Access' Command.
538  *
539  *  @param ctx - IPMI context pointer (for channel)
540  *  @param channel - channel number
541  *  @param reserved1 - skip 4 bits
542  *  @param userId - user id
543  *  @param reserved2 - skip 2 bits
544  *
545  *  @returns IPMI completion code plus response data
546  *   - stdPayload0ipmiReserved - IPMI payload (reserved).
547  *   - stdPayload1SOL - SOL payload
548  *   - stdPayload2
549  *   - stdPayload3
550  *   - stdPayload4
551  *   - stdPayload5
552  *   - stdPayload6
553  *   - stdPayload7
554 
555  *   - stdPayloadEnables2Reserved - Reserved.
556 
557  *   - oemPayload0
558  *   - oemPayload1
559  *   - oemPayload2
560  *   - oemPayload3
561  *   - oemPayload4
562  *   - oemPayload5
563  *   - oemPayload6
564  *   - oemPayload7
565 
566  *  - oemPayloadEnables2Reserved - Reserved
567  */
568 ipmi::RspType<bool,    // stdPayload0ipmiReserved
569               bool,    // stdPayload1SOL
570               bool,    // stdPayload2
571               bool,    // stdPayload3
572               bool,    // stdPayload4
573               bool,    // stdPayload5
574               bool,    // stdPayload6
575               bool,    // stdPayload7
576 
577               uint8_t, // stdPayloadEnables2Reserved
578 
579               bool,    // oemPayload0
580               bool,    // oemPayload1
581               bool,    // oemPayload2
582               bool,    // oemPayload3
583               bool,    // oemPayload4
584               bool,    // oemPayload5
585               bool,    // oemPayload6
586               bool,    // oemPayload7
587 
588               uint8_t  // oemPayloadEnables2Reserved
589               >
590     ipmiGetUserPayloadAccess(ipmi::Context::ptr ctx,
591 
592                              uint4_t channel, uint4_t reserved1,
593 
594                              uint6_t userId, uint2_t reserved2)
595 {
596     uint8_t chNum = convertCurrentChannelNum(static_cast<uint8_t>(channel),
597                                              ctx->channel);
598 
599     if (reserved1 || reserved2 || !isValidChannel(chNum))
600     {
601         return ipmi::responseInvalidFieldRequest();
602     }
603     if (getChannelSessionSupport(chNum) == EChannelSessSupported::none)
604     {
605         return ipmi::response(ccActionNotSupportedForChannel);
606     }
607     if (!ipmiUserIsValidUserId(static_cast<uint8_t>(userId)))
608     {
609         return ipmi::responseParmOutOfRange();
610     }
611 
612     ipmi::Cc retStatus;
613     PayloadAccess payloadAccess = {};
614     retStatus = ipmiUserGetUserPayloadAccess(
615         chNum, static_cast<uint8_t>(userId), payloadAccess);
616     if (retStatus != ccSuccess)
617     {
618         return ipmi::response(retStatus);
619     }
620     constexpr uint8_t res8bits = 0;
621     return ipmi::responseSuccess(payloadAccess.stdPayloadEnables1.test(0),
622                                  payloadAccess.stdPayloadEnables1.test(1),
623                                  payloadAccess.stdPayloadEnables1.test(2),
624                                  payloadAccess.stdPayloadEnables1.test(3),
625                                  payloadAccess.stdPayloadEnables1.test(4),
626                                  payloadAccess.stdPayloadEnables1.test(5),
627                                  payloadAccess.stdPayloadEnables1.test(6),
628                                  payloadAccess.stdPayloadEnables1.test(7),
629 
630                                  res8bits,
631 
632                                  payloadAccess.oemPayloadEnables1.test(0),
633                                  payloadAccess.oemPayloadEnables1.test(1),
634                                  payloadAccess.oemPayloadEnables1.test(2),
635                                  payloadAccess.oemPayloadEnables1.test(3),
636                                  payloadAccess.oemPayloadEnables1.test(4),
637                                  payloadAccess.oemPayloadEnables1.test(5),
638                                  payloadAccess.oemPayloadEnables1.test(6),
639                                  payloadAccess.oemPayloadEnables1.test(7),
640 
641                                  res8bits);
642 }
643 
644 void registerUserIpmiFunctions() __attribute__((constructor));
645 void registerUserIpmiFunctions()
646 {
647     post_work([]() { ipmiUserInit(); });
648     ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
649                           ipmi::app::cmdSetUserAccessCommand,
650                           ipmi::Privilege::Admin, ipmiSetUserAccess);
651 
652     ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
653                           ipmi::app::cmdGetUserAccessCommand,
654                           ipmi::Privilege::Admin, ipmiGetUserAccess);
655 
656     ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
657                           ipmi::app::cmdGetUserNameCommand,
658                           ipmi::Privilege::Admin, ipmiGetUserName);
659 
660     ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
661                           ipmi::app::cmdSetUserName, ipmi::Privilege::Admin,
662                           ipmiSetUserName);
663 
664     ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
665                           ipmi::app::cmdSetUserPasswordCommand,
666                           ipmi::Privilege::Admin, ipmiSetUserPassword);
667 
668     ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
669                           ipmi::app::cmdGetChannelAuthCapabilities,
670                           ipmi::Privilege::Callback,
671                           ipmiGetChannelAuthenticationCapabilities);
672 
673     ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
674                           ipmi::app::cmdSetUserPayloadAccess,
675                           ipmi::Privilege::Admin, ipmiSetUserPayloadAccess);
676 
677     ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
678                           ipmi::app::cmdGetUserPayloadAccess,
679                           ipmi::Privilege::Operator, ipmiGetUserPayloadAccess);
680 
681     return;
682 }
683 } // namespace ipmi
684