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