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