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