blob: 52a9aef364c3a146fb4f1e280dee2705a7f5ca03 [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
Saravanan Palanisamy77381f12019-05-15 22:33:17 +000034static constexpr uint8_t enableOperation = 0x00;
35static constexpr uint8_t disableOperation = 0x01;
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +053036
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +053037/** @brief implements the set user access command
38 * @param ctx - IPMI context pointer (for channel)
39 * @param channel - channel number
40 * @param ipmiEnabled - indicates ipmi messaging state
41 * @param linkAuthEnabled - indicates link authentication state
42 * @param accessCallback - indicates callback state
43 * @param bitsUpdate - indicates update request
44 * @param userId - user id
45 * @param reserved1 - skip 2 bits
46 * @param privilege - user privilege
47 * @param reserved2 - skip 4 bits
48 * @param sessionLimit - optional - unused for now
49 *
50 * @returns ipmi completion code
51 */
52ipmi::RspType<> ipmiSetUserAccess(ipmi::Context::ptr ctx, uint4_t channel,
53 uint1_t ipmiEnabled, uint1_t linkAuthEnabled,
54 uint1_t accessCallback, uint1_t bitsUpdate,
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +053055
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +053056 uint6_t userId, uint2_t reserved1,
57
58 uint4_t privilege, uint4_t reserved2,
59
60 std::optional<uint8_t> sessionLimit)
61{
62 uint8_t sessLimit = sessionLimit.value_or(0);
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +000063 if (reserved1 || reserved2 || sessLimit ||
64 !ipmiUserIsValidPrivilege(static_cast<uint8_t>(privilege)))
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +053065 {
66 log<level::DEBUG>("Set user access - Invalid field in request");
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +053067 return ipmi::responseInvalidFieldRequest();
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +053068 }
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +000069
70 uint8_t chNum =
71 convertCurrentChannelNum(static_cast<uint8_t>(channel), ctx->channel);
72 if (!isValidChannel(chNum))
73 {
74 log<level::DEBUG>("Set user access - Invalid channel request");
75 return ipmi::response(invalidChannel);
76 }
77 if (getChannelSessionSupport(chNum) == EChannelSessSupported::none)
78 {
79 log<level::DEBUG>("Set user access - No support on channel");
80 return ipmi::response(ccActionNotSupportedForChannel);
81 }
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +053082 if (!ipmiUserIsValidUserId(static_cast<uint8_t>(userId)))
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +053083 {
84 log<level::DEBUG>("Set user access - Parameter out of range");
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +053085 return ipmi::responseParmOutOfRange();
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +053086 }
Richard Marian Thomaiyar06df8762018-12-08 17:38:25 +053087
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +053088 PrivAccess privAccess = {0};
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +053089 if (bitsUpdate)
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +053090 {
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +053091 privAccess.ipmiEnabled = static_cast<uint8_t>(ipmiEnabled);
92 privAccess.linkAuthEnabled = static_cast<uint8_t>(linkAuthEnabled);
93 privAccess.accessCallback = static_cast<uint8_t>(accessCallback);
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +053094 }
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +053095 privAccess.privilege = static_cast<uint8_t>(privilege);
96 return ipmi::response(
97 ipmiUserSetPrivilegeAccess(static_cast<uint8_t>(userId), chNum,
98 privAccess, static_cast<bool>(bitsUpdate)));
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +053099}
100
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530101/** @brief implements the set user access command
102 * @param ctx - IPMI context pointer (for channel)
103 * @param channel - channel number
104 * @param reserved1 - skip 4 bits
105 * @param userId - user id
106 * @param reserved2 - skip 2 bits
107 *
108 * @returns ipmi completion code plus response data
109 * - maxChUsers - max channel users
110 * - reserved1 - skip 2 bits
111 * - enabledUsers - enabled users count
112 * - enabledStatus - enabled status
113 * - fixedUsers - fixed users count
114 * - reserved2 - skip 2 bits
115 * - privilege - user privilege
116 * - ipmiEnabled - ipmi messaging state
117 * - linkAuthEnabled - link authenticatin state
118 * - accessCallback - callback state
119 * - reserved - skip 1 bit
120 */
121ipmi::RspType<uint6_t, // max channel users
122 uint2_t, // reserved1
123
124 uint6_t, // enabled users count
125 uint2_t, // enabled status
126
127 uint6_t, // fixed users count
128 uint2_t, // reserved2
129
130 uint4_t, // privilege
131 uint1_t, // ipmi messaging state
132 uint1_t, // link authentication state
133 uint1_t, // access callback state
134 uint1_t // reserved3
135 >
136 ipmiGetUserAccess(ipmi::Context::ptr ctx, uint4_t channel,
137 uint4_t reserved1,
138
139 uint6_t userId, uint2_t reserved2)
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530140{
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530141 uint8_t chNum =
Vernon Mauery5ed39592019-05-14 09:16:53 -0700142 convertCurrentChannelNum(static_cast<uint8_t>(channel), ctx->channel);
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000143
144 if (reserved1 || reserved2 || !isValidChannel(chNum))
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530145 {
146 log<level::DEBUG>("Get user access - Invalid field in request");
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530147 return ipmi::responseInvalidFieldRequest();
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530148 }
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000149
150 if (getChannelSessionSupport(chNum) == EChannelSessSupported::none)
151 {
152 log<level::DEBUG>("Get user access - No support on channel");
153 return ipmi::response(ccActionNotSupportedForChannel);
154 }
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530155 if (!ipmiUserIsValidUserId(static_cast<uint8_t>(userId)))
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530156 {
157 log<level::DEBUG>("Get user access - Parameter out of range");
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530158 return ipmi::responseParmOutOfRange();
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530159 }
160
161 uint8_t maxChUsers = 0, enabledUsers = 0, fixedUsers = 0;
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530162 ipmi::Cc retStatus;
Richard Marian Thomaiyarb6771e02019-01-29 14:42:44 +0530163 retStatus = ipmiUserGetAllCounts(maxChUsers, enabledUsers, fixedUsers);
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000164 if (retStatus != ccSuccess)
Richard Marian Thomaiyarb6771e02019-01-29 14:42:44 +0530165 {
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530166 return ipmi::response(retStatus);
Richard Marian Thomaiyarb6771e02019-01-29 14:42:44 +0530167 }
168
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530169 bool enabledState = false;
170 retStatus =
171 ipmiUserCheckEnabled(static_cast<uint8_t>(userId), enabledState);
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000172 if (retStatus != ccSuccess)
Richard Marian Thomaiyarb6771e02019-01-29 14:42:44 +0530173 {
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530174 return ipmi::response(retStatus);
Richard Marian Thomaiyarb6771e02019-01-29 14:42:44 +0530175 }
176
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530177 uint2_t enabledStatus = enabledState ? userIdEnabledViaSetPassword
178 : userIdDisabledViaSetPassword;
179 PrivAccess privAccess{};
180 retStatus = ipmiUserGetPrivilegeAccess(static_cast<uint8_t>(userId), chNum,
181 privAccess);
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000182 if (retStatus != ccSuccess)
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530183 {
184 return ipmi::response(retStatus);
185 }
186 constexpr uint2_t res2Bits = 0;
187 return ipmi::responseSuccess(
188 static_cast<uint6_t>(maxChUsers), res2Bits,
189
190 static_cast<uint6_t>(enabledUsers), enabledStatus,
191
192 static_cast<uint6_t>(fixedUsers), res2Bits,
193
194 static_cast<uint4_t>(privAccess.privilege),
195 static_cast<uint1_t>(privAccess.ipmiEnabled),
196 static_cast<uint1_t>(privAccess.linkAuthEnabled),
197 static_cast<uint1_t>(privAccess.accessCallback),
198 static_cast<uint1_t>(privAccess.reserved));
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530199}
200
Vernon Maueryac30b392021-08-05 11:08:23 -0700201/** @brief implementes the get user name command
202 * @param[in] ctx - ipmi command context
203 * @param[in] userId - 6-bit user ID
204 * @param[in] reserved - 2-bits reserved
205 * @param[in] name - 16-byte array for username
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530206
Vernon Maueryac30b392021-08-05 11:08:23 -0700207 * @returns ipmi response
208 */
209ipmi::RspType<>
210 ipmiSetUserName(ipmi::Context::ptr ctx, uint6_t id, uint2_t reserved,
211 const std::array<uint8_t, ipmi::ipmiMaxUserName>& name)
212{
213 if (reserved)
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530214 {
Vernon Maueryac30b392021-08-05 11:08:23 -0700215 return ipmi::responseInvalidFieldRequest();
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530216 }
Vernon Maueryac30b392021-08-05 11:08:23 -0700217 uint8_t userId = static_cast<uint8_t>(id);
218 if (!ipmiUserIsValidUserId(userId))
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530219 {
220 log<level::DEBUG>("Set user name - Invalid user id");
Vernon Maueryac30b392021-08-05 11:08:23 -0700221 return ipmi::responseParmOutOfRange();
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530222 }
223
Vernon Maueryac30b392021-08-05 11:08:23 -0700224 size_t nameLen = strnlen(reinterpret_cast<const char*>(name.data()),
225 ipmi::ipmiMaxUserName);
226 const std::string strUserName(reinterpret_cast<const char*>(name.data()),
jayaprakash Mutyalacdcdf2b2020-03-28 00:12:05 +0000227 nameLen);
228
Vernon Maueryac30b392021-08-05 11:08:23 -0700229 ipmi::Cc res = ipmiUserSetUserName(userId, strUserName);
230 return ipmi::response(res);
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530231}
232
233/** @brief implementes the get user name command
Vernon Mauery3c89de12021-08-05 11:08:23 -0700234 * @param[in] ctx - ipmi command context
235 * @param[in] userId - 6-bit user ID
236 * @param[in] reserved - 2-bits reserved
237
238 * @returns ipmi response with 16-byte username
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530239 */
Vernon Mauery3c89de12021-08-05 11:08:23 -0700240ipmi::RspType<std::array<uint8_t, ipmi::ipmiMaxUserName>> // user name
241 ipmiGetUserName(ipmi::Context::ptr ctx, uint6_t id, uint2_t reserved)
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530242{
Vernon Mauery3c89de12021-08-05 11:08:23 -0700243 if (reserved)
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530244 {
Vernon Mauery3c89de12021-08-05 11:08:23 -0700245 return ipmi::responseInvalidFieldRequest();
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530246 }
247
Vernon Mauery3c89de12021-08-05 11:08:23 -0700248 uint8_t userId = static_cast<uint8_t>(id);
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530249 std::string userName;
Vernon Mauery3c89de12021-08-05 11:08:23 -0700250 if (ipmiUserGetUserName(userId, userName) != ccSuccess)
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530251 { // Invalid User ID
Vernon Mauery3c89de12021-08-05 11:08:23 -0700252 log<level::DEBUG>("User Name not found", entry("USER-ID=%u", userId));
253 return ipmi::responseParmOutOfRange();
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530254 }
Vernon Mauery3c89de12021-08-05 11:08:23 -0700255 // copy the std::string into a fixed array
256 if (userName.size() > ipmi::ipmiMaxUserName)
257 {
258 return ipmi::responseUnspecifiedError();
259 }
260 std::array<uint8_t, ipmi::ipmiMaxUserName> userNameFixed;
261 std::fill(userNameFixed.begin(), userNameFixed.end(), 0);
262 std::copy(userName.begin(), userName.end(), userNameFixed.begin());
263 return ipmi::responseSuccess(std::move(userNameFixed));
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530264}
265
Vernon Mauery7a3296d2021-08-05 11:08:23 -0700266/** @brief implementes the get user name command
267 * @param[in] ctx - ipmi command context
268 * @param[in] userId - 6-bit user ID
269 * @param[in] reserved - 2-bits reserved
270
271 * @returns ipmi response with 16-byte username
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530272 */
Vernon Mauery7a3296d2021-08-05 11:08:23 -0700273ipmi::RspType<> // user name
274 ipmiSetUserPassword(ipmi::Context::ptr ctx, uint6_t id, bool reserved1,
275 bool pwLen20, uint2_t operation, uint6_t reserved2,
276 SecureBuffer& userPassword)
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530277{
Vernon Mauery7a3296d2021-08-05 11:08:23 -0700278 if (reserved1 || reserved2)
Snehalatha Venkatesh37b1d1a2021-06-28 10:13:37 +0000279 {
280 log<level::DEBUG>("Invalid data field in request");
Vernon Mauery7a3296d2021-08-05 11:08:23 -0700281 return ipmi::responseInvalidFieldRequest();
Snehalatha Venkatesh37b1d1a2021-06-28 10:13:37 +0000282 }
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530283
Vernon Mauery7a3296d2021-08-05 11:08:23 -0700284 if (pwLen20 && userPassword.size() != maxIpmi20PasswordSize)
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530285 {
286 log<level::DEBUG>("Invalid Length");
Vernon Mauery7a3296d2021-08-05 11:08:23 -0700287 return ipmi::responseReqDataLenInvalid();
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530288 }
Vernon Mauery7a3296d2021-08-05 11:08:23 -0700289 else if (!pwLen20 && userPassword.size() != maxIpmi15PasswordSize)
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530290 {
291 log<level::DEBUG>("Invalid Length");
Vernon Mauery7a3296d2021-08-05 11:08:23 -0700292 return ipmi::responseReqDataLenInvalid();
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530293 }
Vernon Mauery7a3296d2021-08-05 11:08:23 -0700294 size_t passwordLength = userPassword.size();
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530295
Vernon Mauery7a3296d2021-08-05 11:08:23 -0700296 uint8_t userId = static_cast<uint8_t>(id);
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530297 std::string userName;
Vernon Mauery7a3296d2021-08-05 11:08:23 -0700298 if (ipmiUserGetUserName(userId, userName) != ccSuccess)
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530299 {
Vernon Mauery7a3296d2021-08-05 11:08:23 -0700300 log<level::DEBUG>("User Name not found", entry("USER-ID=%d", userId));
301 return ipmi::responseParmOutOfRange();
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530302 }
Vernon Mauery7a3296d2021-08-05 11:08:23 -0700303
304 static constexpr uint2_t opDisableUser = 0x00;
305 static constexpr uint2_t opEnableUser = 0x01;
306 static constexpr uint2_t opSetPassword = 0x02;
307 static constexpr uint2_t opTestPassword = 0x03;
308 if (operation == opSetPassword)
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530309 {
Vernon Mauery7a3296d2021-08-05 11:08:23 -0700310 // turn the non-nul terminated SecureBuffer into a SecureString
311 SecureString password(
312 reinterpret_cast<const char*>(userPassword.data()), passwordLength);
313 ipmi::Cc res = ipmiUserSetUserPassword(userId, password.data());
314 return ipmi::response(res);
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530315 }
Vernon Mauery7a3296d2021-08-05 11:08:23 -0700316 else if (operation == opEnableUser || operation == opDisableUser)
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530317 {
Vernon Mauery7a3296d2021-08-05 11:08:23 -0700318 ipmi::Cc res =
319 ipmiUserUpdateEnabledState(userId, static_cast<bool>(operation));
320 return ipmi::response(res);
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530321 }
Vernon Mauery7a3296d2021-08-05 11:08:23 -0700322 else if (operation == opTestPassword)
Richard Marian Thomaiyar282e79b2018-11-13 19:00:58 +0530323 {
Vernon Mauery1e22a0f2021-07-30 13:36:54 -0700324 SecureString password = ipmiUserGetPassword(userName);
Vernon Mauery7a3296d2021-08-05 11:08:23 -0700325 // extend with zeros, if needed
326 if (password.size() < passwordLength)
327 {
328 password.resize(passwordLength, '\0');
329 }
Vernon Mauery1e22a0f2021-07-30 13:36:54 -0700330 SecureString testPassword(
Vernon Mauery7a3296d2021-08-05 11:08:23 -0700331 reinterpret_cast<const char*>(userPassword.data()), passwordLength);
Vernon Mauery1e22a0f2021-07-30 13:36:54 -0700332 // constant time string compare: always compare exactly as many bytes
333 // as the length of the input, resizing the actual password to match,
334 // maintaining a knowledge if the sizes differed originally
335 static const std::array<char, maxIpmi20PasswordSize> empty = {'\0'};
336 size_t cmpLen = testPassword.size();
337 bool pwLenDiffers = password.size() != cmpLen;
338 const char* cmpPassword = nullptr;
339 if (pwLenDiffers)
340 {
341 cmpPassword = empty.data();
342 }
343 else
344 {
345 cmpPassword = password.data();
346 }
347 bool pwBad = CRYPTO_memcmp(cmpPassword, testPassword.data(), cmpLen);
348 pwBad |= pwLenDiffers;
349 if (pwBad)
Richard Marian Thomaiyar282e79b2018-11-13 19:00:58 +0530350 {
351 log<level::DEBUG>("Test password failed",
Vernon Mauery7a3296d2021-08-05 11:08:23 -0700352 entry("USER-ID=%d", userId));
353 static constexpr ipmi::Cc ipmiCCPasswdFailMismatch = 0x80;
354 return ipmi::response(ipmiCCPasswdFailMismatch);
Richard Marian Thomaiyar282e79b2018-11-13 19:00:58 +0530355 }
Vernon Mauery7a3296d2021-08-05 11:08:23 -0700356 return ipmi::responseSuccess();
Richard Marian Thomaiyar282e79b2018-11-13 19:00:58 +0530357 }
Vernon Mauery7a3296d2021-08-05 11:08:23 -0700358 return ipmi::responseInvalidFieldRequest();
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530359}
360
smritic46f6cd2019-03-20 14:09:41 +0530361/** @brief implements the get channel authentication command
362 * @param ctx - IPMI context pointer (for channel)
363 * @param extData - get IPMI 2.0 extended data
364 * @param reserved1 - skip 3 bits
365 * @param chNum - channel number to get info about
366 * @param reserved2 - skip 4 bits
367 * @param privLevel - requested privilege level
368
369 * @returns ipmi completion code plus response data
370 * - channel number
371 * - rmcpAuthTypes - RMCP auth types (IPMI 1.5)
372 * - reserved1
373 * - extDataSupport - true for IPMI 2.0 extensions
374 * - anonymousLogin - true for anonymous login enabled
375 * - nullUsers - true for null user names enabled
376 * - nonNullUsers - true for non-null usernames enabled
377 * - userAuth - false for user authentication enabled
378 * - perMessageAuth - false for per message authentication enabled
379 * - KGStatus - true for Kg required for authentication
380 * - reserved2
381 * - rmcp - RMCP (IPMI 1.5) connection support
382 * - rmcpp - RMCP+ (IPMI 2.0) connection support
383 * - reserved3
384 * - oemID - OEM IANA of any OEM auth support
385 * - oemAuxillary - OEM data for auth
386 */
387ipmi::RspType<uint8_t, // channel number
388 uint6_t, // rmcpAuthTypes
389 bool, // reserved1
390 bool, // extDataSupport
391 bool, // anonymousLogin
392 bool, // nullUsers
393 bool, // nonNullUsers
394 bool, // userAuth
395 bool, // perMessageAuth
396 bool, // KGStatus
397 uint2_t, // reserved2
398 bool, // rmcp
399 bool, // rmcpp
400 uint6_t, // reserved3
401 uint24_t, // oemID
402 uint8_t // oemAuxillary
403 >
404 ipmiGetChannelAuthenticationCapabilities(ipmi::Context::ptr ctx,
405 uint4_t chNum, uint3_t reserved1,
406 bool extData, uint4_t privLevel,
407 uint4_t reserved2)
408{
smritic46f6cd2019-03-20 14:09:41 +0530409 uint8_t channel =
Vernon Mauery5ed39592019-05-14 09:16:53 -0700410 convertCurrentChannelNum(static_cast<uint8_t>(chNum), ctx->channel);
smritic46f6cd2019-03-20 14:09:41 +0530411
412 if (reserved1 || reserved2 || !isValidChannel(channel) ||
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000413 !isValidPrivLimit(static_cast<uint8_t>(privLevel)))
smritic46f6cd2019-03-20 14:09:41 +0530414 {
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000415 log<level::DEBUG>(
416 "Get channel auth capabilities - Invalid field in request");
417 return ipmi::responseInvalidFieldRequest();
418 }
419
420 if (getChannelSessionSupport(channel) == EChannelSessSupported::none)
421 {
422 log<level::DEBUG>(
423 "Get channel auth capabilities - No support on channel");
424 return ipmi::response(ccActionNotSupportedForChannel);
smritic46f6cd2019-03-20 14:09:41 +0530425 }
426
427 constexpr bool extDataSupport = true; // true for IPMI 2.0 extensions
428 constexpr bool reserved3 = false;
429 constexpr uint6_t rmcpAuthTypes = 0; // IPMI 1.5 auth types - not supported
430 constexpr uint2_t reserved4 = 0;
431 constexpr bool KGStatus = false; // Not supporting now.
432 constexpr bool perMessageAuth = false; // Per message auth - enabled
433 constexpr bool userAuth = false; // User authentication - enabled
434 constexpr bool nullUsers = false; // Null user names - not supported
435 constexpr bool anonymousLogin = false; // Anonymous login - not supported
436 constexpr uint6_t reserved5 = 0;
437 constexpr bool rmcpp = true; // IPMI 2.0 - supported
438 constexpr bool rmcp = false; // IPMI 1.5 - not supported
439 constexpr uint24_t oemID = 0;
440 constexpr uint8_t oemAuxillary = 0;
441
442 bool nonNullUsers = 0;
443 uint8_t maxChUsers = 0, enabledUsers = 0, fixedUsers = 0;
444 ipmi::ipmiUserGetAllCounts(maxChUsers, enabledUsers, fixedUsers);
445 nonNullUsers = enabledUsers > 0;
446
447 return ipmi::responseSuccess(
448 channel, rmcpAuthTypes, reserved3, extDataSupport, anonymousLogin,
449 nullUsers, nonNullUsers, userAuth, perMessageAuth, KGStatus, reserved4,
450 rmcp, rmcpp, reserved5, oemID, oemAuxillary);
451}
452
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000453/** @brief implements the set user payload access command.
454 * @param ctx - IPMI context pointer (for channel)
455 * @param channel - channel number (4 bits)
456 * @param reserved1 - skip 4 bits
457 * @param userId - user id (6 bits)
458 * @param operation - access ENABLE /DISABLE. (2 bits)
459 * @param stdPayload0 - IPMI - reserved. (1 bit)
460 * @param stdPayload1 - SOL. (1 bit)
461 * @param stdPayload2 - (1 bit)
462 * @param stdPayload3 - (1 bit)
463 * @param stdPayload4 - (1 bit)
464 * @param stdPayload5 - (1 bit)
465 * @param stdPayload6 - (1 bit)
466 * @param stdPayload7 - (1 bit)
467 * @param stdPayloadEnables2Reserved - (8 bits)
468 * @param oemPayload0 - (1 bit)
469 * @param oemPayload1 - (1 bit)
470 * @param oemPayload2 - (1 bit)
471 * @param oemPayload3 - (1 bit)
472 * @param oemPayload4 - (1 bit)
473 * @param oemPayload5 - (1 bit)
474 * @param oemPayload6 - (1 bit)
475 * @param oemPayload7 - (1 bit)
476 * @param oemPayloadEnables2Reserved - (8 bits)
477 *
478 * @returns IPMI completion code
479 */
480ipmi::RspType<> ipmiSetUserPayloadAccess(
481 ipmi::Context::ptr ctx,
482
483 uint4_t channel, uint4_t reserved,
484
485 uint6_t userId, uint2_t operation,
486
487 bool stdPayload0ipmiReserved, bool stdPayload1SOL, bool stdPayload2,
488 bool stdPayload3, bool stdPayload4, bool stdPayload5, bool stdPayload6,
489 bool stdPayload7,
490
491 uint8_t stdPayloadEnables2Reserved,
492
493 bool oemPayload0, bool oemPayload1, bool oemPayload2, bool oemPayload3,
494 bool oemPayload4, bool oemPayload5, bool oemPayload6, bool oemPayload7,
495
496 uint8_t oemPayloadEnables2Reserved)
497{
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000498 auto chNum =
499 convertCurrentChannelNum(static_cast<uint8_t>(channel), ctx->channel);
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000500 // Validate the reserved args. Only SOL payload is supported as on date.
501 if (reserved || stdPayload0ipmiReserved || stdPayload2 || stdPayload3 ||
502 stdPayload4 || stdPayload5 || stdPayload6 || stdPayload7 ||
503 oemPayload0 || oemPayload1 || oemPayload2 || oemPayload3 ||
504 oemPayload4 || oemPayload5 || oemPayload6 || oemPayload7 ||
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000505 stdPayloadEnables2Reserved || oemPayloadEnables2Reserved ||
506 !isValidChannel(chNum))
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000507 {
508 return ipmi::responseInvalidFieldRequest();
509 }
510
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000511 if ((operation != enableOperation && operation != disableOperation))
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000512 {
513 return ipmi::responseInvalidFieldRequest();
514 }
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000515 if (getChannelSessionSupport(chNum) == EChannelSessSupported::none)
516 {
517 return ipmi::response(ccActionNotSupportedForChannel);
518 }
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000519 if (!ipmiUserIsValidUserId(static_cast<uint8_t>(userId)))
520 {
521 return ipmi::responseParmOutOfRange();
522 }
523
524 PayloadAccess payloadAccess = {0};
525 payloadAccess.stdPayloadEnables1[1] = stdPayload1SOL;
526
527 return ipmi::response(ipmiUserSetUserPayloadAccess(
528 chNum, static_cast<uint8_t>(operation), static_cast<uint8_t>(userId),
529 payloadAccess));
530}
531
532/** @brief implements the get user payload access command
533 * This command returns information about user payload enable settings
534 * that were set using the 'Set User Payload Access' Command.
535 *
536 * @param ctx - IPMI context pointer (for channel)
537 * @param channel - channel number
538 * @param reserved1 - skip 4 bits
539 * @param userId - user id
540 * @param reserved2 - skip 2 bits
541 *
542 * @returns IPMI completion code plus response data
543 * - stdPayload0ipmiReserved - IPMI payload (reserved).
544 * - stdPayload1SOL - SOL payload
545 * - stdPayload2
546 * - stdPayload3
547 * - stdPayload4
548 * - stdPayload5
549 * - stdPayload6
550 * - stdPayload7
551
552 * - stdPayloadEnables2Reserved - Reserved.
553
554 * - oemPayload0
555 * - oemPayload1
556 * - oemPayload2
557 * - oemPayload3
558 * - oemPayload4
559 * - oemPayload5
560 * - oemPayload6
561 * - oemPayload7
562
563 * - oemPayloadEnables2Reserved - Reserved
564 */
565ipmi::RspType<bool, // stdPayload0ipmiReserved
566 bool, // stdPayload1SOL
567 bool, // stdPayload2
568 bool, // stdPayload3
569 bool, // stdPayload4
570 bool, // stdPayload5
571 bool, // stdPayload6
572 bool, // stdPayload7
573
574 uint8_t, // stdPayloadEnables2Reserved
575
576 bool, // oemPayload0
577 bool, // oemPayload1
578 bool, // oemPayload2
579 bool, // oemPayload3
580 bool, // oemPayload4
581 bool, // oemPayload5
582 bool, // oemPayload6
583 bool, // oemPayload7
584
585 uint8_t // oemPayloadEnables2Reserved
586 >
587 ipmiGetUserPayloadAccess(ipmi::Context::ptr ctx,
588
589 uint4_t channel, uint4_t reserved1,
590
591 uint6_t userId, uint2_t reserved2)
592{
593 uint8_t chNum =
594 convertCurrentChannelNum(static_cast<uint8_t>(channel), ctx->channel);
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000595
596 if (reserved1 || reserved2 || !isValidChannel(chNum))
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000597 {
598 return ipmi::responseInvalidFieldRequest();
599 }
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000600 if (getChannelSessionSupport(chNum) == EChannelSessSupported::none)
601 {
602 return ipmi::response(ccActionNotSupportedForChannel);
603 }
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000604 if (!ipmiUserIsValidUserId(static_cast<uint8_t>(userId)))
605 {
606 return ipmi::responseParmOutOfRange();
607 }
608
609 ipmi::Cc retStatus;
610 PayloadAccess payloadAccess = {};
611 retStatus = ipmiUserGetUserPayloadAccess(
612 chNum, static_cast<uint8_t>(userId), payloadAccess);
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000613 if (retStatus != ccSuccess)
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000614 {
615 return ipmi::response(retStatus);
616 }
617 constexpr uint8_t res8bits = 0;
618 return ipmi::responseSuccess(payloadAccess.stdPayloadEnables1.test(0),
619 payloadAccess.stdPayloadEnables1.test(1),
620 payloadAccess.stdPayloadEnables1.test(2),
621 payloadAccess.stdPayloadEnables1.test(3),
622 payloadAccess.stdPayloadEnables1.test(4),
623 payloadAccess.stdPayloadEnables1.test(5),
624 payloadAccess.stdPayloadEnables1.test(6),
625 payloadAccess.stdPayloadEnables1.test(7),
626
627 res8bits,
628
629 payloadAccess.oemPayloadEnables1.test(0),
630 payloadAccess.oemPayloadEnables1.test(1),
631 payloadAccess.oemPayloadEnables1.test(2),
632 payloadAccess.oemPayloadEnables1.test(3),
633 payloadAccess.oemPayloadEnables1.test(4),
634 payloadAccess.oemPayloadEnables1.test(5),
635 payloadAccess.oemPayloadEnables1.test(6),
636 payloadAccess.oemPayloadEnables1.test(7),
637
638 res8bits);
639}
640
William A. Kennington III343d0612018-12-10 15:56:24 -0800641void registerUserIpmiFunctions() __attribute__((constructor));
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530642void registerUserIpmiFunctions()
643{
Richard Marian Thomaiyar0be80bd2020-01-10 12:20:16 +0530644 post_work([]() { ipmiUserInit(); });
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530645 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
646 ipmi::app::cmdSetUserAccessCommand,
647 ipmi::Privilege::Admin, ipmiSetUserAccess);
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530648
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530649 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
650 ipmi::app::cmdGetUserAccessCommand,
651 ipmi::Privilege::Operator, ipmiGetUserAccess);
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530652
Vernon Mauery3c89de12021-08-05 11:08:23 -0700653 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
654 ipmi::app::cmdGetUserNameCommand,
655 ipmi::Privilege::Operator, ipmiGetUserName);
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530656
Vernon Maueryac30b392021-08-05 11:08:23 -0700657 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
658 ipmi::app::cmdSetUserName, ipmi::Privilege::Admin,
659 ipmiSetUserName);
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530660
Vernon Mauery7a3296d2021-08-05 11:08:23 -0700661 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
662 ipmi::app::cmdSetUserPasswordCommand,
663 ipmi::Privilege::Admin, ipmiSetUserPassword);
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530664
smritic46f6cd2019-03-20 14:09:41 +0530665 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
666 ipmi::app::cmdGetChannelAuthCapabilities,
667 ipmi::Privilege::Callback,
668 ipmiGetChannelAuthenticationCapabilities);
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000669
670 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
671 ipmi::app::cmdSetUserPayloadAccess,
672 ipmi::Privilege::Admin, ipmiSetUserPayloadAccess);
673
674 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
675 ipmi::app::cmdGetUserPayloadAccess,
676 ipmi::Privilege::Operator, ipmiGetUserPayloadAccess);
677
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530678 return;
679}
680} // namespace ipmi