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     size_t nameLen = strnlen(reinterpret_cast<const char*>(req->userName),
296                              sizeof(req->userName));
297     const std::string strUserName(reinterpret_cast<const char*>(req->userName),
298                                   nameLen);
299 
300     return ipmiUserSetUserName(req->userId, strUserName);
301 }
302 
303 /** @brief implementes the get user name command
304  *  @param[in] netfn - specifies netfn.
305  *  @param[in] cmd   - specifies cmd number.
306  *  @param[in] request - pointer to request data.
307  *  @param[in, out] dataLen - specifies request data length, and returns
308  * response data length.
309  *  @param[in] context - ipmi context.
310  *  @returns ipmi completion code.
311  */
312 Cc ipmiGetUserName(ipmi_netfn_t netfn, ipmi_cmd_t cmd, ipmi_request_t request,
313                    ipmi_response_t response, ipmi_data_len_t dataLen,
314                    ipmi_context_t context)
315 {
316     const GetUserNameReq* req = static_cast<GetUserNameReq*>(request);
317     size_t reqLength = *dataLen;
318 
319     *dataLen = 0;
320 
321     if (reqLength != sizeof(*req))
322     {
323         log<level::DEBUG>("Get user name - Invalid Length");
324         return ccReqDataLenInvalid;
325     }
326 
327     std::string userName;
328     if (ipmiUserGetUserName(req->userId, userName) != ccSuccess)
329     { // Invalid User ID
330         log<level::DEBUG>("User Name not found",
331                           entry("USER-ID=%d", (uint8_t)req->userId));
332         return ccParmOutOfRange;
333     }
334     GetUserNameResp* resp = static_cast<GetUserNameResp*>(response);
335     std::fill(reinterpret_cast<uint8_t*>(resp),
336               reinterpret_cast<uint8_t*>(resp) + sizeof(*resp), 0);
337     userName.copy(reinterpret_cast<char*>(resp->userName),
338                   sizeof(resp->userName), 0);
339     *dataLen = sizeof(*resp);
340 
341     return ccSuccess;
342 }
343 
344 /** @brief implementes the set user password command
345  *  @param[in] netfn - specifies netfn.
346  *  @param[in] cmd   - specifies cmd number.
347  *  @param[in] request - pointer to request data.
348  *  @param[in, out] dataLen - specifies request data length, and returns
349  * response data length.
350  *  @param[in] context - ipmi context.
351  *  @returns ipmi completion code.
352  */
353 Cc ipmiSetUserPassword(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
354                        ipmi_request_t request, ipmi_response_t response,
355                        ipmi_data_len_t dataLen, ipmi_context_t context)
356 {
357     const SetUserPasswordReq* req = static_cast<SetUserPasswordReq*>(request);
358     size_t reqLength = *dataLen;
359     // subtract 2 bytes header to know the password length - including NULL
360     uint8_t passwordLength = *dataLen - 2;
361     *dataLen = 0;
362 
363     // verify input length based on operation. Required password size is 20
364     // bytes as  we support only IPMI 2.0, but in order to be compatible with
365     // tools, accept 16 bytes of password size too.
366     if (reqLength < 2 ||
367         // If enable / disable user, reqLength has to be >=2 & <= 22
368         ((req->operation == disableUser || req->operation == enableUser) &&
369          ((reqLength < 2) || (reqLength > sizeof(SetUserPasswordReq)))))
370     {
371         log<level::DEBUG>("Invalid Length");
372         return ccReqDataLenInvalid;
373     }
374     // If set / test password then password length has to be 16 or 20 bytes
375     // based on the password size bit.
376     if (((req->operation == setPassword) || (req->operation == testPassword)) &&
377         (((req->ipmi20 == passwordKeySize20) &&
378           (passwordLength != maxIpmi20PasswordSize)) ||
379          ((req->ipmi20 == passwordKeySize16) &&
380           (passwordLength != maxIpmi15PasswordSize))))
381     {
382         log<level::DEBUG>("Invalid Length");
383         return ccReqDataLenInvalid;
384     }
385 
386     std::string userName;
387     if (ipmiUserGetUserName(req->userId, userName) != ccSuccess)
388     {
389         log<level::DEBUG>("User Name not found",
390                           entry("USER-ID=%d", (uint8_t)req->userId));
391         return ccParmOutOfRange;
392     }
393     if (req->operation == setPassword)
394     {
395         return ipmiUserSetUserPassword(
396             req->userId, reinterpret_cast<const char*>(req->userPassword));
397     }
398     else if (req->operation == enableUser || req->operation == disableUser)
399     {
400         return ipmiUserUpdateEnabledState(req->userId,
401                                           static_cast<bool>(req->operation));
402     }
403     else if (req->operation == testPassword)
404     {
405         auto password = ipmiUserGetPassword(userName);
406         std::string testPassword(
407             reinterpret_cast<const char*>(req->userPassword), 0,
408             passwordLength);
409         // Note: For security reasons password size won't be compared and
410         // wrong password size completion code will not be returned if size
411         // doesn't match as specified in IPMI specification.
412         if (password != testPassword)
413         {
414             log<level::DEBUG>("Test password failed",
415                               entry("USER-ID=%d", (uint8_t)req->userId));
416             return static_cast<Cc>(
417                 IPMISetPasswordReturnCodes::ipmiCCPasswdFailMismatch);
418         }
419         return ccSuccess;
420     }
421     return ccInvalidFieldRequest;
422 }
423 
424 /** @brief implements the get channel authentication command
425  *  @param ctx - IPMI context pointer (for channel)
426  *  @param extData - get IPMI 2.0 extended data
427  *  @param reserved1 - skip 3 bits
428  *  @param chNum - channel number to get info about
429  *  @param reserved2 - skip 4 bits
430  *  @param privLevel - requested privilege level
431 
432  *  @returns ipmi completion code plus response data
433  *   - channel number
434  *   - rmcpAuthTypes - RMCP auth types (IPMI 1.5)
435  *   - reserved1
436  *   - extDataSupport - true for IPMI 2.0 extensions
437  *   - anonymousLogin - true for anonymous login enabled
438  *   - nullUsers - true for null user names enabled
439  *   - nonNullUsers - true for non-null usernames enabled
440  *   - userAuth - false for user authentication enabled
441  *   - perMessageAuth - false for per message authentication enabled
442  *   - KGStatus - true for Kg required for authentication
443  *   - reserved2
444  *   - rmcp - RMCP (IPMI 1.5) connection support
445  *   - rmcpp - RMCP+ (IPMI 2.0) connection support
446  *   - reserved3
447  *   - oemID - OEM IANA of any OEM auth support
448  *   - oemAuxillary - OEM data for auth
449  */
450 ipmi::RspType<uint8_t,  // channel number
451               uint6_t,  // rmcpAuthTypes
452               bool,     // reserved1
453               bool,     // extDataSupport
454               bool,     // anonymousLogin
455               bool,     // nullUsers
456               bool,     // nonNullUsers
457               bool,     // userAuth
458               bool,     // perMessageAuth
459               bool,     // KGStatus
460               uint2_t,  // reserved2
461               bool,     // rmcp
462               bool,     // rmcpp
463               uint6_t,  // reserved3
464               uint24_t, // oemID
465               uint8_t   // oemAuxillary
466               >
467     ipmiGetChannelAuthenticationCapabilities(ipmi::Context::ptr ctx,
468                                              uint4_t chNum, uint3_t reserved1,
469                                              bool extData, uint4_t privLevel,
470                                              uint4_t reserved2)
471 {
472     uint8_t channel =
473         convertCurrentChannelNum(static_cast<uint8_t>(chNum), ctx->channel);
474 
475     if (reserved1 || reserved2 || !isValidChannel(channel) ||
476         !isValidPrivLimit(static_cast<uint8_t>(privLevel)))
477     {
478         log<level::DEBUG>(
479             "Get channel auth capabilities - Invalid field in request");
480         return ipmi::responseInvalidFieldRequest();
481     }
482 
483     if (getChannelSessionSupport(channel) == EChannelSessSupported::none)
484     {
485         log<level::DEBUG>(
486             "Get channel auth capabilities - No support on channel");
487         return ipmi::response(ccActionNotSupportedForChannel);
488     }
489 
490     constexpr bool extDataSupport = true; // true for IPMI 2.0 extensions
491     constexpr bool reserved3 = false;
492     constexpr uint6_t rmcpAuthTypes = 0; // IPMI 1.5 auth types - not supported
493     constexpr uint2_t reserved4 = 0;
494     constexpr bool KGStatus = false;       // Not supporting now.
495     constexpr bool perMessageAuth = false; // Per message auth - enabled
496     constexpr bool userAuth = false;       // User authentication - enabled
497     constexpr bool nullUsers = false;      // Null user names - not supported
498     constexpr bool anonymousLogin = false; // Anonymous login - not supported
499     constexpr uint6_t reserved5 = 0;
500     constexpr bool rmcpp = true; // IPMI 2.0 - supported
501     constexpr bool rmcp = false; // IPMI 1.5 - not supported
502     constexpr uint24_t oemID = 0;
503     constexpr uint8_t oemAuxillary = 0;
504 
505     bool nonNullUsers = 0;
506     uint8_t maxChUsers = 0, enabledUsers = 0, fixedUsers = 0;
507     ipmi::ipmiUserGetAllCounts(maxChUsers, enabledUsers, fixedUsers);
508     nonNullUsers = enabledUsers > 0;
509 
510     return ipmi::responseSuccess(
511         channel, rmcpAuthTypes, reserved3, extDataSupport, anonymousLogin,
512         nullUsers, nonNullUsers, userAuth, perMessageAuth, KGStatus, reserved4,
513         rmcp, rmcpp, reserved5, oemID, oemAuxillary);
514 }
515 
516 /** @brief implements the set user payload access command.
517  *  @param ctx - IPMI context pointer (for channel)
518  *  @param channel - channel number (4 bits)
519  *  @param reserved1 - skip 4 bits
520  *  @param userId - user id (6 bits)
521  *  @param operation - access ENABLE /DISABLE. (2 bits)
522  *  @param stdPayload0 - IPMI - reserved. (1 bit)
523  *  @param stdPayload1 - SOL.             (1 bit)
524  *  @param stdPayload2 -                  (1 bit)
525  *  @param stdPayload3 -                  (1 bit)
526  *  @param stdPayload4 -                  (1 bit)
527  *  @param stdPayload5 -                  (1 bit)
528  *  @param stdPayload6 -                  (1 bit)
529  *  @param stdPayload7 -                  (1 bit)
530  *  @param stdPayloadEnables2Reserved -   (8 bits)
531  *  @param oemPayload0 -                  (1 bit)
532  *  @param oemPayload1 -                  (1 bit)
533  *  @param oemPayload2 -                  (1 bit)
534  *  @param oemPayload3 -                  (1 bit)
535  *  @param oemPayload4 -                  (1 bit)
536  *  @param oemPayload5 -                  (1 bit)
537  *  @param oemPayload6 -                  (1 bit)
538  *  @param oemPayload7 -                  (1 bit)
539  *  @param oemPayloadEnables2Reserved -   (8 bits)
540  *
541  *  @returns IPMI completion code
542  */
543 ipmi::RspType<> ipmiSetUserPayloadAccess(
544     ipmi::Context::ptr ctx,
545 
546     uint4_t channel, uint4_t reserved,
547 
548     uint6_t userId, uint2_t operation,
549 
550     bool stdPayload0ipmiReserved, bool stdPayload1SOL, bool stdPayload2,
551     bool stdPayload3, bool stdPayload4, bool stdPayload5, bool stdPayload6,
552     bool stdPayload7,
553 
554     uint8_t stdPayloadEnables2Reserved,
555 
556     bool oemPayload0, bool oemPayload1, bool oemPayload2, bool oemPayload3,
557     bool oemPayload4, bool oemPayload5, bool oemPayload6, bool oemPayload7,
558 
559     uint8_t oemPayloadEnables2Reserved)
560 {
561     auto chNum =
562         convertCurrentChannelNum(static_cast<uint8_t>(channel), ctx->channel);
563     // Validate the reserved args. Only SOL payload is supported as on date.
564     if (reserved || stdPayload0ipmiReserved || stdPayload2 || stdPayload3 ||
565         stdPayload4 || stdPayload5 || stdPayload6 || stdPayload7 ||
566         oemPayload0 || oemPayload1 || oemPayload2 || oemPayload3 ||
567         oemPayload4 || oemPayload5 || oemPayload6 || oemPayload7 ||
568         stdPayloadEnables2Reserved || oemPayloadEnables2Reserved ||
569         !isValidChannel(chNum))
570     {
571         return ipmi::responseInvalidFieldRequest();
572     }
573 
574     if ((operation != enableOperation && operation != disableOperation))
575     {
576         return ipmi::responseInvalidFieldRequest();
577     }
578     if (getChannelSessionSupport(chNum) == EChannelSessSupported::none)
579     {
580         return ipmi::response(ccActionNotSupportedForChannel);
581     }
582     if (!ipmiUserIsValidUserId(static_cast<uint8_t>(userId)))
583     {
584         return ipmi::responseParmOutOfRange();
585     }
586 
587     PayloadAccess payloadAccess = {0};
588     payloadAccess.stdPayloadEnables1[1] = stdPayload1SOL;
589 
590     return ipmi::response(ipmiUserSetUserPayloadAccess(
591         chNum, static_cast<uint8_t>(operation), static_cast<uint8_t>(userId),
592         payloadAccess));
593 }
594 
595 /** @brief implements the get user payload access command
596  *  This command returns information about user payload enable settings
597  *  that were set using the 'Set User Payload Access' Command.
598  *
599  *  @param ctx - IPMI context pointer (for channel)
600  *  @param channel - channel number
601  *  @param reserved1 - skip 4 bits
602  *  @param userId - user id
603  *  @param reserved2 - skip 2 bits
604  *
605  *  @returns IPMI completion code plus response data
606  *   - stdPayload0ipmiReserved - IPMI payload (reserved).
607  *   - stdPayload1SOL - SOL payload
608  *   - stdPayload2
609  *   - stdPayload3
610  *   - stdPayload4
611  *   - stdPayload5
612  *   - stdPayload6
613  *   - stdPayload7
614 
615  *   - stdPayloadEnables2Reserved - Reserved.
616 
617  *   - oemPayload0
618  *   - oemPayload1
619  *   - oemPayload2
620  *   - oemPayload3
621  *   - oemPayload4
622  *   - oemPayload5
623  *   - oemPayload6
624  *   - oemPayload7
625 
626  *  - oemPayloadEnables2Reserved - Reserved
627  */
628 ipmi::RspType<bool, // stdPayload0ipmiReserved
629               bool, // stdPayload1SOL
630               bool, // stdPayload2
631               bool, // stdPayload3
632               bool, // stdPayload4
633               bool, // stdPayload5
634               bool, // stdPayload6
635               bool, // stdPayload7
636 
637               uint8_t, // stdPayloadEnables2Reserved
638 
639               bool, // oemPayload0
640               bool, // oemPayload1
641               bool, // oemPayload2
642               bool, // oemPayload3
643               bool, // oemPayload4
644               bool, // oemPayload5
645               bool, // oemPayload6
646               bool, // oemPayload7
647 
648               uint8_t // oemPayloadEnables2Reserved
649               >
650     ipmiGetUserPayloadAccess(ipmi::Context::ptr ctx,
651 
652                              uint4_t channel, uint4_t reserved1,
653 
654                              uint6_t userId, uint2_t reserved2)
655 {
656     uint8_t chNum =
657         convertCurrentChannelNum(static_cast<uint8_t>(channel), ctx->channel);
658 
659     if (reserved1 || reserved2 || !isValidChannel(chNum))
660     {
661         return ipmi::responseInvalidFieldRequest();
662     }
663     if (getChannelSessionSupport(chNum) == EChannelSessSupported::none)
664     {
665         return ipmi::response(ccActionNotSupportedForChannel);
666     }
667     if (!ipmiUserIsValidUserId(static_cast<uint8_t>(userId)))
668     {
669         return ipmi::responseParmOutOfRange();
670     }
671 
672     ipmi::Cc retStatus;
673     PayloadAccess payloadAccess = {};
674     retStatus = ipmiUserGetUserPayloadAccess(
675         chNum, static_cast<uint8_t>(userId), payloadAccess);
676     if (retStatus != ccSuccess)
677     {
678         return ipmi::response(retStatus);
679     }
680     constexpr uint8_t res8bits = 0;
681     return ipmi::responseSuccess(payloadAccess.stdPayloadEnables1.test(0),
682                                  payloadAccess.stdPayloadEnables1.test(1),
683                                  payloadAccess.stdPayloadEnables1.test(2),
684                                  payloadAccess.stdPayloadEnables1.test(3),
685                                  payloadAccess.stdPayloadEnables1.test(4),
686                                  payloadAccess.stdPayloadEnables1.test(5),
687                                  payloadAccess.stdPayloadEnables1.test(6),
688                                  payloadAccess.stdPayloadEnables1.test(7),
689 
690                                  res8bits,
691 
692                                  payloadAccess.oemPayloadEnables1.test(0),
693                                  payloadAccess.oemPayloadEnables1.test(1),
694                                  payloadAccess.oemPayloadEnables1.test(2),
695                                  payloadAccess.oemPayloadEnables1.test(3),
696                                  payloadAccess.oemPayloadEnables1.test(4),
697                                  payloadAccess.oemPayloadEnables1.test(5),
698                                  payloadAccess.oemPayloadEnables1.test(6),
699                                  payloadAccess.oemPayloadEnables1.test(7),
700 
701                                  res8bits);
702 }
703 
704 void registerUserIpmiFunctions() __attribute__((constructor));
705 void registerUserIpmiFunctions()
706 {
707     post_work([]() { ipmiUserInit(); });
708     ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
709                           ipmi::app::cmdSetUserAccessCommand,
710                           ipmi::Privilege::Admin, ipmiSetUserAccess);
711 
712     ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
713                           ipmi::app::cmdGetUserAccessCommand,
714                           ipmi::Privilege::Operator, ipmiGetUserAccess);
715 
716     ipmi_register_callback(NETFUN_APP, IPMI_CMD_GET_USER_NAME, NULL,
717                            ipmiGetUserName, PRIVILEGE_OPERATOR);
718 
719     ipmi_register_callback(NETFUN_APP, IPMI_CMD_SET_USER_NAME, NULL,
720                            ipmiSetUserName, PRIVILEGE_ADMIN);
721 
722     ipmi_register_callback(NETFUN_APP, IPMI_CMD_SET_USER_PASSWORD, NULL,
723                            ipmiSetUserPassword, PRIVILEGE_ADMIN);
724 
725     ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
726                           ipmi::app::cmdGetChannelAuthCapabilities,
727                           ipmi::Privilege::Callback,
728                           ipmiGetChannelAuthenticationCapabilities);
729 
730     ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
731                           ipmi::app::cmdSetUserPayloadAccess,
732                           ipmi::Privilege::Admin, ipmiSetUserPayloadAccess);
733 
734     ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
735                           ipmi::app::cmdGetUserPayloadAccess,
736                           ipmi::Privilege::Operator, ipmiGetUserPayloadAccess);
737 
738     return;
739 }
740 } // namespace ipmi
741