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