1 /*
2 // Copyright (c) 2018 Intel Corporation
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //      http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 */
16 
17 #include "usercommands.hpp"
18 
19 #include "apphandler.hpp"
20 #include "channel_layer.hpp"
21 #include "user_layer.hpp"
22 
23 #include <security/pam_appl.h>
24 
25 #include <ipmid/api.hpp>
26 #include <phosphor-logging/log.hpp>
27 #include <regex>
28 
29 namespace ipmi
30 {
31 
32 using namespace phosphor::logging;
33 
34 static constexpr uint8_t disableUser = 0x00;
35 static constexpr uint8_t enableUser = 0x01;
36 static constexpr uint8_t setPassword = 0x02;
37 static constexpr uint8_t testPassword = 0x03;
38 static constexpr uint8_t passwordKeySize20 = 1;
39 static constexpr uint8_t passwordKeySize16 = 0;
40 static constexpr uint8_t enableOperation = 0x00;
41 static constexpr uint8_t disableOperation = 0x01;
42 
43 /** @struct SetUserNameReq
44  *
45  *  Structure for set user name request command (refer spec sec 22.28)
46  */
47 struct SetUserNameReq
48 {
49 #if BYTE_ORDER == LITTLE_ENDIAN
50     uint8_t userId : 6;
51     uint8_t reserved1 : 2;
52 #endif
53 #if BYTE_ORDER == BIG_ENDIAN
54     uint8_t reserved1 : 2;
55     uint8_t userId : 6;
56 #endif
57     uint8_t userName[16];
58 } __attribute__((packed));
59 
60 /** @struct GetUserNameReq
61  *
62  *  Structure for get user name request command (refer spec sec 22.29)
63  */
64 struct GetUserNameReq
65 {
66 #if BYTE_ORDER == LITTLE_ENDIAN
67     uint8_t userId : 6;
68     uint8_t reserved1 : 2;
69 #endif
70 #if BYTE_ORDER == BIG_ENDIAN
71     uint8_t reserved1 : 2;
72     uint8_t userId : 6;
73 #endif
74 } __attribute__((packed));
75 
76 /** @struct GetUserNameResp
77  *
78  *  Structure for get user name response command (refer spec sec 22.29)
79  */
80 struct GetUserNameResp
81 {
82     uint8_t userName[16];
83 } __attribute__((packed));
84 
85 /** @struct SetUserPasswordReq
86  *
87  *  Structure for set user password request command (refer spec sec 22.30)
88  */
89 struct SetUserPasswordReq
90 {
91 #if BYTE_ORDER == LITTLE_ENDIAN
92     uint8_t userId : 6;
93     uint8_t reserved1 : 1;
94     uint8_t ipmi20 : 1;
95     uint8_t operation : 2;
96     uint8_t reserved2 : 6;
97 #endif
98 #if BYTE_ORDER == BIG_ENDIAN
99     uint8_t ipmi20 : 1;
100     uint8_t reserved1 : 1;
101     uint8_t userId : 6;
102     uint8_t reserved2 : 6;
103     uint8_t operation : 2;
104 #endif
105     uint8_t userPassword[maxIpmi20PasswordSize];
106 } __attribute__((packed));
107 
108 /** @brief implements the set user access command
109  *  @param ctx - IPMI context pointer (for channel)
110  *  @param channel - channel number
111  *  @param ipmiEnabled - indicates ipmi messaging state
112  *  @param linkAuthEnabled - indicates link authentication state
113  *  @param accessCallback - indicates callback state
114  *  @param bitsUpdate - indicates update request
115  *  @param userId - user id
116  *  @param reserved1 - skip 2 bits
117  *  @param privilege - user privilege
118  *  @param reserved2 - skip 4 bits
119  *  @param sessionLimit - optional - unused for now
120  *
121  *  @returns ipmi completion code
122  */
123 ipmi::RspType<> ipmiSetUserAccess(ipmi::Context::ptr ctx, uint4_t channel,
124                                   uint1_t ipmiEnabled, uint1_t linkAuthEnabled,
125                                   uint1_t accessCallback, uint1_t bitsUpdate,
126 
127                                   uint6_t userId, uint2_t reserved1,
128 
129                                   uint4_t privilege, uint4_t reserved2,
130 
131                                   std::optional<uint8_t> sessionLimit)
132 {
133     uint8_t sessLimit = sessionLimit.value_or(0);
134     if (reserved1 || reserved2 || sessLimit ||
135         !ipmiUserIsValidPrivilege(static_cast<uint8_t>(privilege)))
136     {
137         log<level::DEBUG>("Set user access - Invalid field in request");
138         return ipmi::responseInvalidFieldRequest();
139     }
140 
141     uint8_t chNum =
142         convertCurrentChannelNum(static_cast<uint8_t>(channel), ctx->channel);
143     if (!isValidChannel(chNum))
144     {
145         log<level::DEBUG>("Set user access - Invalid channel request");
146         return ipmi::response(invalidChannel);
147     }
148     if (getChannelSessionSupport(chNum) == EChannelSessSupported::none)
149     {
150         log<level::DEBUG>("Set user access - No support on channel");
151         return ipmi::response(ccActionNotSupportedForChannel);
152     }
153     if (!ipmiUserIsValidUserId(static_cast<uint8_t>(userId)))
154     {
155         log<level::DEBUG>("Set user access - Parameter out of range");
156         return ipmi::responseParmOutOfRange();
157     }
158 
159     PrivAccess privAccess = {0};
160     if (bitsUpdate)
161     {
162         privAccess.ipmiEnabled = static_cast<uint8_t>(ipmiEnabled);
163         privAccess.linkAuthEnabled = static_cast<uint8_t>(linkAuthEnabled);
164         privAccess.accessCallback = static_cast<uint8_t>(accessCallback);
165     }
166     privAccess.privilege = static_cast<uint8_t>(privilege);
167     return ipmi::response(
168         ipmiUserSetPrivilegeAccess(static_cast<uint8_t>(userId), chNum,
169                                    privAccess, static_cast<bool>(bitsUpdate)));
170 }
171 
172 /** @brief implements the set user access command
173  *  @param ctx - IPMI context pointer (for channel)
174  *  @param channel - channel number
175  *  @param reserved1 - skip 4 bits
176  *  @param userId - user id
177  *  @param reserved2 - skip 2 bits
178  *
179  *  @returns ipmi completion code plus response data
180  *   - maxChUsers - max channel users
181  *   - reserved1 - skip 2 bits
182  *   - enabledUsers - enabled users count
183  *   - enabledStatus - enabled status
184  *   - fixedUsers - fixed users count
185  *   - reserved2 - skip 2 bits
186  *   - privilege - user privilege
187  *   - ipmiEnabled - ipmi messaging state
188  *   - linkAuthEnabled - link authenticatin state
189  *   - accessCallback - callback state
190  *   - reserved - skip 1 bit
191  */
192 ipmi::RspType<uint6_t, // max channel users
193               uint2_t, // reserved1
194 
195               uint6_t, // enabled users count
196               uint2_t, // enabled status
197 
198               uint6_t, // fixed users count
199               uint2_t, // reserved2
200 
201               uint4_t, // privilege
202               uint1_t, // ipmi messaging state
203               uint1_t, // link authentication state
204               uint1_t, // access callback state
205               uint1_t  // reserved3
206               >
207     ipmiGetUserAccess(ipmi::Context::ptr ctx, uint4_t channel,
208                       uint4_t reserved1,
209 
210                       uint6_t userId, uint2_t reserved2)
211 {
212     uint8_t chNum =
213         convertCurrentChannelNum(static_cast<uint8_t>(channel), ctx->channel);
214 
215     if (reserved1 || reserved2 || !isValidChannel(chNum))
216     {
217         log<level::DEBUG>("Get user access - Invalid field in request");
218         return ipmi::responseInvalidFieldRequest();
219     }
220 
221     if (getChannelSessionSupport(chNum) == EChannelSessSupported::none)
222     {
223         log<level::DEBUG>("Get user access - No support on channel");
224         return ipmi::response(ccActionNotSupportedForChannel);
225     }
226     if (!ipmiUserIsValidUserId(static_cast<uint8_t>(userId)))
227     {
228         log<level::DEBUG>("Get user access - Parameter out of range");
229         return ipmi::responseParmOutOfRange();
230     }
231 
232     uint8_t maxChUsers = 0, enabledUsers = 0, fixedUsers = 0;
233     ipmi::Cc retStatus;
234     retStatus = ipmiUserGetAllCounts(maxChUsers, enabledUsers, fixedUsers);
235     if (retStatus != ccSuccess)
236     {
237         return ipmi::response(retStatus);
238     }
239 
240     bool enabledState = false;
241     retStatus =
242         ipmiUserCheckEnabled(static_cast<uint8_t>(userId), enabledState);
243     if (retStatus != ccSuccess)
244     {
245         return ipmi::response(retStatus);
246     }
247 
248     uint2_t enabledStatus = enabledState ? userIdEnabledViaSetPassword
249                                          : userIdDisabledViaSetPassword;
250     PrivAccess privAccess{};
251     retStatus = ipmiUserGetPrivilegeAccess(static_cast<uint8_t>(userId), chNum,
252                                            privAccess);
253     if (retStatus != ccSuccess)
254     {
255         return ipmi::response(retStatus);
256     }
257     constexpr uint2_t res2Bits = 0;
258     return ipmi::responseSuccess(
259         static_cast<uint6_t>(maxChUsers), res2Bits,
260 
261         static_cast<uint6_t>(enabledUsers), enabledStatus,
262 
263         static_cast<uint6_t>(fixedUsers), res2Bits,
264 
265         static_cast<uint4_t>(privAccess.privilege),
266         static_cast<uint1_t>(privAccess.ipmiEnabled),
267         static_cast<uint1_t>(privAccess.linkAuthEnabled),
268         static_cast<uint1_t>(privAccess.accessCallback),
269         static_cast<uint1_t>(privAccess.reserved));
270 }
271 
272 Cc ipmiSetUserName(ipmi_netfn_t netfn, ipmi_cmd_t cmd, ipmi_request_t request,
273                    ipmi_response_t response, ipmi_data_len_t dataLen,
274                    ipmi_context_t context)
275 {
276     const SetUserNameReq* req = static_cast<SetUserNameReq*>(request);
277     size_t reqLength = *dataLen;
278     *dataLen = 0;
279 
280     if (reqLength != sizeof(*req))
281     {
282         log<level::DEBUG>("Set user name - Invalid Length");
283         return ccReqDataLenInvalid;
284     }
285     if (req->reserved1)
286     {
287         return ccInvalidFieldRequest;
288     }
289     if (!ipmiUserIsValidUserId(req->userId))
290     {
291         log<level::DEBUG>("Set user name - Invalid user id");
292         return ccParmOutOfRange;
293     }
294 
295     size_t nameLen = strnlen(reinterpret_cast<const char*>(req->userName),
296                              sizeof(req->userName));
297     const std::string strUserName(reinterpret_cast<const char*>(req->userName),
298                                   nameLen);
299 
300     return ipmiUserSetUserName(req->userId, strUserName);
301 }
302 
303 /** @brief implementes the get user name command
304  *  @param[in] netfn - specifies netfn.
305  *  @param[in] cmd   - specifies cmd number.
306  *  @param[in] request - pointer to request data.
307  *  @param[in, out] dataLen - specifies request data length, and returns
308  * response data length.
309  *  @param[in] context - ipmi context.
310  *  @returns ipmi completion code.
311  */
312 Cc ipmiGetUserName(ipmi_netfn_t netfn, ipmi_cmd_t cmd, ipmi_request_t request,
313                    ipmi_response_t response, ipmi_data_len_t dataLen,
314                    ipmi_context_t context)
315 {
316     const GetUserNameReq* req = static_cast<GetUserNameReq*>(request);
317     size_t reqLength = *dataLen;
318 
319     *dataLen = 0;
320 
321     if (reqLength != sizeof(*req))
322     {
323         log<level::DEBUG>("Get user name - Invalid Length");
324         return ccReqDataLenInvalid;
325     }
326 
327     std::string userName;
328     if (ipmiUserGetUserName(req->userId, userName) != ccSuccess)
329     { // Invalid User ID
330         log<level::DEBUG>("User Name not found",
331                           entry("USER-ID=%d", (uint8_t)req->userId));
332         return ccParmOutOfRange;
333     }
334     GetUserNameResp* resp = static_cast<GetUserNameResp*>(response);
335     std::fill(reinterpret_cast<uint8_t*>(resp),
336               reinterpret_cast<uint8_t*>(resp) + sizeof(*resp), 0);
337     userName.copy(reinterpret_cast<char*>(resp->userName),
338                   sizeof(resp->userName), 0);
339     *dataLen = sizeof(*resp);
340 
341     return ccSuccess;
342 }
343 
344 /** @brief implementes the set user password command
345  *  @param[in] netfn - specifies netfn.
346  *  @param[in] cmd   - specifies cmd number.
347  *  @param[in] request - pointer to request data.
348  *  @param[in, out] dataLen - specifies request data length, and returns
349  * response data length.
350  *  @param[in] context - ipmi context.
351  *  @returns ipmi completion code.
352  */
353 Cc ipmiSetUserPassword(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
354                        ipmi_request_t request, ipmi_response_t response,
355                        ipmi_data_len_t dataLen, ipmi_context_t context)
356 {
357     const SetUserPasswordReq* req = static_cast<SetUserPasswordReq*>(request);
358     size_t reqLength = *dataLen;
359     // subtract 2 bytes header to know the password length - including NULL
360     uint8_t passwordLength = *dataLen - 2;
361     *dataLen = 0;
362 
363     // verify input length based on operation. Required password size is 20
364     // bytes as  we support only IPMI 2.0, but in order to be compatible with
365     // tools, accept 16 bytes of password size too.
366     if (reqLength < 2 ||
367         // If enable / disable user, reqLength has to be >=2 & <= 22
368         ((req->operation == disableUser || req->operation == enableUser) &&
369          ((reqLength < 2) || (reqLength > sizeof(SetUserPasswordReq)))))
370     {
371         log<level::DEBUG>("Invalid Length");
372         return ccReqDataLenInvalid;
373     }
374     // If set / test password then password length has to be 16 or 20 bytes
375     // based on the password size bit.
376     if (((req->operation == setPassword) || (req->operation == testPassword)) &&
377         (((req->ipmi20 == passwordKeySize20) &&
378           (passwordLength != maxIpmi20PasswordSize)) ||
379          ((req->ipmi20 == passwordKeySize16) &&
380           (passwordLength != maxIpmi15PasswordSize))))
381     {
382         log<level::DEBUG>("Invalid Length");
383         return ccReqDataLenInvalid;
384     }
385 
386     std::string userName;
387     if (ipmiUserGetUserName(req->userId, userName) != ccSuccess)
388     {
389         log<level::DEBUG>("User Name not found",
390                           entry("USER-ID=%d", (uint8_t)req->userId));
391         return ccParmOutOfRange;
392     }
393     if (req->operation == setPassword)
394     {
395         return ipmiUserSetUserPassword(
396             req->userId, reinterpret_cast<const char*>(req->userPassword));
397     }
398     else if (req->operation == enableUser || req->operation == disableUser)
399     {
400         return ipmiUserUpdateEnabledState(req->userId,
401                                           static_cast<bool>(req->operation));
402     }
403     else if (req->operation == testPassword)
404     {
405         auto password = ipmiUserGetPassword(userName);
406         std::string testPassword(
407             reinterpret_cast<const char*>(req->userPassword), 0,
408             passwordLength);
409         // Note: For security reasons password size won't be compared and
410         // wrong password size completion code will not be returned if size
411         // doesn't match as specified in IPMI specification.
412         if (password != testPassword)
413         {
414             log<level::DEBUG>("Test password failed",
415                               entry("USER-ID=%d", (uint8_t)req->userId));
416             // Clear sensitive data
417             OPENSSL_cleanse(&testPassword, testPassword.length());
418             OPENSSL_cleanse(&password, password.length());
419 
420             return static_cast<Cc>(
421                 IPMISetPasswordReturnCodes::ipmiCCPasswdFailMismatch);
422         }
423         // Clear sensitive data
424         OPENSSL_cleanse(&testPassword, testPassword.length());
425         OPENSSL_cleanse(&password, password.length());
426 
427         return ccSuccess;
428     }
429     return ccInvalidFieldRequest;
430 }
431 
432 /** @brief implements the get channel authentication command
433  *  @param ctx - IPMI context pointer (for channel)
434  *  @param extData - get IPMI 2.0 extended data
435  *  @param reserved1 - skip 3 bits
436  *  @param chNum - channel number to get info about
437  *  @param reserved2 - skip 4 bits
438  *  @param privLevel - requested privilege level
439 
440  *  @returns ipmi completion code plus response data
441  *   - channel number
442  *   - rmcpAuthTypes - RMCP auth types (IPMI 1.5)
443  *   - reserved1
444  *   - extDataSupport - true for IPMI 2.0 extensions
445  *   - anonymousLogin - true for anonymous login enabled
446  *   - nullUsers - true for null user names enabled
447  *   - nonNullUsers - true for non-null usernames enabled
448  *   - userAuth - false for user authentication enabled
449  *   - perMessageAuth - false for per message authentication enabled
450  *   - KGStatus - true for Kg required for authentication
451  *   - reserved2
452  *   - rmcp - RMCP (IPMI 1.5) connection support
453  *   - rmcpp - RMCP+ (IPMI 2.0) connection support
454  *   - reserved3
455  *   - oemID - OEM IANA of any OEM auth support
456  *   - oemAuxillary - OEM data for auth
457  */
458 ipmi::RspType<uint8_t,  // channel number
459               uint6_t,  // rmcpAuthTypes
460               bool,     // reserved1
461               bool,     // extDataSupport
462               bool,     // anonymousLogin
463               bool,     // nullUsers
464               bool,     // nonNullUsers
465               bool,     // userAuth
466               bool,     // perMessageAuth
467               bool,     // KGStatus
468               uint2_t,  // reserved2
469               bool,     // rmcp
470               bool,     // rmcpp
471               uint6_t,  // reserved3
472               uint24_t, // oemID
473               uint8_t   // oemAuxillary
474               >
475     ipmiGetChannelAuthenticationCapabilities(ipmi::Context::ptr ctx,
476                                              uint4_t chNum, uint3_t reserved1,
477                                              bool extData, uint4_t privLevel,
478                                              uint4_t reserved2)
479 {
480     uint8_t channel =
481         convertCurrentChannelNum(static_cast<uint8_t>(chNum), ctx->channel);
482 
483     if (reserved1 || reserved2 || !isValidChannel(channel) ||
484         !isValidPrivLimit(static_cast<uint8_t>(privLevel)))
485     {
486         log<level::DEBUG>(
487             "Get channel auth capabilities - Invalid field in request");
488         return ipmi::responseInvalidFieldRequest();
489     }
490 
491     if (getChannelSessionSupport(channel) == EChannelSessSupported::none)
492     {
493         log<level::DEBUG>(
494             "Get channel auth capabilities - No support on channel");
495         return ipmi::response(ccActionNotSupportedForChannel);
496     }
497 
498     constexpr bool extDataSupport = true; // true for IPMI 2.0 extensions
499     constexpr bool reserved3 = false;
500     constexpr uint6_t rmcpAuthTypes = 0; // IPMI 1.5 auth types - not supported
501     constexpr uint2_t reserved4 = 0;
502     constexpr bool KGStatus = false;       // Not supporting now.
503     constexpr bool perMessageAuth = false; // Per message auth - enabled
504     constexpr bool userAuth = false;       // User authentication - enabled
505     constexpr bool nullUsers = false;      // Null user names - not supported
506     constexpr bool anonymousLogin = false; // Anonymous login - not supported
507     constexpr uint6_t reserved5 = 0;
508     constexpr bool rmcpp = true; // IPMI 2.0 - supported
509     constexpr bool rmcp = false; // IPMI 1.5 - not supported
510     constexpr uint24_t oemID = 0;
511     constexpr uint8_t oemAuxillary = 0;
512 
513     bool nonNullUsers = 0;
514     uint8_t maxChUsers = 0, enabledUsers = 0, fixedUsers = 0;
515     ipmi::ipmiUserGetAllCounts(maxChUsers, enabledUsers, fixedUsers);
516     nonNullUsers = enabledUsers > 0;
517 
518     return ipmi::responseSuccess(
519         channel, rmcpAuthTypes, reserved3, extDataSupport, anonymousLogin,
520         nullUsers, nonNullUsers, userAuth, perMessageAuth, KGStatus, reserved4,
521         rmcp, rmcpp, reserved5, oemID, oemAuxillary);
522 }
523 
524 /** @brief implements the set user payload access command.
525  *  @param ctx - IPMI context pointer (for channel)
526  *  @param channel - channel number (4 bits)
527  *  @param reserved1 - skip 4 bits
528  *  @param userId - user id (6 bits)
529  *  @param operation - access ENABLE /DISABLE. (2 bits)
530  *  @param stdPayload0 - IPMI - reserved. (1 bit)
531  *  @param stdPayload1 - SOL.             (1 bit)
532  *  @param stdPayload2 -                  (1 bit)
533  *  @param stdPayload3 -                  (1 bit)
534  *  @param stdPayload4 -                  (1 bit)
535  *  @param stdPayload5 -                  (1 bit)
536  *  @param stdPayload6 -                  (1 bit)
537  *  @param stdPayload7 -                  (1 bit)
538  *  @param stdPayloadEnables2Reserved -   (8 bits)
539  *  @param oemPayload0 -                  (1 bit)
540  *  @param oemPayload1 -                  (1 bit)
541  *  @param oemPayload2 -                  (1 bit)
542  *  @param oemPayload3 -                  (1 bit)
543  *  @param oemPayload4 -                  (1 bit)
544  *  @param oemPayload5 -                  (1 bit)
545  *  @param oemPayload6 -                  (1 bit)
546  *  @param oemPayload7 -                  (1 bit)
547  *  @param oemPayloadEnables2Reserved -   (8 bits)
548  *
549  *  @returns IPMI completion code
550  */
551 ipmi::RspType<> ipmiSetUserPayloadAccess(
552     ipmi::Context::ptr ctx,
553 
554     uint4_t channel, uint4_t reserved,
555 
556     uint6_t userId, uint2_t operation,
557 
558     bool stdPayload0ipmiReserved, bool stdPayload1SOL, bool stdPayload2,
559     bool stdPayload3, bool stdPayload4, bool stdPayload5, bool stdPayload6,
560     bool stdPayload7,
561 
562     uint8_t stdPayloadEnables2Reserved,
563 
564     bool oemPayload0, bool oemPayload1, bool oemPayload2, bool oemPayload3,
565     bool oemPayload4, bool oemPayload5, bool oemPayload6, bool oemPayload7,
566 
567     uint8_t oemPayloadEnables2Reserved)
568 {
569     auto chNum =
570         convertCurrentChannelNum(static_cast<uint8_t>(channel), ctx->channel);
571     // Validate the reserved args. Only SOL payload is supported as on date.
572     if (reserved || stdPayload0ipmiReserved || stdPayload2 || stdPayload3 ||
573         stdPayload4 || stdPayload5 || stdPayload6 || stdPayload7 ||
574         oemPayload0 || oemPayload1 || oemPayload2 || oemPayload3 ||
575         oemPayload4 || oemPayload5 || oemPayload6 || oemPayload7 ||
576         stdPayloadEnables2Reserved || oemPayloadEnables2Reserved ||
577         !isValidChannel(chNum))
578     {
579         return ipmi::responseInvalidFieldRequest();
580     }
581 
582     if ((operation != enableOperation && operation != disableOperation))
583     {
584         return ipmi::responseInvalidFieldRequest();
585     }
586     if (getChannelSessionSupport(chNum) == EChannelSessSupported::none)
587     {
588         return ipmi::response(ccActionNotSupportedForChannel);
589     }
590     if (!ipmiUserIsValidUserId(static_cast<uint8_t>(userId)))
591     {
592         return ipmi::responseParmOutOfRange();
593     }
594 
595     PayloadAccess payloadAccess = {0};
596     payloadAccess.stdPayloadEnables1[1] = stdPayload1SOL;
597 
598     return ipmi::response(ipmiUserSetUserPayloadAccess(
599         chNum, static_cast<uint8_t>(operation), static_cast<uint8_t>(userId),
600         payloadAccess));
601 }
602 
603 /** @brief implements the get user payload access command
604  *  This command returns information about user payload enable settings
605  *  that were set using the 'Set User Payload Access' Command.
606  *
607  *  @param ctx - IPMI context pointer (for channel)
608  *  @param channel - channel number
609  *  @param reserved1 - skip 4 bits
610  *  @param userId - user id
611  *  @param reserved2 - skip 2 bits
612  *
613  *  @returns IPMI completion code plus response data
614  *   - stdPayload0ipmiReserved - IPMI payload (reserved).
615  *   - stdPayload1SOL - SOL payload
616  *   - stdPayload2
617  *   - stdPayload3
618  *   - stdPayload4
619  *   - stdPayload5
620  *   - stdPayload6
621  *   - stdPayload7
622 
623  *   - stdPayloadEnables2Reserved - Reserved.
624 
625  *   - oemPayload0
626  *   - oemPayload1
627  *   - oemPayload2
628  *   - oemPayload3
629  *   - oemPayload4
630  *   - oemPayload5
631  *   - oemPayload6
632  *   - oemPayload7
633 
634  *  - oemPayloadEnables2Reserved - Reserved
635  */
636 ipmi::RspType<bool, // stdPayload0ipmiReserved
637               bool, // stdPayload1SOL
638               bool, // stdPayload2
639               bool, // stdPayload3
640               bool, // stdPayload4
641               bool, // stdPayload5
642               bool, // stdPayload6
643               bool, // stdPayload7
644 
645               uint8_t, // stdPayloadEnables2Reserved
646 
647               bool, // oemPayload0
648               bool, // oemPayload1
649               bool, // oemPayload2
650               bool, // oemPayload3
651               bool, // oemPayload4
652               bool, // oemPayload5
653               bool, // oemPayload6
654               bool, // oemPayload7
655 
656               uint8_t // oemPayloadEnables2Reserved
657               >
658     ipmiGetUserPayloadAccess(ipmi::Context::ptr ctx,
659 
660                              uint4_t channel, uint4_t reserved1,
661 
662                              uint6_t userId, uint2_t reserved2)
663 {
664     uint8_t chNum =
665         convertCurrentChannelNum(static_cast<uint8_t>(channel), ctx->channel);
666 
667     if (reserved1 || reserved2 || !isValidChannel(chNum))
668     {
669         return ipmi::responseInvalidFieldRequest();
670     }
671     if (getChannelSessionSupport(chNum) == EChannelSessSupported::none)
672     {
673         return ipmi::response(ccActionNotSupportedForChannel);
674     }
675     if (!ipmiUserIsValidUserId(static_cast<uint8_t>(userId)))
676     {
677         return ipmi::responseParmOutOfRange();
678     }
679 
680     ipmi::Cc retStatus;
681     PayloadAccess payloadAccess = {};
682     retStatus = ipmiUserGetUserPayloadAccess(
683         chNum, static_cast<uint8_t>(userId), payloadAccess);
684     if (retStatus != ccSuccess)
685     {
686         return ipmi::response(retStatus);
687     }
688     constexpr uint8_t res8bits = 0;
689     return ipmi::responseSuccess(payloadAccess.stdPayloadEnables1.test(0),
690                                  payloadAccess.stdPayloadEnables1.test(1),
691                                  payloadAccess.stdPayloadEnables1.test(2),
692                                  payloadAccess.stdPayloadEnables1.test(3),
693                                  payloadAccess.stdPayloadEnables1.test(4),
694                                  payloadAccess.stdPayloadEnables1.test(5),
695                                  payloadAccess.stdPayloadEnables1.test(6),
696                                  payloadAccess.stdPayloadEnables1.test(7),
697 
698                                  res8bits,
699 
700                                  payloadAccess.oemPayloadEnables1.test(0),
701                                  payloadAccess.oemPayloadEnables1.test(1),
702                                  payloadAccess.oemPayloadEnables1.test(2),
703                                  payloadAccess.oemPayloadEnables1.test(3),
704                                  payloadAccess.oemPayloadEnables1.test(4),
705                                  payloadAccess.oemPayloadEnables1.test(5),
706                                  payloadAccess.oemPayloadEnables1.test(6),
707                                  payloadAccess.oemPayloadEnables1.test(7),
708 
709                                  res8bits);
710 }
711 
712 void registerUserIpmiFunctions() __attribute__((constructor));
713 void registerUserIpmiFunctions()
714 {
715     post_work([]() { ipmiUserInit(); });
716     ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
717                           ipmi::app::cmdSetUserAccessCommand,
718                           ipmi::Privilege::Admin, ipmiSetUserAccess);
719 
720     ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
721                           ipmi::app::cmdGetUserAccessCommand,
722                           ipmi::Privilege::Operator, ipmiGetUserAccess);
723 
724     ipmi_register_callback(NETFUN_APP, IPMI_CMD_GET_USER_NAME, NULL,
725                            ipmiGetUserName, PRIVILEGE_OPERATOR);
726 
727     ipmi_register_callback(NETFUN_APP, IPMI_CMD_SET_USER_NAME, NULL,
728                            ipmiSetUserName, PRIVILEGE_ADMIN);
729 
730     ipmi_register_callback(NETFUN_APP, IPMI_CMD_SET_USER_PASSWORD, NULL,
731                            ipmiSetUserPassword, PRIVILEGE_ADMIN);
732 
733     ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
734                           ipmi::app::cmdGetChannelAuthCapabilities,
735                           ipmi::Privilege::Callback,
736                           ipmiGetChannelAuthenticationCapabilities);
737 
738     ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
739                           ipmi::app::cmdSetUserPayloadAccess,
740                           ipmi::Privilege::Admin, ipmiSetUserPayloadAccess);
741 
742     ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
743                           ipmi::app::cmdGetUserPayloadAccess,
744                           ipmi::Privilege::Operator, ipmiGetUserPayloadAccess);
745 
746     return;
747 }
748 } // namespace ipmi
749