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