xref: /openbmc/phosphor-host-ipmid/user_channel/usercommands.cpp (revision ef1259becab17e03cf31bc74e9db34ac98dd4298)
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         SecureString password = ipmiUserGetPassword(userName);
362         SecureString testPassword(
363             reinterpret_cast<const char*>(req->userPassword), passwordLength);
364         // constant time string compare: always compare exactly as many bytes
365         // as the length of the input, resizing the actual password to match,
366         // maintaining a knowledge if the sizes differed originally
367         static const std::array<char, maxIpmi20PasswordSize> empty = {'\0'};
368         size_t cmpLen = testPassword.size();
369         bool pwLenDiffers = password.size() != cmpLen;
370         const char* cmpPassword = nullptr;
371         if (pwLenDiffers)
372         {
373             cmpPassword = empty.data();
374         }
375         else
376         {
377             cmpPassword = password.data();
378         }
379         bool pwBad = CRYPTO_memcmp(cmpPassword, testPassword.data(), cmpLen);
380         pwBad |= pwLenDiffers;
381         if (pwBad)
382         {
383             log<level::DEBUG>("Test password failed",
384                               entry("USER-ID=%d", (uint8_t)req->userId));
385             return static_cast<Cc>(
386                 IPMISetPasswordReturnCodes::ipmiCCPasswdFailMismatch);
387         }
388         return ccSuccess;
389     }
390     return ccInvalidFieldRequest;
391 }
392 
393 /** @brief implements the get channel authentication command
394  *  @param ctx - IPMI context pointer (for channel)
395  *  @param extData - get IPMI 2.0 extended data
396  *  @param reserved1 - skip 3 bits
397  *  @param chNum - channel number to get info about
398  *  @param reserved2 - skip 4 bits
399  *  @param privLevel - requested privilege level
400 
401  *  @returns ipmi completion code plus response data
402  *   - channel number
403  *   - rmcpAuthTypes - RMCP auth types (IPMI 1.5)
404  *   - reserved1
405  *   - extDataSupport - true for IPMI 2.0 extensions
406  *   - anonymousLogin - true for anonymous login enabled
407  *   - nullUsers - true for null user names enabled
408  *   - nonNullUsers - true for non-null usernames enabled
409  *   - userAuth - false for user authentication enabled
410  *   - perMessageAuth - false for per message authentication enabled
411  *   - KGStatus - true for Kg required for authentication
412  *   - reserved2
413  *   - rmcp - RMCP (IPMI 1.5) connection support
414  *   - rmcpp - RMCP+ (IPMI 2.0) connection support
415  *   - reserved3
416  *   - oemID - OEM IANA of any OEM auth support
417  *   - oemAuxillary - OEM data for auth
418  */
419 ipmi::RspType<uint8_t,  // channel number
420               uint6_t,  // rmcpAuthTypes
421               bool,     // reserved1
422               bool,     // extDataSupport
423               bool,     // anonymousLogin
424               bool,     // nullUsers
425               bool,     // nonNullUsers
426               bool,     // userAuth
427               bool,     // perMessageAuth
428               bool,     // KGStatus
429               uint2_t,  // reserved2
430               bool,     // rmcp
431               bool,     // rmcpp
432               uint6_t,  // reserved3
433               uint24_t, // oemID
434               uint8_t   // oemAuxillary
435               >
436     ipmiGetChannelAuthenticationCapabilities(ipmi::Context::ptr ctx,
437                                              uint4_t chNum, uint3_t reserved1,
438                                              bool extData, uint4_t privLevel,
439                                              uint4_t reserved2)
440 {
441     uint8_t channel =
442         convertCurrentChannelNum(static_cast<uint8_t>(chNum), ctx->channel);
443 
444     if (reserved1 || reserved2 || !isValidChannel(channel) ||
445         !isValidPrivLimit(static_cast<uint8_t>(privLevel)))
446     {
447         log<level::DEBUG>(
448             "Get channel auth capabilities - Invalid field in request");
449         return ipmi::responseInvalidFieldRequest();
450     }
451 
452     if (getChannelSessionSupport(channel) == EChannelSessSupported::none)
453     {
454         log<level::DEBUG>(
455             "Get channel auth capabilities - No support on channel");
456         return ipmi::response(ccActionNotSupportedForChannel);
457     }
458 
459     constexpr bool extDataSupport = true; // true for IPMI 2.0 extensions
460     constexpr bool reserved3 = false;
461     constexpr uint6_t rmcpAuthTypes = 0; // IPMI 1.5 auth types - not supported
462     constexpr uint2_t reserved4 = 0;
463     constexpr bool KGStatus = false;       // Not supporting now.
464     constexpr bool perMessageAuth = false; // Per message auth - enabled
465     constexpr bool userAuth = false;       // User authentication - enabled
466     constexpr bool nullUsers = false;      // Null user names - not supported
467     constexpr bool anonymousLogin = false; // Anonymous login - not supported
468     constexpr uint6_t reserved5 = 0;
469     constexpr bool rmcpp = true; // IPMI 2.0 - supported
470     constexpr bool rmcp = false; // IPMI 1.5 - not supported
471     constexpr uint24_t oemID = 0;
472     constexpr uint8_t oemAuxillary = 0;
473 
474     bool nonNullUsers = 0;
475     uint8_t maxChUsers = 0, enabledUsers = 0, fixedUsers = 0;
476     ipmi::ipmiUserGetAllCounts(maxChUsers, enabledUsers, fixedUsers);
477     nonNullUsers = enabledUsers > 0;
478 
479     return ipmi::responseSuccess(
480         channel, rmcpAuthTypes, reserved3, extDataSupport, anonymousLogin,
481         nullUsers, nonNullUsers, userAuth, perMessageAuth, KGStatus, reserved4,
482         rmcp, rmcpp, reserved5, oemID, oemAuxillary);
483 }
484 
485 /** @brief implements the set user payload access command.
486  *  @param ctx - IPMI context pointer (for channel)
487  *  @param channel - channel number (4 bits)
488  *  @param reserved1 - skip 4 bits
489  *  @param userId - user id (6 bits)
490  *  @param operation - access ENABLE /DISABLE. (2 bits)
491  *  @param stdPayload0 - IPMI - reserved. (1 bit)
492  *  @param stdPayload1 - SOL.             (1 bit)
493  *  @param stdPayload2 -                  (1 bit)
494  *  @param stdPayload3 -                  (1 bit)
495  *  @param stdPayload4 -                  (1 bit)
496  *  @param stdPayload5 -                  (1 bit)
497  *  @param stdPayload6 -                  (1 bit)
498  *  @param stdPayload7 -                  (1 bit)
499  *  @param stdPayloadEnables2Reserved -   (8 bits)
500  *  @param oemPayload0 -                  (1 bit)
501  *  @param oemPayload1 -                  (1 bit)
502  *  @param oemPayload2 -                  (1 bit)
503  *  @param oemPayload3 -                  (1 bit)
504  *  @param oemPayload4 -                  (1 bit)
505  *  @param oemPayload5 -                  (1 bit)
506  *  @param oemPayload6 -                  (1 bit)
507  *  @param oemPayload7 -                  (1 bit)
508  *  @param oemPayloadEnables2Reserved -   (8 bits)
509  *
510  *  @returns IPMI completion code
511  */
512 ipmi::RspType<> ipmiSetUserPayloadAccess(
513     ipmi::Context::ptr ctx,
514 
515     uint4_t channel, uint4_t reserved,
516 
517     uint6_t userId, uint2_t operation,
518 
519     bool stdPayload0ipmiReserved, bool stdPayload1SOL, bool stdPayload2,
520     bool stdPayload3, bool stdPayload4, bool stdPayload5, bool stdPayload6,
521     bool stdPayload7,
522 
523     uint8_t stdPayloadEnables2Reserved,
524 
525     bool oemPayload0, bool oemPayload1, bool oemPayload2, bool oemPayload3,
526     bool oemPayload4, bool oemPayload5, bool oemPayload6, bool oemPayload7,
527 
528     uint8_t oemPayloadEnables2Reserved)
529 {
530     auto chNum =
531         convertCurrentChannelNum(static_cast<uint8_t>(channel), ctx->channel);
532     // Validate the reserved args. Only SOL payload is supported as on date.
533     if (reserved || stdPayload0ipmiReserved || stdPayload2 || stdPayload3 ||
534         stdPayload4 || stdPayload5 || stdPayload6 || stdPayload7 ||
535         oemPayload0 || oemPayload1 || oemPayload2 || oemPayload3 ||
536         oemPayload4 || oemPayload5 || oemPayload6 || oemPayload7 ||
537         stdPayloadEnables2Reserved || oemPayloadEnables2Reserved ||
538         !isValidChannel(chNum))
539     {
540         return ipmi::responseInvalidFieldRequest();
541     }
542 
543     if ((operation != enableOperation && operation != disableOperation))
544     {
545         return ipmi::responseInvalidFieldRequest();
546     }
547     if (getChannelSessionSupport(chNum) == EChannelSessSupported::none)
548     {
549         return ipmi::response(ccActionNotSupportedForChannel);
550     }
551     if (!ipmiUserIsValidUserId(static_cast<uint8_t>(userId)))
552     {
553         return ipmi::responseParmOutOfRange();
554     }
555 
556     PayloadAccess payloadAccess = {0};
557     payloadAccess.stdPayloadEnables1[1] = stdPayload1SOL;
558 
559     return ipmi::response(ipmiUserSetUserPayloadAccess(
560         chNum, static_cast<uint8_t>(operation), static_cast<uint8_t>(userId),
561         payloadAccess));
562 }
563 
564 /** @brief implements the get user payload access command
565  *  This command returns information about user payload enable settings
566  *  that were set using the 'Set User Payload Access' Command.
567  *
568  *  @param ctx - IPMI context pointer (for channel)
569  *  @param channel - channel number
570  *  @param reserved1 - skip 4 bits
571  *  @param userId - user id
572  *  @param reserved2 - skip 2 bits
573  *
574  *  @returns IPMI completion code plus response data
575  *   - stdPayload0ipmiReserved - IPMI payload (reserved).
576  *   - stdPayload1SOL - SOL payload
577  *   - stdPayload2
578  *   - stdPayload3
579  *   - stdPayload4
580  *   - stdPayload5
581  *   - stdPayload6
582  *   - stdPayload7
583 
584  *   - stdPayloadEnables2Reserved - Reserved.
585 
586  *   - oemPayload0
587  *   - oemPayload1
588  *   - oemPayload2
589  *   - oemPayload3
590  *   - oemPayload4
591  *   - oemPayload5
592  *   - oemPayload6
593  *   - oemPayload7
594 
595  *  - oemPayloadEnables2Reserved - Reserved
596  */
597 ipmi::RspType<bool, // stdPayload0ipmiReserved
598               bool, // stdPayload1SOL
599               bool, // stdPayload2
600               bool, // stdPayload3
601               bool, // stdPayload4
602               bool, // stdPayload5
603               bool, // stdPayload6
604               bool, // stdPayload7
605 
606               uint8_t, // stdPayloadEnables2Reserved
607 
608               bool, // oemPayload0
609               bool, // oemPayload1
610               bool, // oemPayload2
611               bool, // oemPayload3
612               bool, // oemPayload4
613               bool, // oemPayload5
614               bool, // oemPayload6
615               bool, // oemPayload7
616 
617               uint8_t // oemPayloadEnables2Reserved
618               >
619     ipmiGetUserPayloadAccess(ipmi::Context::ptr ctx,
620 
621                              uint4_t channel, uint4_t reserved1,
622 
623                              uint6_t userId, uint2_t reserved2)
624 {
625     uint8_t chNum =
626         convertCurrentChannelNum(static_cast<uint8_t>(channel), ctx->channel);
627 
628     if (reserved1 || reserved2 || !isValidChannel(chNum))
629     {
630         return ipmi::responseInvalidFieldRequest();
631     }
632     if (getChannelSessionSupport(chNum) == EChannelSessSupported::none)
633     {
634         return ipmi::response(ccActionNotSupportedForChannel);
635     }
636     if (!ipmiUserIsValidUserId(static_cast<uint8_t>(userId)))
637     {
638         return ipmi::responseParmOutOfRange();
639     }
640 
641     ipmi::Cc retStatus;
642     PayloadAccess payloadAccess = {};
643     retStatus = ipmiUserGetUserPayloadAccess(
644         chNum, static_cast<uint8_t>(userId), payloadAccess);
645     if (retStatus != ccSuccess)
646     {
647         return ipmi::response(retStatus);
648     }
649     constexpr uint8_t res8bits = 0;
650     return ipmi::responseSuccess(payloadAccess.stdPayloadEnables1.test(0),
651                                  payloadAccess.stdPayloadEnables1.test(1),
652                                  payloadAccess.stdPayloadEnables1.test(2),
653                                  payloadAccess.stdPayloadEnables1.test(3),
654                                  payloadAccess.stdPayloadEnables1.test(4),
655                                  payloadAccess.stdPayloadEnables1.test(5),
656                                  payloadAccess.stdPayloadEnables1.test(6),
657                                  payloadAccess.stdPayloadEnables1.test(7),
658 
659                                  res8bits,
660 
661                                  payloadAccess.oemPayloadEnables1.test(0),
662                                  payloadAccess.oemPayloadEnables1.test(1),
663                                  payloadAccess.oemPayloadEnables1.test(2),
664                                  payloadAccess.oemPayloadEnables1.test(3),
665                                  payloadAccess.oemPayloadEnables1.test(4),
666                                  payloadAccess.oemPayloadEnables1.test(5),
667                                  payloadAccess.oemPayloadEnables1.test(6),
668                                  payloadAccess.oemPayloadEnables1.test(7),
669 
670                                  res8bits);
671 }
672 
673 void registerUserIpmiFunctions() __attribute__((constructor));
674 void registerUserIpmiFunctions()
675 {
676     post_work([]() { ipmiUserInit(); });
677     ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
678                           ipmi::app::cmdSetUserAccessCommand,
679                           ipmi::Privilege::Admin, ipmiSetUserAccess);
680 
681     ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
682                           ipmi::app::cmdGetUserAccessCommand,
683                           ipmi::Privilege::Operator, ipmiGetUserAccess);
684 
685     ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
686                           ipmi::app::cmdGetUserNameCommand,
687                           ipmi::Privilege::Operator, ipmiGetUserName);
688 
689     ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
690                           ipmi::app::cmdSetUserName, ipmi::Privilege::Admin,
691                           ipmiSetUserName);
692 
693     ipmi_register_callback(NETFUN_APP, IPMI_CMD_SET_USER_PASSWORD, NULL,
694                            ipmiSetUserPassword, PRIVILEGE_ADMIN);
695 
696     ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
697                           ipmi::app::cmdGetChannelAuthCapabilities,
698                           ipmi::Privilege::Callback,
699                           ipmiGetChannelAuthenticationCapabilities);
700 
701     ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
702                           ipmi::app::cmdSetUserPayloadAccess,
703                           ipmi::Privilege::Admin, ipmiSetUserPayloadAccess);
704 
705     ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
706                           ipmi::app::cmdGetUserPayloadAccess,
707                           ipmi::Privilege::Operator, ipmiGetUserPayloadAccess);
708 
709     return;
710 }
711 } // namespace ipmi
712