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