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