blob: 36c6ebc2c5cf3411f4b4b1677500c6a77ce598d2 [file] [log] [blame]
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +05301/*
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"
Richard Marian Thomaiyar06df8762018-12-08 17:38:25 +053020#include "channel_layer.hpp"
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +053021#include "user_layer.hpp"
22
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +053023#include <security/pam_appl.h>
24
Vernon Mauerye08fbff2019-04-03 09:19:34 -070025#include <ipmid/api.hpp>
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +053026#include <phosphor-logging/log.hpp>
27#include <regex>
28
29namespace ipmi
30{
31
32using namespace phosphor::logging;
33
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +053034static constexpr uint8_t disableUser = 0x00;
35static constexpr uint8_t enableUser = 0x01;
36static constexpr uint8_t setPassword = 0x02;
37static constexpr uint8_t testPassword = 0x03;
Richard Marian Thomaiyar23df06f2019-01-04 16:42:22 +053038static constexpr uint8_t passwordKeySize20 = 1;
39static constexpr uint8_t passwordKeySize16 = 0;
Saravanan Palanisamy77381f12019-05-15 22:33:17 +000040static constexpr uint8_t enableOperation = 0x00;
41static constexpr uint8_t disableOperation = 0x01;
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +053042
Richard Marian Thomaiyar6e1ba9e2018-11-29 06:29:21 +053043/** @struct SetUserNameReq
44 *
45 * Structure for set user name request command (refer spec sec 22.28)
46 */
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +053047struct 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
Richard Marian Thomaiyar6e1ba9e2018-11-29 06:29:21 +053060/** @struct GetUserNameReq
61 *
62 * Structure for get user name request command (refer spec sec 22.29)
63 */
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +053064struct 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
Richard Marian Thomaiyar6e1ba9e2018-11-29 06:29:21 +053076/** @struct GetUserNameResp
77 *
78 * Structure for get user name response command (refer spec sec 22.29)
79 */
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +053080struct GetUserNameResp
81{
82 uint8_t userName[16];
83} __attribute__((packed));
84
Richard Marian Thomaiyar6e1ba9e2018-11-29 06:29:21 +053085/** @struct SetUserPasswordReq
86 *
87 * Structure for set user password request command (refer spec sec 22.30)
88 */
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +053089struct 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
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530108/** @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 */
123ipmi::RspType<> ipmiSetUserAccess(ipmi::Context::ptr ctx, uint4_t channel,
124 uint1_t ipmiEnabled, uint1_t linkAuthEnabled,
125 uint1_t accessCallback, uint1_t bitsUpdate,
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530126
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530127 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);
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000134 if (reserved1 || reserved2 || sessLimit ||
135 !ipmiUserIsValidPrivilege(static_cast<uint8_t>(privilege)))
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530136 {
137 log<level::DEBUG>("Set user access - Invalid field in request");
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530138 return ipmi::responseInvalidFieldRequest();
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530139 }
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000140
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 }
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530153 if (!ipmiUserIsValidUserId(static_cast<uint8_t>(userId)))
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530154 {
155 log<level::DEBUG>("Set user access - Parameter out of range");
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530156 return ipmi::responseParmOutOfRange();
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530157 }
Richard Marian Thomaiyar06df8762018-12-08 17:38:25 +0530158
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530159 PrivAccess privAccess = {0};
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530160 if (bitsUpdate)
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530161 {
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530162 privAccess.ipmiEnabled = static_cast<uint8_t>(ipmiEnabled);
163 privAccess.linkAuthEnabled = static_cast<uint8_t>(linkAuthEnabled);
164 privAccess.accessCallback = static_cast<uint8_t>(accessCallback);
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530165 }
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530166 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)));
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530170}
171
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530172/** @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 */
192ipmi::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)
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530211{
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530212 uint8_t chNum =
Vernon Mauery5ed39592019-05-14 09:16:53 -0700213 convertCurrentChannelNum(static_cast<uint8_t>(channel), ctx->channel);
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000214
215 if (reserved1 || reserved2 || !isValidChannel(chNum))
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530216 {
217 log<level::DEBUG>("Get user access - Invalid field in request");
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530218 return ipmi::responseInvalidFieldRequest();
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530219 }
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000220
221 if (getChannelSessionSupport(chNum) == EChannelSessSupported::none)
222 {
223 log<level::DEBUG>("Get user access - No support on channel");
224 return ipmi::response(ccActionNotSupportedForChannel);
225 }
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530226 if (!ipmiUserIsValidUserId(static_cast<uint8_t>(userId)))
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530227 {
228 log<level::DEBUG>("Get user access - Parameter out of range");
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530229 return ipmi::responseParmOutOfRange();
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530230 }
231
232 uint8_t maxChUsers = 0, enabledUsers = 0, fixedUsers = 0;
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530233 ipmi::Cc retStatus;
Richard Marian Thomaiyarb6771e02019-01-29 14:42:44 +0530234 retStatus = ipmiUserGetAllCounts(maxChUsers, enabledUsers, fixedUsers);
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000235 if (retStatus != ccSuccess)
Richard Marian Thomaiyarb6771e02019-01-29 14:42:44 +0530236 {
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530237 return ipmi::response(retStatus);
Richard Marian Thomaiyarb6771e02019-01-29 14:42:44 +0530238 }
239
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530240 bool enabledState = false;
241 retStatus =
242 ipmiUserCheckEnabled(static_cast<uint8_t>(userId), enabledState);
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000243 if (retStatus != ccSuccess)
Richard Marian Thomaiyarb6771e02019-01-29 14:42:44 +0530244 {
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530245 return ipmi::response(retStatus);
Richard Marian Thomaiyarb6771e02019-01-29 14:42:44 +0530246 }
247
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530248 uint2_t enabledStatus = enabledState ? userIdEnabledViaSetPassword
249 : userIdDisabledViaSetPassword;
250 PrivAccess privAccess{};
251 retStatus = ipmiUserGetPrivilegeAccess(static_cast<uint8_t>(userId), chNum,
252 privAccess);
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000253 if (retStatus != ccSuccess)
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530254 {
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));
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530270}
271
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000272Cc 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)
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530275{
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");
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000283 return ccReqDataLenInvalid;
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530284 }
285 if (req->reserved1)
286 {
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000287 return ccInvalidFieldRequest;
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530288 }
289 if (!ipmiUserIsValidUserId(req->userId))
290 {
291 log<level::DEBUG>("Set user name - Invalid user id");
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000292 return ccParmOutOfRange;
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530293 }
294
295 return ipmiUserSetUserName(req->userId,
296 reinterpret_cast<const char*>(req->userName));
297}
298
299/** @brief implementes the get user name command
300 * @param[in] netfn - specifies netfn.
301 * @param[in] cmd - specifies cmd number.
302 * @param[in] request - pointer to request data.
303 * @param[in, out] dataLen - specifies request data length, and returns
304 * response data length.
305 * @param[in] context - ipmi context.
306 * @returns ipmi completion code.
307 */
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000308Cc ipmiGetUserName(ipmi_netfn_t netfn, ipmi_cmd_t cmd, ipmi_request_t request,
309 ipmi_response_t response, ipmi_data_len_t dataLen,
310 ipmi_context_t context)
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530311{
312 const GetUserNameReq* req = static_cast<GetUserNameReq*>(request);
313 size_t reqLength = *dataLen;
314
315 *dataLen = 0;
316
317 if (reqLength != sizeof(*req))
318 {
319 log<level::DEBUG>("Get user name - Invalid Length");
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000320 return ccReqDataLenInvalid;
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530321 }
322
323 std::string userName;
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000324 if (ipmiUserGetUserName(req->userId, userName) != ccSuccess)
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530325 { // Invalid User ID
326 log<level::DEBUG>("User Name not found",
Ayushi Smriti05ad3412019-10-16 16:10:18 +0530327 entry("USER-ID=%d", (uint8_t)req->userId));
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000328 return ccParmOutOfRange;
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530329 }
330 GetUserNameResp* resp = static_cast<GetUserNameResp*>(response);
331 std::fill(reinterpret_cast<uint8_t*>(resp),
332 reinterpret_cast<uint8_t*>(resp) + sizeof(*resp), 0);
333 userName.copy(reinterpret_cast<char*>(resp->userName),
334 sizeof(resp->userName), 0);
335 *dataLen = sizeof(*resp);
336
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000337 return ccSuccess;
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530338}
339
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530340/** @brief implementes the set user password command
341 * @param[in] netfn - specifies netfn.
342 * @param[in] cmd - specifies cmd number.
343 * @param[in] request - pointer to request data.
344 * @param[in, out] dataLen - specifies request data length, and returns
345 * response data length.
346 * @param[in] context - ipmi context.
347 * @returns ipmi completion code.
348 */
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000349Cc ipmiSetUserPassword(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
350 ipmi_request_t request, ipmi_response_t response,
351 ipmi_data_len_t dataLen, ipmi_context_t context)
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530352{
353 const SetUserPasswordReq* req = static_cast<SetUserPasswordReq*>(request);
354 size_t reqLength = *dataLen;
355 // subtract 2 bytes header to know the password length - including NULL
356 uint8_t passwordLength = *dataLen - 2;
357 *dataLen = 0;
358
359 // verify input length based on operation. Required password size is 20
360 // bytes as we support only IPMI 2.0, but in order to be compatible with
361 // tools, accept 16 bytes of password size too.
362 if (reqLength < 2 ||
363 // If enable / disable user, reqLength has to be >=2 & <= 22
364 ((req->operation == disableUser || req->operation == enableUser) &&
365 ((reqLength < 2) || (reqLength > sizeof(SetUserPasswordReq)))))
366 {
367 log<level::DEBUG>("Invalid Length");
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000368 return ccReqDataLenInvalid;
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530369 }
370 // If set / test password then password length has to be 16 or 20 bytes
Richard Marian Thomaiyar23df06f2019-01-04 16:42:22 +0530371 // based on the password size bit.
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530372 if (((req->operation == setPassword) || (req->operation == testPassword)) &&
Richard Marian Thomaiyar23df06f2019-01-04 16:42:22 +0530373 (((req->ipmi20 == passwordKeySize20) &&
374 (passwordLength != maxIpmi20PasswordSize)) ||
375 ((req->ipmi20 == passwordKeySize16) &&
376 (passwordLength != maxIpmi15PasswordSize))))
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530377 {
378 log<level::DEBUG>("Invalid Length");
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000379 return ccReqDataLenInvalid;
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530380 }
381
382 std::string userName;
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000383 if (ipmiUserGetUserName(req->userId, userName) != ccSuccess)
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530384 {
385 log<level::DEBUG>("User Name not found",
Ayushi Smriti05ad3412019-10-16 16:10:18 +0530386 entry("USER-ID=%d", (uint8_t)req->userId));
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000387 return ccParmOutOfRange;
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530388 }
389 if (req->operation == setPassword)
390 {
Suryakanth Sekar90b00c72019-01-16 10:37:57 +0530391 return ipmiUserSetUserPassword(
392 req->userId, reinterpret_cast<const char*>(req->userPassword));
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530393 }
Richard Marian Thomaiyar282e79b2018-11-13 19:00:58 +0530394 else if (req->operation == enableUser || req->operation == disableUser)
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530395 {
Richard Marian Thomaiyar282e79b2018-11-13 19:00:58 +0530396 return ipmiUserUpdateEnabledState(req->userId,
397 static_cast<bool>(req->operation));
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530398 }
Richard Marian Thomaiyar282e79b2018-11-13 19:00:58 +0530399 else if (req->operation == testPassword)
400 {
401 auto password = ipmiUserGetPassword(userName);
402 std::string testPassword(
403 reinterpret_cast<const char*>(req->userPassword), 0,
404 passwordLength);
405 // Note: For security reasons password size won't be compared and
406 // wrong password size completion code will not be returned if size
407 // doesn't match as specified in IPMI specification.
408 if (password != testPassword)
409 {
410 log<level::DEBUG>("Test password failed",
Ayushi Smriti05ad3412019-10-16 16:10:18 +0530411 entry("USER-ID=%d", (uint8_t)req->userId));
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000412 return static_cast<Cc>(
Richard Marian Thomaiyar282e79b2018-11-13 19:00:58 +0530413 IPMISetPasswordReturnCodes::ipmiCCPasswdFailMismatch);
414 }
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000415 return ccSuccess;
Richard Marian Thomaiyar282e79b2018-11-13 19:00:58 +0530416 }
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000417 return ccInvalidFieldRequest;
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530418}
419
smritic46f6cd2019-03-20 14:09:41 +0530420/** @brief implements the get channel authentication command
421 * @param ctx - IPMI context pointer (for channel)
422 * @param extData - get IPMI 2.0 extended data
423 * @param reserved1 - skip 3 bits
424 * @param chNum - channel number to get info about
425 * @param reserved2 - skip 4 bits
426 * @param privLevel - requested privilege level
427
428 * @returns ipmi completion code plus response data
429 * - channel number
430 * - rmcpAuthTypes - RMCP auth types (IPMI 1.5)
431 * - reserved1
432 * - extDataSupport - true for IPMI 2.0 extensions
433 * - anonymousLogin - true for anonymous login enabled
434 * - nullUsers - true for null user names enabled
435 * - nonNullUsers - true for non-null usernames enabled
436 * - userAuth - false for user authentication enabled
437 * - perMessageAuth - false for per message authentication enabled
438 * - KGStatus - true for Kg required for authentication
439 * - reserved2
440 * - rmcp - RMCP (IPMI 1.5) connection support
441 * - rmcpp - RMCP+ (IPMI 2.0) connection support
442 * - reserved3
443 * - oemID - OEM IANA of any OEM auth support
444 * - oemAuxillary - OEM data for auth
445 */
446ipmi::RspType<uint8_t, // channel number
447 uint6_t, // rmcpAuthTypes
448 bool, // reserved1
449 bool, // extDataSupport
450 bool, // anonymousLogin
451 bool, // nullUsers
452 bool, // nonNullUsers
453 bool, // userAuth
454 bool, // perMessageAuth
455 bool, // KGStatus
456 uint2_t, // reserved2
457 bool, // rmcp
458 bool, // rmcpp
459 uint6_t, // reserved3
460 uint24_t, // oemID
461 uint8_t // oemAuxillary
462 >
463 ipmiGetChannelAuthenticationCapabilities(ipmi::Context::ptr ctx,
464 uint4_t chNum, uint3_t reserved1,
465 bool extData, uint4_t privLevel,
466 uint4_t reserved2)
467{
smritic46f6cd2019-03-20 14:09:41 +0530468 uint8_t channel =
Vernon Mauery5ed39592019-05-14 09:16:53 -0700469 convertCurrentChannelNum(static_cast<uint8_t>(chNum), ctx->channel);
smritic46f6cd2019-03-20 14:09:41 +0530470
471 if (reserved1 || reserved2 || !isValidChannel(channel) ||
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000472 !isValidPrivLimit(static_cast<uint8_t>(privLevel)))
smritic46f6cd2019-03-20 14:09:41 +0530473 {
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000474 log<level::DEBUG>(
475 "Get channel auth capabilities - Invalid field in request");
476 return ipmi::responseInvalidFieldRequest();
477 }
478
479 if (getChannelSessionSupport(channel) == EChannelSessSupported::none)
480 {
481 log<level::DEBUG>(
482 "Get channel auth capabilities - No support on channel");
483 return ipmi::response(ccActionNotSupportedForChannel);
smritic46f6cd2019-03-20 14:09:41 +0530484 }
485
486 constexpr bool extDataSupport = true; // true for IPMI 2.0 extensions
487 constexpr bool reserved3 = false;
488 constexpr uint6_t rmcpAuthTypes = 0; // IPMI 1.5 auth types - not supported
489 constexpr uint2_t reserved4 = 0;
490 constexpr bool KGStatus = false; // Not supporting now.
491 constexpr bool perMessageAuth = false; // Per message auth - enabled
492 constexpr bool userAuth = false; // User authentication - enabled
493 constexpr bool nullUsers = false; // Null user names - not supported
494 constexpr bool anonymousLogin = false; // Anonymous login - not supported
495 constexpr uint6_t reserved5 = 0;
496 constexpr bool rmcpp = true; // IPMI 2.0 - supported
497 constexpr bool rmcp = false; // IPMI 1.5 - not supported
498 constexpr uint24_t oemID = 0;
499 constexpr uint8_t oemAuxillary = 0;
500
501 bool nonNullUsers = 0;
502 uint8_t maxChUsers = 0, enabledUsers = 0, fixedUsers = 0;
503 ipmi::ipmiUserGetAllCounts(maxChUsers, enabledUsers, fixedUsers);
504 nonNullUsers = enabledUsers > 0;
505
506 return ipmi::responseSuccess(
507 channel, rmcpAuthTypes, reserved3, extDataSupport, anonymousLogin,
508 nullUsers, nonNullUsers, userAuth, perMessageAuth, KGStatus, reserved4,
509 rmcp, rmcpp, reserved5, oemID, oemAuxillary);
510}
511
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000512/** @brief implements the set user payload access command.
513 * @param ctx - IPMI context pointer (for channel)
514 * @param channel - channel number (4 bits)
515 * @param reserved1 - skip 4 bits
516 * @param userId - user id (6 bits)
517 * @param operation - access ENABLE /DISABLE. (2 bits)
518 * @param stdPayload0 - IPMI - reserved. (1 bit)
519 * @param stdPayload1 - SOL. (1 bit)
520 * @param stdPayload2 - (1 bit)
521 * @param stdPayload3 - (1 bit)
522 * @param stdPayload4 - (1 bit)
523 * @param stdPayload5 - (1 bit)
524 * @param stdPayload6 - (1 bit)
525 * @param stdPayload7 - (1 bit)
526 * @param stdPayloadEnables2Reserved - (8 bits)
527 * @param oemPayload0 - (1 bit)
528 * @param oemPayload1 - (1 bit)
529 * @param oemPayload2 - (1 bit)
530 * @param oemPayload3 - (1 bit)
531 * @param oemPayload4 - (1 bit)
532 * @param oemPayload5 - (1 bit)
533 * @param oemPayload6 - (1 bit)
534 * @param oemPayload7 - (1 bit)
535 * @param oemPayloadEnables2Reserved - (8 bits)
536 *
537 * @returns IPMI completion code
538 */
539ipmi::RspType<> ipmiSetUserPayloadAccess(
540 ipmi::Context::ptr ctx,
541
542 uint4_t channel, uint4_t reserved,
543
544 uint6_t userId, uint2_t operation,
545
546 bool stdPayload0ipmiReserved, bool stdPayload1SOL, bool stdPayload2,
547 bool stdPayload3, bool stdPayload4, bool stdPayload5, bool stdPayload6,
548 bool stdPayload7,
549
550 uint8_t stdPayloadEnables2Reserved,
551
552 bool oemPayload0, bool oemPayload1, bool oemPayload2, bool oemPayload3,
553 bool oemPayload4, bool oemPayload5, bool oemPayload6, bool oemPayload7,
554
555 uint8_t oemPayloadEnables2Reserved)
556{
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000557 auto chNum =
558 convertCurrentChannelNum(static_cast<uint8_t>(channel), ctx->channel);
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000559 // Validate the reserved args. Only SOL payload is supported as on date.
560 if (reserved || stdPayload0ipmiReserved || stdPayload2 || stdPayload3 ||
561 stdPayload4 || stdPayload5 || stdPayload6 || stdPayload7 ||
562 oemPayload0 || oemPayload1 || oemPayload2 || oemPayload3 ||
563 oemPayload4 || oemPayload5 || oemPayload6 || oemPayload7 ||
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000564 stdPayloadEnables2Reserved || oemPayloadEnables2Reserved ||
565 !isValidChannel(chNum))
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000566 {
567 return ipmi::responseInvalidFieldRequest();
568 }
569
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000570 if ((operation != enableOperation && operation != disableOperation))
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000571 {
572 return ipmi::responseInvalidFieldRequest();
573 }
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000574 if (getChannelSessionSupport(chNum) == EChannelSessSupported::none)
575 {
576 return ipmi::response(ccActionNotSupportedForChannel);
577 }
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000578 if (!ipmiUserIsValidUserId(static_cast<uint8_t>(userId)))
579 {
580 return ipmi::responseParmOutOfRange();
581 }
582
583 PayloadAccess payloadAccess = {0};
584 payloadAccess.stdPayloadEnables1[1] = stdPayload1SOL;
585
586 return ipmi::response(ipmiUserSetUserPayloadAccess(
587 chNum, static_cast<uint8_t>(operation), static_cast<uint8_t>(userId),
588 payloadAccess));
589}
590
591/** @brief implements the get user payload access command
592 * This command returns information about user payload enable settings
593 * that were set using the 'Set User Payload Access' Command.
594 *
595 * @param ctx - IPMI context pointer (for channel)
596 * @param channel - channel number
597 * @param reserved1 - skip 4 bits
598 * @param userId - user id
599 * @param reserved2 - skip 2 bits
600 *
601 * @returns IPMI completion code plus response data
602 * - stdPayload0ipmiReserved - IPMI payload (reserved).
603 * - stdPayload1SOL - SOL payload
604 * - stdPayload2
605 * - stdPayload3
606 * - stdPayload4
607 * - stdPayload5
608 * - stdPayload6
609 * - stdPayload7
610
611 * - stdPayloadEnables2Reserved - Reserved.
612
613 * - oemPayload0
614 * - oemPayload1
615 * - oemPayload2
616 * - oemPayload3
617 * - oemPayload4
618 * - oemPayload5
619 * - oemPayload6
620 * - oemPayload7
621
622 * - oemPayloadEnables2Reserved - Reserved
623 */
624ipmi::RspType<bool, // stdPayload0ipmiReserved
625 bool, // stdPayload1SOL
626 bool, // stdPayload2
627 bool, // stdPayload3
628 bool, // stdPayload4
629 bool, // stdPayload5
630 bool, // stdPayload6
631 bool, // stdPayload7
632
633 uint8_t, // stdPayloadEnables2Reserved
634
635 bool, // oemPayload0
636 bool, // oemPayload1
637 bool, // oemPayload2
638 bool, // oemPayload3
639 bool, // oemPayload4
640 bool, // oemPayload5
641 bool, // oemPayload6
642 bool, // oemPayload7
643
644 uint8_t // oemPayloadEnables2Reserved
645 >
646 ipmiGetUserPayloadAccess(ipmi::Context::ptr ctx,
647
648 uint4_t channel, uint4_t reserved1,
649
650 uint6_t userId, uint2_t reserved2)
651{
652 uint8_t chNum =
653 convertCurrentChannelNum(static_cast<uint8_t>(channel), ctx->channel);
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000654
655 if (reserved1 || reserved2 || !isValidChannel(chNum))
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000656 {
657 return ipmi::responseInvalidFieldRequest();
658 }
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000659 if (getChannelSessionSupport(chNum) == EChannelSessSupported::none)
660 {
661 return ipmi::response(ccActionNotSupportedForChannel);
662 }
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000663 if (!ipmiUserIsValidUserId(static_cast<uint8_t>(userId)))
664 {
665 return ipmi::responseParmOutOfRange();
666 }
667
668 ipmi::Cc retStatus;
669 PayloadAccess payloadAccess = {};
670 retStatus = ipmiUserGetUserPayloadAccess(
671 chNum, static_cast<uint8_t>(userId), payloadAccess);
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000672 if (retStatus != ccSuccess)
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000673 {
674 return ipmi::response(retStatus);
675 }
676 constexpr uint8_t res8bits = 0;
677 return ipmi::responseSuccess(payloadAccess.stdPayloadEnables1.test(0),
678 payloadAccess.stdPayloadEnables1.test(1),
679 payloadAccess.stdPayloadEnables1.test(2),
680 payloadAccess.stdPayloadEnables1.test(3),
681 payloadAccess.stdPayloadEnables1.test(4),
682 payloadAccess.stdPayloadEnables1.test(5),
683 payloadAccess.stdPayloadEnables1.test(6),
684 payloadAccess.stdPayloadEnables1.test(7),
685
686 res8bits,
687
688 payloadAccess.oemPayloadEnables1.test(0),
689 payloadAccess.oemPayloadEnables1.test(1),
690 payloadAccess.oemPayloadEnables1.test(2),
691 payloadAccess.oemPayloadEnables1.test(3),
692 payloadAccess.oemPayloadEnables1.test(4),
693 payloadAccess.oemPayloadEnables1.test(5),
694 payloadAccess.oemPayloadEnables1.test(6),
695 payloadAccess.oemPayloadEnables1.test(7),
696
697 res8bits);
698}
699
William A. Kennington III343d0612018-12-10 15:56:24 -0800700void registerUserIpmiFunctions() __attribute__((constructor));
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530701void registerUserIpmiFunctions()
702{
Richard Marian Thomaiyar0be80bd2020-01-10 12:20:16 +0530703 post_work([]() { ipmiUserInit(); });
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530704 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
705 ipmi::app::cmdSetUserAccessCommand,
706 ipmi::Privilege::Admin, ipmiSetUserAccess);
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530707
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530708 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
709 ipmi::app::cmdGetUserAccessCommand,
710 ipmi::Privilege::Operator, ipmiGetUserAccess);
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530711
712 ipmi_register_callback(NETFUN_APP, IPMI_CMD_GET_USER_NAME, NULL,
713 ipmiGetUserName, PRIVILEGE_OPERATOR);
714
715 ipmi_register_callback(NETFUN_APP, IPMI_CMD_SET_USER_NAME, NULL,
716 ipmiSetUserName, PRIVILEGE_ADMIN);
717
718 ipmi_register_callback(NETFUN_APP, IPMI_CMD_SET_USER_PASSWORD, NULL,
719 ipmiSetUserPassword, PRIVILEGE_ADMIN);
720
smritic46f6cd2019-03-20 14:09:41 +0530721 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
722 ipmi::app::cmdGetChannelAuthCapabilities,
723 ipmi::Privilege::Callback,
724 ipmiGetChannelAuthenticationCapabilities);
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000725
726 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
727 ipmi::app::cmdSetUserPayloadAccess,
728 ipmi::Privilege::Admin, ipmiSetUserPayloadAccess);
729
730 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
731 ipmi::app::cmdGetUserPayloadAccess,
732 ipmi::Privilege::Operator, ipmiGetUserPayloadAccess);
733
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530734 return;
735}
736} // namespace ipmi