blob: 6467e45a72116be80fef02bdb587ee9c6faf0b6b [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>
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -050027
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +053028#include <regex>
29
30namespace ipmi
31{
32
33using namespace phosphor::logging;
34
Saravanan Palanisamy77381f12019-05-15 22:33:17 +000035static constexpr uint8_t enableOperation = 0x00;
36static constexpr uint8_t disableOperation = 0x01;
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +053037
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +053038/** @brief implements the set user access command
39 * @param ctx - IPMI context pointer (for channel)
40 * @param channel - channel number
41 * @param ipmiEnabled - indicates ipmi messaging state
42 * @param linkAuthEnabled - indicates link authentication state
43 * @param accessCallback - indicates callback state
44 * @param bitsUpdate - indicates update request
45 * @param userId - user id
46 * @param reserved1 - skip 2 bits
47 * @param privilege - user privilege
48 * @param reserved2 - skip 4 bits
49 * @param sessionLimit - optional - unused for now
50 *
51 * @returns ipmi completion code
52 */
53ipmi::RspType<> ipmiSetUserAccess(ipmi::Context::ptr ctx, uint4_t channel,
54 uint1_t ipmiEnabled, uint1_t linkAuthEnabled,
55 uint1_t accessCallback, uint1_t bitsUpdate,
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +053056
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +053057 uint6_t userId, uint2_t reserved1,
58
59 uint4_t privilege, uint4_t reserved2,
60
61 std::optional<uint8_t> sessionLimit)
62{
63 uint8_t sessLimit = sessionLimit.value_or(0);
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +000064 if (reserved1 || reserved2 || sessLimit ||
65 !ipmiUserIsValidPrivilege(static_cast<uint8_t>(privilege)))
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +053066 {
67 log<level::DEBUG>("Set user access - Invalid field in request");
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +053068 return ipmi::responseInvalidFieldRequest();
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +053069 }
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +000070
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -050071 uint8_t chNum = convertCurrentChannelNum(static_cast<uint8_t>(channel),
72 ctx->channel);
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +000073 if (!isValidChannel(chNum))
74 {
75 log<level::DEBUG>("Set user access - Invalid channel request");
76 return ipmi::response(invalidChannel);
77 }
78 if (getChannelSessionSupport(chNum) == EChannelSessSupported::none)
79 {
80 log<level::DEBUG>("Set user access - No support on channel");
81 return ipmi::response(ccActionNotSupportedForChannel);
82 }
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +053083 if (!ipmiUserIsValidUserId(static_cast<uint8_t>(userId)))
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +053084 {
85 log<level::DEBUG>("Set user access - Parameter out of range");
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +053086 return ipmi::responseParmOutOfRange();
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +053087 }
Richard Marian Thomaiyar06df8762018-12-08 17:38:25 +053088
Willy Tu11d68892022-01-20 10:37:34 -080089 PrivAccess privAccess = {};
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +053090 if (bitsUpdate)
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +053091 {
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +053092 privAccess.ipmiEnabled = static_cast<uint8_t>(ipmiEnabled);
93 privAccess.linkAuthEnabled = static_cast<uint8_t>(linkAuthEnabled);
94 privAccess.accessCallback = static_cast<uint8_t>(accessCallback);
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +053095 }
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +053096 privAccess.privilege = static_cast<uint8_t>(privilege);
97 return ipmi::response(
98 ipmiUserSetPrivilegeAccess(static_cast<uint8_t>(userId), chNum,
99 privAccess, static_cast<bool>(bitsUpdate)));
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530100}
101
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530102/** @brief implements the set user access command
103 * @param ctx - IPMI context pointer (for channel)
104 * @param channel - channel number
105 * @param reserved1 - skip 4 bits
106 * @param userId - user id
107 * @param reserved2 - skip 2 bits
108 *
109 * @returns ipmi completion code plus response data
110 * - maxChUsers - max channel users
111 * - reserved1 - skip 2 bits
112 * - enabledUsers - enabled users count
113 * - enabledStatus - enabled status
114 * - fixedUsers - fixed users count
115 * - reserved2 - skip 2 bits
116 * - privilege - user privilege
117 * - ipmiEnabled - ipmi messaging state
118 * - linkAuthEnabled - link authenticatin state
119 * - accessCallback - callback state
120 * - reserved - skip 1 bit
121 */
122ipmi::RspType<uint6_t, // max channel users
123 uint2_t, // reserved1
124
125 uint6_t, // enabled users count
126 uint2_t, // enabled status
127
128 uint6_t, // fixed users count
129 uint2_t, // reserved2
130
131 uint4_t, // privilege
132 uint1_t, // ipmi messaging state
133 uint1_t, // link authentication state
134 uint1_t, // access callback state
135 uint1_t // reserved3
136 >
137 ipmiGetUserAccess(ipmi::Context::ptr ctx, uint4_t channel,
138 uint4_t reserved1,
139
140 uint6_t userId, uint2_t reserved2)
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530141{
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -0500142 uint8_t chNum = convertCurrentChannelNum(static_cast<uint8_t>(channel),
143 ctx->channel);
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000144
145 if (reserved1 || reserved2 || !isValidChannel(chNum))
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530146 {
147 log<level::DEBUG>("Get user access - Invalid field in request");
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530148 return ipmi::responseInvalidFieldRequest();
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530149 }
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000150
151 if (getChannelSessionSupport(chNum) == EChannelSessSupported::none)
152 {
153 log<level::DEBUG>("Get user access - No support on channel");
154 return ipmi::response(ccActionNotSupportedForChannel);
155 }
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530156 if (!ipmiUserIsValidUserId(static_cast<uint8_t>(userId)))
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530157 {
158 log<level::DEBUG>("Get user access - Parameter out of range");
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530159 return ipmi::responseParmOutOfRange();
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530160 }
161
162 uint8_t maxChUsers = 0, enabledUsers = 0, fixedUsers = 0;
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530163 ipmi::Cc retStatus;
Richard Marian Thomaiyarb6771e02019-01-29 14:42:44 +0530164 retStatus = ipmiUserGetAllCounts(maxChUsers, enabledUsers, fixedUsers);
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000165 if (retStatus != ccSuccess)
Richard Marian Thomaiyarb6771e02019-01-29 14:42:44 +0530166 {
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530167 return ipmi::response(retStatus);
Richard Marian Thomaiyarb6771e02019-01-29 14:42:44 +0530168 }
169
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530170 bool enabledState = false;
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -0500171 retStatus = ipmiUserCheckEnabled(static_cast<uint8_t>(userId),
172 enabledState);
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000173 if (retStatus != ccSuccess)
Richard Marian Thomaiyarb6771e02019-01-29 14:42:44 +0530174 {
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530175 return ipmi::response(retStatus);
Richard Marian Thomaiyarb6771e02019-01-29 14:42:44 +0530176 }
177
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530178 uint2_t enabledStatus = enabledState ? userIdEnabledViaSetPassword
179 : userIdDisabledViaSetPassword;
180 PrivAccess privAccess{};
181 retStatus = ipmiUserGetPrivilegeAccess(static_cast<uint8_t>(userId), chNum,
182 privAccess);
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000183 if (retStatus != ccSuccess)
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530184 {
185 return ipmi::response(retStatus);
186 }
187 constexpr uint2_t res2Bits = 0;
188 return ipmi::responseSuccess(
189 static_cast<uint6_t>(maxChUsers), res2Bits,
190
191 static_cast<uint6_t>(enabledUsers), enabledStatus,
192
193 static_cast<uint6_t>(fixedUsers), res2Bits,
194
195 static_cast<uint4_t>(privAccess.privilege),
196 static_cast<uint1_t>(privAccess.ipmiEnabled),
197 static_cast<uint1_t>(privAccess.linkAuthEnabled),
198 static_cast<uint1_t>(privAccess.accessCallback),
199 static_cast<uint1_t>(privAccess.reserved));
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530200}
201
Vernon Maueryac30b392021-08-05 11:08:23 -0700202/** @brief implementes the get user name command
203 * @param[in] ctx - ipmi command context
204 * @param[in] userId - 6-bit user ID
205 * @param[in] reserved - 2-bits reserved
206 * @param[in] name - 16-byte array for username
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530207
Vernon Maueryac30b392021-08-05 11:08:23 -0700208 * @returns ipmi response
209 */
210ipmi::RspType<>
Willy Tu11d68892022-01-20 10:37:34 -0800211 ipmiSetUserName([[maybe_unused]] ipmi::Context::ptr ctx, uint6_t id,
212 uint2_t reserved,
Vernon Maueryac30b392021-08-05 11:08:23 -0700213 const std::array<uint8_t, ipmi::ipmiMaxUserName>& name)
214{
215 if (reserved)
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530216 {
Vernon Maueryac30b392021-08-05 11:08:23 -0700217 return ipmi::responseInvalidFieldRequest();
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530218 }
Vernon Maueryac30b392021-08-05 11:08:23 -0700219 uint8_t userId = static_cast<uint8_t>(id);
220 if (!ipmiUserIsValidUserId(userId))
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530221 {
222 log<level::DEBUG>("Set user name - Invalid user id");
Vernon Maueryac30b392021-08-05 11:08:23 -0700223 return ipmi::responseParmOutOfRange();
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530224 }
225
Vernon Maueryac30b392021-08-05 11:08:23 -0700226 size_t nameLen = strnlen(reinterpret_cast<const char*>(name.data()),
227 ipmi::ipmiMaxUserName);
228 const std::string strUserName(reinterpret_cast<const char*>(name.data()),
jayaprakash Mutyalacdcdf2b2020-03-28 00:12:05 +0000229 nameLen);
230
Vernon Maueryac30b392021-08-05 11:08:23 -0700231 ipmi::Cc res = ipmiUserSetUserName(userId, strUserName);
232 return ipmi::response(res);
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530233}
234
235/** @brief implementes the get user name command
Vernon Mauery3c89de12021-08-05 11:08:23 -0700236 * @param[in] ctx - ipmi command context
237 * @param[in] userId - 6-bit user ID
238 * @param[in] reserved - 2-bits reserved
239
240 * @returns ipmi response with 16-byte username
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530241 */
Vernon Mauery3c89de12021-08-05 11:08:23 -0700242ipmi::RspType<std::array<uint8_t, ipmi::ipmiMaxUserName>> // user name
Willy Tu11d68892022-01-20 10:37:34 -0800243 ipmiGetUserName([[maybe_unused]] ipmi::Context::ptr ctx, uint6_t id,
244 uint2_t reserved)
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530245{
Vernon Mauery3c89de12021-08-05 11:08:23 -0700246 if (reserved)
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530247 {
Vernon Mauery3c89de12021-08-05 11:08:23 -0700248 return ipmi::responseInvalidFieldRequest();
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530249 }
250
Vernon Mauery3c89de12021-08-05 11:08:23 -0700251 uint8_t userId = static_cast<uint8_t>(id);
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530252 std::string userName;
Vernon Mauery3c89de12021-08-05 11:08:23 -0700253 if (ipmiUserGetUserName(userId, userName) != ccSuccess)
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530254 { // Invalid User ID
Vernon Mauery3c89de12021-08-05 11:08:23 -0700255 log<level::DEBUG>("User Name not found", entry("USER-ID=%u", userId));
256 return ipmi::responseParmOutOfRange();
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530257 }
Vernon Mauery3c89de12021-08-05 11:08:23 -0700258 // copy the std::string into a fixed array
259 if (userName.size() > ipmi::ipmiMaxUserName)
260 {
261 return ipmi::responseUnspecifiedError();
262 }
263 std::array<uint8_t, ipmi::ipmiMaxUserName> userNameFixed;
264 std::fill(userNameFixed.begin(), userNameFixed.end(), 0);
265 std::copy(userName.begin(), userName.end(), userNameFixed.begin());
266 return ipmi::responseSuccess(std::move(userNameFixed));
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530267}
268
Vernon Mauery7a3296d2021-08-05 11:08:23 -0700269/** @brief implementes the get user name command
270 * @param[in] ctx - ipmi command context
271 * @param[in] userId - 6-bit user ID
272 * @param[in] reserved - 2-bits reserved
273
274 * @returns ipmi response with 16-byte username
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530275 */
Vernon Mauery7a3296d2021-08-05 11:08:23 -0700276ipmi::RspType<> // user name
Willy Tu11d68892022-01-20 10:37:34 -0800277 ipmiSetUserPassword([[maybe_unused]] ipmi::Context::ptr ctx, uint6_t id,
278 bool reserved1, bool pwLen20, uint2_t operation,
279 uint6_t reserved2, SecureBuffer& userPassword)
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530280{
Vernon Mauery7a3296d2021-08-05 11:08:23 -0700281 if (reserved1 || reserved2)
Snehalatha Venkatesh37b1d1a2021-06-28 10:13:37 +0000282 {
283 log<level::DEBUG>("Invalid data field in request");
Vernon Mauery7a3296d2021-08-05 11:08:23 -0700284 return ipmi::responseInvalidFieldRequest();
Snehalatha Venkatesh37b1d1a2021-06-28 10:13:37 +0000285 }
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530286
Ayushi Smriti29b9f312021-09-24 12:29:23 +0530287 static constexpr uint2_t opDisableUser = 0x00;
288 static constexpr uint2_t opEnableUser = 0x01;
289 static constexpr uint2_t opSetPassword = 0x02;
290 static constexpr uint2_t opTestPassword = 0x03;
291
292 // If set / test password operation then password size has to be 16 or 20
293 // bytes based on the password size bit
294 if (((operation == opSetPassword) || (operation == opTestPassword)) &&
295 ((pwLen20 && (userPassword.size() != maxIpmi20PasswordSize)) ||
296 (!pwLen20 && (userPassword.size() != maxIpmi15PasswordSize))))
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530297 {
298 log<level::DEBUG>("Invalid Length");
Vernon Mauery7a3296d2021-08-05 11:08:23 -0700299 return ipmi::responseReqDataLenInvalid();
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530300 }
Ayushi Smriti29b9f312021-09-24 12:29:23 +0530301
Vernon Mauery7a3296d2021-08-05 11:08:23 -0700302 size_t passwordLength = userPassword.size();
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530303
Vernon Mauery7a3296d2021-08-05 11:08:23 -0700304 uint8_t userId = static_cast<uint8_t>(id);
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530305 std::string userName;
Vernon Mauery7a3296d2021-08-05 11:08:23 -0700306 if (ipmiUserGetUserName(userId, userName) != ccSuccess)
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530307 {
Vernon Mauery7a3296d2021-08-05 11:08:23 -0700308 log<level::DEBUG>("User Name not found", entry("USER-ID=%d", userId));
309 return ipmi::responseParmOutOfRange();
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530310 }
Vernon Mauery7a3296d2021-08-05 11:08:23 -0700311
Vernon Mauery7a3296d2021-08-05 11:08:23 -0700312 if (operation == opSetPassword)
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530313 {
Vernon Mauery7a3296d2021-08-05 11:08:23 -0700314 // turn the non-nul terminated SecureBuffer into a SecureString
315 SecureString password(
316 reinterpret_cast<const char*>(userPassword.data()), passwordLength);
317 ipmi::Cc res = ipmiUserSetUserPassword(userId, password.data());
318 return ipmi::response(res);
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530319 }
Vernon Mauery7a3296d2021-08-05 11:08:23 -0700320 else if (operation == opEnableUser || operation == opDisableUser)
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530321 {
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -0500322 ipmi::Cc res = ipmiUserUpdateEnabledState(userId,
323 static_cast<bool>(operation));
Vernon Mauery7a3296d2021-08-05 11:08:23 -0700324 return ipmi::response(res);
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530325 }
Vernon Mauery7a3296d2021-08-05 11:08:23 -0700326 else if (operation == opTestPassword)
Richard Marian Thomaiyar282e79b2018-11-13 19:00:58 +0530327 {
Vernon Mauery1e22a0f2021-07-30 13:36:54 -0700328 SecureString password = ipmiUserGetPassword(userName);
Vernon Mauery7a3296d2021-08-05 11:08:23 -0700329 // extend with zeros, if needed
330 if (password.size() < passwordLength)
331 {
332 password.resize(passwordLength, '\0');
333 }
Vernon Mauery1e22a0f2021-07-30 13:36:54 -0700334 SecureString testPassword(
Vernon Mauery7a3296d2021-08-05 11:08:23 -0700335 reinterpret_cast<const char*>(userPassword.data()), passwordLength);
Vernon Mauery1e22a0f2021-07-30 13:36:54 -0700336 // constant time string compare: always compare exactly as many bytes
337 // as the length of the input, resizing the actual password to match,
338 // maintaining a knowledge if the sizes differed originally
339 static const std::array<char, maxIpmi20PasswordSize> empty = {'\0'};
340 size_t cmpLen = testPassword.size();
341 bool pwLenDiffers = password.size() != cmpLen;
342 const char* cmpPassword = nullptr;
343 if (pwLenDiffers)
344 {
345 cmpPassword = empty.data();
346 }
347 else
348 {
349 cmpPassword = password.data();
350 }
351 bool pwBad = CRYPTO_memcmp(cmpPassword, testPassword.data(), cmpLen);
352 pwBad |= pwLenDiffers;
353 if (pwBad)
Richard Marian Thomaiyar282e79b2018-11-13 19:00:58 +0530354 {
355 log<level::DEBUG>("Test password failed",
Vernon Mauery7a3296d2021-08-05 11:08:23 -0700356 entry("USER-ID=%d", userId));
357 static constexpr ipmi::Cc ipmiCCPasswdFailMismatch = 0x80;
358 return ipmi::response(ipmiCCPasswdFailMismatch);
Richard Marian Thomaiyar282e79b2018-11-13 19:00:58 +0530359 }
Vernon Mauery7a3296d2021-08-05 11:08:23 -0700360 return ipmi::responseSuccess();
Richard Marian Thomaiyar282e79b2018-11-13 19:00:58 +0530361 }
Vernon Mauery7a3296d2021-08-05 11:08:23 -0700362 return ipmi::responseInvalidFieldRequest();
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530363}
364
smritic46f6cd2019-03-20 14:09:41 +0530365/** @brief implements the get channel authentication command
366 * @param ctx - IPMI context pointer (for channel)
367 * @param extData - get IPMI 2.0 extended data
368 * @param reserved1 - skip 3 bits
369 * @param chNum - channel number to get info about
370 * @param reserved2 - skip 4 bits
371 * @param privLevel - requested privilege level
372
373 * @returns ipmi completion code plus response data
374 * - channel number
375 * - rmcpAuthTypes - RMCP auth types (IPMI 1.5)
376 * - reserved1
377 * - extDataSupport - true for IPMI 2.0 extensions
378 * - anonymousLogin - true for anonymous login enabled
379 * - nullUsers - true for null user names enabled
380 * - nonNullUsers - true for non-null usernames enabled
381 * - userAuth - false for user authentication enabled
382 * - perMessageAuth - false for per message authentication enabled
383 * - KGStatus - true for Kg required for authentication
384 * - reserved2
385 * - rmcp - RMCP (IPMI 1.5) connection support
386 * - rmcpp - RMCP+ (IPMI 2.0) connection support
387 * - reserved3
388 * - oemID - OEM IANA of any OEM auth support
389 * - oemAuxillary - OEM data for auth
390 */
391ipmi::RspType<uint8_t, // channel number
392 uint6_t, // rmcpAuthTypes
393 bool, // reserved1
394 bool, // extDataSupport
395 bool, // anonymousLogin
396 bool, // nullUsers
397 bool, // nonNullUsers
398 bool, // userAuth
399 bool, // perMessageAuth
400 bool, // KGStatus
401 uint2_t, // reserved2
402 bool, // rmcp
403 bool, // rmcpp
404 uint6_t, // reserved3
405 uint24_t, // oemID
406 uint8_t // oemAuxillary
407 >
408 ipmiGetChannelAuthenticationCapabilities(ipmi::Context::ptr ctx,
409 uint4_t chNum, uint3_t reserved1,
Willy Tu11d68892022-01-20 10:37:34 -0800410 [[maybe_unused]] bool extData,
411 uint4_t privLevel,
smritic46f6cd2019-03-20 14:09:41 +0530412 uint4_t reserved2)
413{
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -0500414 uint8_t channel = convertCurrentChannelNum(static_cast<uint8_t>(chNum),
415 ctx->channel);
smritic46f6cd2019-03-20 14:09:41 +0530416
417 if (reserved1 || reserved2 || !isValidChannel(channel) ||
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000418 !isValidPrivLimit(static_cast<uint8_t>(privLevel)))
smritic46f6cd2019-03-20 14:09:41 +0530419 {
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000420 log<level::DEBUG>(
421 "Get channel auth capabilities - Invalid field in request");
422 return ipmi::responseInvalidFieldRequest();
423 }
424
425 if (getChannelSessionSupport(channel) == EChannelSessSupported::none)
426 {
427 log<level::DEBUG>(
428 "Get channel auth capabilities - No support on channel");
429 return ipmi::response(ccActionNotSupportedForChannel);
smritic46f6cd2019-03-20 14:09:41 +0530430 }
431
432 constexpr bool extDataSupport = true; // true for IPMI 2.0 extensions
433 constexpr bool reserved3 = false;
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -0500434 constexpr uint6_t rmcpAuthTypes = 0; // IPMI 1.5 auth types - not supported
smritic46f6cd2019-03-20 14:09:41 +0530435 constexpr uint2_t reserved4 = 0;
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -0500436 constexpr bool KGStatus = false; // Not supporting now.
smritic46f6cd2019-03-20 14:09:41 +0530437 constexpr bool perMessageAuth = false; // Per message auth - enabled
438 constexpr bool userAuth = false; // User authentication - enabled
439 constexpr bool nullUsers = false; // Null user names - not supported
440 constexpr bool anonymousLogin = false; // Anonymous login - not supported
441 constexpr uint6_t reserved5 = 0;
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -0500442 constexpr bool rmcpp = true; // IPMI 2.0 - supported
443 constexpr bool rmcp = false; // IPMI 1.5 - not supported
smritic46f6cd2019-03-20 14:09:41 +0530444 constexpr uint24_t oemID = 0;
445 constexpr uint8_t oemAuxillary = 0;
446
447 bool nonNullUsers = 0;
448 uint8_t maxChUsers = 0, enabledUsers = 0, fixedUsers = 0;
449 ipmi::ipmiUserGetAllCounts(maxChUsers, enabledUsers, fixedUsers);
450 nonNullUsers = enabledUsers > 0;
451
452 return ipmi::responseSuccess(
453 channel, rmcpAuthTypes, reserved3, extDataSupport, anonymousLogin,
454 nullUsers, nonNullUsers, userAuth, perMessageAuth, KGStatus, reserved4,
455 rmcp, rmcpp, reserved5, oemID, oemAuxillary);
456}
457
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000458/** @brief implements the set user payload access command.
459 * @param ctx - IPMI context pointer (for channel)
460 * @param channel - channel number (4 bits)
461 * @param reserved1 - skip 4 bits
462 * @param userId - user id (6 bits)
463 * @param operation - access ENABLE /DISABLE. (2 bits)
464 * @param stdPayload0 - IPMI - reserved. (1 bit)
465 * @param stdPayload1 - SOL. (1 bit)
466 * @param stdPayload2 - (1 bit)
467 * @param stdPayload3 - (1 bit)
468 * @param stdPayload4 - (1 bit)
469 * @param stdPayload5 - (1 bit)
470 * @param stdPayload6 - (1 bit)
471 * @param stdPayload7 - (1 bit)
472 * @param stdPayloadEnables2Reserved - (8 bits)
473 * @param oemPayload0 - (1 bit)
474 * @param oemPayload1 - (1 bit)
475 * @param oemPayload2 - (1 bit)
476 * @param oemPayload3 - (1 bit)
477 * @param oemPayload4 - (1 bit)
478 * @param oemPayload5 - (1 bit)
479 * @param oemPayload6 - (1 bit)
480 * @param oemPayload7 - (1 bit)
481 * @param oemPayloadEnables2Reserved - (8 bits)
482 *
483 * @returns IPMI completion code
484 */
485ipmi::RspType<> ipmiSetUserPayloadAccess(
486 ipmi::Context::ptr ctx,
487
488 uint4_t channel, uint4_t reserved,
489
490 uint6_t userId, uint2_t operation,
491
492 bool stdPayload0ipmiReserved, bool stdPayload1SOL, bool stdPayload2,
493 bool stdPayload3, bool stdPayload4, bool stdPayload5, bool stdPayload6,
494 bool stdPayload7,
495
496 uint8_t stdPayloadEnables2Reserved,
497
498 bool oemPayload0, bool oemPayload1, bool oemPayload2, bool oemPayload3,
499 bool oemPayload4, bool oemPayload5, bool oemPayload6, bool oemPayload7,
500
501 uint8_t oemPayloadEnables2Reserved)
502{
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -0500503 auto chNum = convertCurrentChannelNum(static_cast<uint8_t>(channel),
504 ctx->channel);
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000505 // Validate the reserved args. Only SOL payload is supported as on date.
506 if (reserved || stdPayload0ipmiReserved || stdPayload2 || stdPayload3 ||
507 stdPayload4 || stdPayload5 || stdPayload6 || stdPayload7 ||
508 oemPayload0 || oemPayload1 || oemPayload2 || oemPayload3 ||
509 oemPayload4 || oemPayload5 || oemPayload6 || oemPayload7 ||
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000510 stdPayloadEnables2Reserved || oemPayloadEnables2Reserved ||
511 !isValidChannel(chNum))
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000512 {
513 return ipmi::responseInvalidFieldRequest();
514 }
515
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000516 if ((operation != enableOperation && operation != disableOperation))
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000517 {
518 return ipmi::responseInvalidFieldRequest();
519 }
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000520 if (getChannelSessionSupport(chNum) == EChannelSessSupported::none)
521 {
522 return ipmi::response(ccActionNotSupportedForChannel);
523 }
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000524 if (!ipmiUserIsValidUserId(static_cast<uint8_t>(userId)))
525 {
526 return ipmi::responseParmOutOfRange();
527 }
528
Willy Tu11d68892022-01-20 10:37:34 -0800529 PayloadAccess payloadAccess = {};
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000530 payloadAccess.stdPayloadEnables1[1] = stdPayload1SOL;
531
532 return ipmi::response(ipmiUserSetUserPayloadAccess(
533 chNum, static_cast<uint8_t>(operation), static_cast<uint8_t>(userId),
534 payloadAccess));
535}
536
537/** @brief implements the get user payload access command
538 * This command returns information about user payload enable settings
539 * that were set using the 'Set User Payload Access' Command.
540 *
541 * @param ctx - IPMI context pointer (for channel)
542 * @param channel - channel number
543 * @param reserved1 - skip 4 bits
544 * @param userId - user id
545 * @param reserved2 - skip 2 bits
546 *
547 * @returns IPMI completion code plus response data
548 * - stdPayload0ipmiReserved - IPMI payload (reserved).
549 * - stdPayload1SOL - SOL payload
550 * - stdPayload2
551 * - stdPayload3
552 * - stdPayload4
553 * - stdPayload5
554 * - stdPayload6
555 * - stdPayload7
556
557 * - stdPayloadEnables2Reserved - Reserved.
558
559 * - oemPayload0
560 * - oemPayload1
561 * - oemPayload2
562 * - oemPayload3
563 * - oemPayload4
564 * - oemPayload5
565 * - oemPayload6
566 * - oemPayload7
567
568 * - oemPayloadEnables2Reserved - Reserved
569 */
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -0500570ipmi::RspType<bool, // stdPayload0ipmiReserved
571 bool, // stdPayload1SOL
572 bool, // stdPayload2
573 bool, // stdPayload3
574 bool, // stdPayload4
575 bool, // stdPayload5
576 bool, // stdPayload6
577 bool, // stdPayload7
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000578
579 uint8_t, // stdPayloadEnables2Reserved
580
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -0500581 bool, // oemPayload0
582 bool, // oemPayload1
583 bool, // oemPayload2
584 bool, // oemPayload3
585 bool, // oemPayload4
586 bool, // oemPayload5
587 bool, // oemPayload6
588 bool, // oemPayload7
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000589
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -0500590 uint8_t // oemPayloadEnables2Reserved
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000591 >
592 ipmiGetUserPayloadAccess(ipmi::Context::ptr ctx,
593
594 uint4_t channel, uint4_t reserved1,
595
596 uint6_t userId, uint2_t reserved2)
597{
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -0500598 uint8_t chNum = convertCurrentChannelNum(static_cast<uint8_t>(channel),
599 ctx->channel);
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000600
601 if (reserved1 || reserved2 || !isValidChannel(chNum))
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000602 {
603 return ipmi::responseInvalidFieldRequest();
604 }
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000605 if (getChannelSessionSupport(chNum) == EChannelSessSupported::none)
606 {
607 return ipmi::response(ccActionNotSupportedForChannel);
608 }
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000609 if (!ipmiUserIsValidUserId(static_cast<uint8_t>(userId)))
610 {
611 return ipmi::responseParmOutOfRange();
612 }
613
614 ipmi::Cc retStatus;
615 PayloadAccess payloadAccess = {};
616 retStatus = ipmiUserGetUserPayloadAccess(
617 chNum, static_cast<uint8_t>(userId), payloadAccess);
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000618 if (retStatus != ccSuccess)
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000619 {
620 return ipmi::response(retStatus);
621 }
622 constexpr uint8_t res8bits = 0;
623 return ipmi::responseSuccess(payloadAccess.stdPayloadEnables1.test(0),
624 payloadAccess.stdPayloadEnables1.test(1),
625 payloadAccess.stdPayloadEnables1.test(2),
626 payloadAccess.stdPayloadEnables1.test(3),
627 payloadAccess.stdPayloadEnables1.test(4),
628 payloadAccess.stdPayloadEnables1.test(5),
629 payloadAccess.stdPayloadEnables1.test(6),
630 payloadAccess.stdPayloadEnables1.test(7),
631
632 res8bits,
633
634 payloadAccess.oemPayloadEnables1.test(0),
635 payloadAccess.oemPayloadEnables1.test(1),
636 payloadAccess.oemPayloadEnables1.test(2),
637 payloadAccess.oemPayloadEnables1.test(3),
638 payloadAccess.oemPayloadEnables1.test(4),
639 payloadAccess.oemPayloadEnables1.test(5),
640 payloadAccess.oemPayloadEnables1.test(6),
641 payloadAccess.oemPayloadEnables1.test(7),
642
643 res8bits);
644}
645
William A. Kennington III343d0612018-12-10 15:56:24 -0800646void registerUserIpmiFunctions() __attribute__((constructor));
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530647void registerUserIpmiFunctions()
648{
Richard Marian Thomaiyar0be80bd2020-01-10 12:20:16 +0530649 post_work([]() { ipmiUserInit(); });
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530650 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
651 ipmi::app::cmdSetUserAccessCommand,
652 ipmi::Privilege::Admin, ipmiSetUserAccess);
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530653
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530654 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
655 ipmi::app::cmdGetUserAccessCommand,
ankita prasadbd604762023-01-18 10:56:43 +0000656 ipmi::Privilege::Admin, ipmiGetUserAccess);
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530657
Vernon Mauery3c89de12021-08-05 11:08:23 -0700658 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
659 ipmi::app::cmdGetUserNameCommand,
ankita prasadbd604762023-01-18 10:56:43 +0000660 ipmi::Privilege::Admin, ipmiGetUserName);
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530661
Vernon Maueryac30b392021-08-05 11:08:23 -0700662 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
663 ipmi::app::cmdSetUserName, ipmi::Privilege::Admin,
664 ipmiSetUserName);
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530665
Vernon Mauery7a3296d2021-08-05 11:08:23 -0700666 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
667 ipmi::app::cmdSetUserPasswordCommand,
668 ipmi::Privilege::Admin, ipmiSetUserPassword);
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530669
smritic46f6cd2019-03-20 14:09:41 +0530670 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
671 ipmi::app::cmdGetChannelAuthCapabilities,
672 ipmi::Privilege::Callback,
673 ipmiGetChannelAuthenticationCapabilities);
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000674
675 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
676 ipmi::app::cmdSetUserPayloadAccess,
677 ipmi::Privilege::Admin, ipmiSetUserPayloadAccess);
678
679 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
680 ipmi::app::cmdGetUserPayloadAccess,
681 ipmi::Privilege::Operator, ipmiGetUserPayloadAccess);
682
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530683 return;
684}
685} // namespace ipmi