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