blob: 7af38b9fb2ed34fe1b31841f1555c5477db9a67e [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
Ayushi Smriti29b9f312021-09-24 12:29:23 +0530284 static constexpr uint2_t opDisableUser = 0x00;
285 static constexpr uint2_t opEnableUser = 0x01;
286 static constexpr uint2_t opSetPassword = 0x02;
287 static constexpr uint2_t opTestPassword = 0x03;
288
289 // If set / test password operation then password size has to be 16 or 20
290 // bytes based on the password size bit
291 if (((operation == opSetPassword) || (operation == opTestPassword)) &&
292 ((pwLen20 && (userPassword.size() != maxIpmi20PasswordSize)) ||
293 (!pwLen20 && (userPassword.size() != maxIpmi15PasswordSize))))
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530294 {
295 log<level::DEBUG>("Invalid Length");
Vernon Mauery7a3296d2021-08-05 11:08:23 -0700296 return ipmi::responseReqDataLenInvalid();
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530297 }
Ayushi Smriti29b9f312021-09-24 12:29:23 +0530298
Vernon Mauery7a3296d2021-08-05 11:08:23 -0700299 size_t passwordLength = userPassword.size();
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530300
Vernon Mauery7a3296d2021-08-05 11:08:23 -0700301 uint8_t userId = static_cast<uint8_t>(id);
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530302 std::string userName;
Vernon Mauery7a3296d2021-08-05 11:08:23 -0700303 if (ipmiUserGetUserName(userId, userName) != ccSuccess)
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530304 {
Vernon Mauery7a3296d2021-08-05 11:08:23 -0700305 log<level::DEBUG>("User Name not found", entry("USER-ID=%d", userId));
306 return ipmi::responseParmOutOfRange();
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530307 }
Vernon Mauery7a3296d2021-08-05 11:08:23 -0700308
Vernon Mauery7a3296d2021-08-05 11:08:23 -0700309 if (operation == opSetPassword)
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530310 {
Vernon Mauery7a3296d2021-08-05 11:08:23 -0700311 // turn the non-nul terminated SecureBuffer into a SecureString
312 SecureString password(
313 reinterpret_cast<const char*>(userPassword.data()), passwordLength);
314 ipmi::Cc res = ipmiUserSetUserPassword(userId, password.data());
315 return ipmi::response(res);
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530316 }
Vernon Mauery7a3296d2021-08-05 11:08:23 -0700317 else if (operation == opEnableUser || operation == opDisableUser)
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530318 {
Vernon Mauery7a3296d2021-08-05 11:08:23 -0700319 ipmi::Cc res =
320 ipmiUserUpdateEnabledState(userId, static_cast<bool>(operation));
321 return ipmi::response(res);
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530322 }
Vernon Mauery7a3296d2021-08-05 11:08:23 -0700323 else if (operation == opTestPassword)
Richard Marian Thomaiyar282e79b2018-11-13 19:00:58 +0530324 {
Vernon Mauery1e22a0f2021-07-30 13:36:54 -0700325 SecureString password = ipmiUserGetPassword(userName);
Vernon Mauery7a3296d2021-08-05 11:08:23 -0700326 // extend with zeros, if needed
327 if (password.size() < passwordLength)
328 {
329 password.resize(passwordLength, '\0');
330 }
Vernon Mauery1e22a0f2021-07-30 13:36:54 -0700331 SecureString testPassword(
Vernon Mauery7a3296d2021-08-05 11:08:23 -0700332 reinterpret_cast<const char*>(userPassword.data()), passwordLength);
Vernon Mauery1e22a0f2021-07-30 13:36:54 -0700333 // constant time string compare: always compare exactly as many bytes
334 // as the length of the input, resizing the actual password to match,
335 // maintaining a knowledge if the sizes differed originally
336 static const std::array<char, maxIpmi20PasswordSize> empty = {'\0'};
337 size_t cmpLen = testPassword.size();
338 bool pwLenDiffers = password.size() != cmpLen;
339 const char* cmpPassword = nullptr;
340 if (pwLenDiffers)
341 {
342 cmpPassword = empty.data();
343 }
344 else
345 {
346 cmpPassword = password.data();
347 }
348 bool pwBad = CRYPTO_memcmp(cmpPassword, testPassword.data(), cmpLen);
349 pwBad |= pwLenDiffers;
350 if (pwBad)
Richard Marian Thomaiyar282e79b2018-11-13 19:00:58 +0530351 {
352 log<level::DEBUG>("Test password failed",
Vernon Mauery7a3296d2021-08-05 11:08:23 -0700353 entry("USER-ID=%d", userId));
354 static constexpr ipmi::Cc ipmiCCPasswdFailMismatch = 0x80;
355 return ipmi::response(ipmiCCPasswdFailMismatch);
Richard Marian Thomaiyar282e79b2018-11-13 19:00:58 +0530356 }
Vernon Mauery7a3296d2021-08-05 11:08:23 -0700357 return ipmi::responseSuccess();
Richard Marian Thomaiyar282e79b2018-11-13 19:00:58 +0530358 }
Vernon Mauery7a3296d2021-08-05 11:08:23 -0700359 return ipmi::responseInvalidFieldRequest();
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530360}
361
smritic46f6cd2019-03-20 14:09:41 +0530362/** @brief implements the get channel authentication command
363 * @param ctx - IPMI context pointer (for channel)
364 * @param extData - get IPMI 2.0 extended data
365 * @param reserved1 - skip 3 bits
366 * @param chNum - channel number to get info about
367 * @param reserved2 - skip 4 bits
368 * @param privLevel - requested privilege level
369
370 * @returns ipmi completion code plus response data
371 * - channel number
372 * - rmcpAuthTypes - RMCP auth types (IPMI 1.5)
373 * - reserved1
374 * - extDataSupport - true for IPMI 2.0 extensions
375 * - anonymousLogin - true for anonymous login enabled
376 * - nullUsers - true for null user names enabled
377 * - nonNullUsers - true for non-null usernames enabled
378 * - userAuth - false for user authentication enabled
379 * - perMessageAuth - false for per message authentication enabled
380 * - KGStatus - true for Kg required for authentication
381 * - reserved2
382 * - rmcp - RMCP (IPMI 1.5) connection support
383 * - rmcpp - RMCP+ (IPMI 2.0) connection support
384 * - reserved3
385 * - oemID - OEM IANA of any OEM auth support
386 * - oemAuxillary - OEM data for auth
387 */
388ipmi::RspType<uint8_t, // channel number
389 uint6_t, // rmcpAuthTypes
390 bool, // reserved1
391 bool, // extDataSupport
392 bool, // anonymousLogin
393 bool, // nullUsers
394 bool, // nonNullUsers
395 bool, // userAuth
396 bool, // perMessageAuth
397 bool, // KGStatus
398 uint2_t, // reserved2
399 bool, // rmcp
400 bool, // rmcpp
401 uint6_t, // reserved3
402 uint24_t, // oemID
403 uint8_t // oemAuxillary
404 >
405 ipmiGetChannelAuthenticationCapabilities(ipmi::Context::ptr ctx,
406 uint4_t chNum, uint3_t reserved1,
407 bool extData, uint4_t privLevel,
408 uint4_t reserved2)
409{
smritic46f6cd2019-03-20 14:09:41 +0530410 uint8_t channel =
Vernon Mauery5ed39592019-05-14 09:16:53 -0700411 convertCurrentChannelNum(static_cast<uint8_t>(chNum), ctx->channel);
smritic46f6cd2019-03-20 14:09:41 +0530412
413 if (reserved1 || reserved2 || !isValidChannel(channel) ||
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000414 !isValidPrivLimit(static_cast<uint8_t>(privLevel)))
smritic46f6cd2019-03-20 14:09:41 +0530415 {
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000416 log<level::DEBUG>(
417 "Get channel auth capabilities - Invalid field in request");
418 return ipmi::responseInvalidFieldRequest();
419 }
420
421 if (getChannelSessionSupport(channel) == EChannelSessSupported::none)
422 {
423 log<level::DEBUG>(
424 "Get channel auth capabilities - No support on channel");
425 return ipmi::response(ccActionNotSupportedForChannel);
smritic46f6cd2019-03-20 14:09:41 +0530426 }
427
428 constexpr bool extDataSupport = true; // true for IPMI 2.0 extensions
429 constexpr bool reserved3 = false;
430 constexpr uint6_t rmcpAuthTypes = 0; // IPMI 1.5 auth types - not supported
431 constexpr uint2_t reserved4 = 0;
432 constexpr bool KGStatus = false; // Not supporting now.
433 constexpr bool perMessageAuth = false; // Per message auth - enabled
434 constexpr bool userAuth = false; // User authentication - enabled
435 constexpr bool nullUsers = false; // Null user names - not supported
436 constexpr bool anonymousLogin = false; // Anonymous login - not supported
437 constexpr uint6_t reserved5 = 0;
438 constexpr bool rmcpp = true; // IPMI 2.0 - supported
439 constexpr bool rmcp = false; // IPMI 1.5 - not supported
440 constexpr uint24_t oemID = 0;
441 constexpr uint8_t oemAuxillary = 0;
442
443 bool nonNullUsers = 0;
444 uint8_t maxChUsers = 0, enabledUsers = 0, fixedUsers = 0;
445 ipmi::ipmiUserGetAllCounts(maxChUsers, enabledUsers, fixedUsers);
446 nonNullUsers = enabledUsers > 0;
447
448 return ipmi::responseSuccess(
449 channel, rmcpAuthTypes, reserved3, extDataSupport, anonymousLogin,
450 nullUsers, nonNullUsers, userAuth, perMessageAuth, KGStatus, reserved4,
451 rmcp, rmcpp, reserved5, oemID, oemAuxillary);
452}
453
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000454/** @brief implements the set user payload access command.
455 * @param ctx - IPMI context pointer (for channel)
456 * @param channel - channel number (4 bits)
457 * @param reserved1 - skip 4 bits
458 * @param userId - user id (6 bits)
459 * @param operation - access ENABLE /DISABLE. (2 bits)
460 * @param stdPayload0 - IPMI - reserved. (1 bit)
461 * @param stdPayload1 - SOL. (1 bit)
462 * @param stdPayload2 - (1 bit)
463 * @param stdPayload3 - (1 bit)
464 * @param stdPayload4 - (1 bit)
465 * @param stdPayload5 - (1 bit)
466 * @param stdPayload6 - (1 bit)
467 * @param stdPayload7 - (1 bit)
468 * @param stdPayloadEnables2Reserved - (8 bits)
469 * @param oemPayload0 - (1 bit)
470 * @param oemPayload1 - (1 bit)
471 * @param oemPayload2 - (1 bit)
472 * @param oemPayload3 - (1 bit)
473 * @param oemPayload4 - (1 bit)
474 * @param oemPayload5 - (1 bit)
475 * @param oemPayload6 - (1 bit)
476 * @param oemPayload7 - (1 bit)
477 * @param oemPayloadEnables2Reserved - (8 bits)
478 *
479 * @returns IPMI completion code
480 */
481ipmi::RspType<> ipmiSetUserPayloadAccess(
482 ipmi::Context::ptr ctx,
483
484 uint4_t channel, uint4_t reserved,
485
486 uint6_t userId, uint2_t operation,
487
488 bool stdPayload0ipmiReserved, bool stdPayload1SOL, bool stdPayload2,
489 bool stdPayload3, bool stdPayload4, bool stdPayload5, bool stdPayload6,
490 bool stdPayload7,
491
492 uint8_t stdPayloadEnables2Reserved,
493
494 bool oemPayload0, bool oemPayload1, bool oemPayload2, bool oemPayload3,
495 bool oemPayload4, bool oemPayload5, bool oemPayload6, bool oemPayload7,
496
497 uint8_t oemPayloadEnables2Reserved)
498{
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000499 auto chNum =
500 convertCurrentChannelNum(static_cast<uint8_t>(channel), ctx->channel);
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000501 // Validate the reserved args. Only SOL payload is supported as on date.
502 if (reserved || stdPayload0ipmiReserved || stdPayload2 || stdPayload3 ||
503 stdPayload4 || stdPayload5 || stdPayload6 || stdPayload7 ||
504 oemPayload0 || oemPayload1 || oemPayload2 || oemPayload3 ||
505 oemPayload4 || oemPayload5 || oemPayload6 || oemPayload7 ||
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000506 stdPayloadEnables2Reserved || oemPayloadEnables2Reserved ||
507 !isValidChannel(chNum))
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000508 {
509 return ipmi::responseInvalidFieldRequest();
510 }
511
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000512 if ((operation != enableOperation && operation != disableOperation))
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000513 {
514 return ipmi::responseInvalidFieldRequest();
515 }
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000516 if (getChannelSessionSupport(chNum) == EChannelSessSupported::none)
517 {
518 return ipmi::response(ccActionNotSupportedForChannel);
519 }
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000520 if (!ipmiUserIsValidUserId(static_cast<uint8_t>(userId)))
521 {
522 return ipmi::responseParmOutOfRange();
523 }
524
525 PayloadAccess payloadAccess = {0};
526 payloadAccess.stdPayloadEnables1[1] = stdPayload1SOL;
527
528 return ipmi::response(ipmiUserSetUserPayloadAccess(
529 chNum, static_cast<uint8_t>(operation), static_cast<uint8_t>(userId),
530 payloadAccess));
531}
532
533/** @brief implements the get user payload access command
534 * This command returns information about user payload enable settings
535 * that were set using the 'Set User Payload Access' Command.
536 *
537 * @param ctx - IPMI context pointer (for channel)
538 * @param channel - channel number
539 * @param reserved1 - skip 4 bits
540 * @param userId - user id
541 * @param reserved2 - skip 2 bits
542 *
543 * @returns IPMI completion code plus response data
544 * - stdPayload0ipmiReserved - IPMI payload (reserved).
545 * - stdPayload1SOL - SOL payload
546 * - stdPayload2
547 * - stdPayload3
548 * - stdPayload4
549 * - stdPayload5
550 * - stdPayload6
551 * - stdPayload7
552
553 * - stdPayloadEnables2Reserved - Reserved.
554
555 * - oemPayload0
556 * - oemPayload1
557 * - oemPayload2
558 * - oemPayload3
559 * - oemPayload4
560 * - oemPayload5
561 * - oemPayload6
562 * - oemPayload7
563
564 * - oemPayloadEnables2Reserved - Reserved
565 */
566ipmi::RspType<bool, // stdPayload0ipmiReserved
567 bool, // stdPayload1SOL
568 bool, // stdPayload2
569 bool, // stdPayload3
570 bool, // stdPayload4
571 bool, // stdPayload5
572 bool, // stdPayload6
573 bool, // stdPayload7
574
575 uint8_t, // stdPayloadEnables2Reserved
576
577 bool, // oemPayload0
578 bool, // oemPayload1
579 bool, // oemPayload2
580 bool, // oemPayload3
581 bool, // oemPayload4
582 bool, // oemPayload5
583 bool, // oemPayload6
584 bool, // oemPayload7
585
586 uint8_t // oemPayloadEnables2Reserved
587 >
588 ipmiGetUserPayloadAccess(ipmi::Context::ptr ctx,
589
590 uint4_t channel, uint4_t reserved1,
591
592 uint6_t userId, uint2_t reserved2)
593{
594 uint8_t chNum =
595 convertCurrentChannelNum(static_cast<uint8_t>(channel), ctx->channel);
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000596
597 if (reserved1 || reserved2 || !isValidChannel(chNum))
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000598 {
599 return ipmi::responseInvalidFieldRequest();
600 }
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000601 if (getChannelSessionSupport(chNum) == EChannelSessSupported::none)
602 {
603 return ipmi::response(ccActionNotSupportedForChannel);
604 }
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000605 if (!ipmiUserIsValidUserId(static_cast<uint8_t>(userId)))
606 {
607 return ipmi::responseParmOutOfRange();
608 }
609
610 ipmi::Cc retStatus;
611 PayloadAccess payloadAccess = {};
612 retStatus = ipmiUserGetUserPayloadAccess(
613 chNum, static_cast<uint8_t>(userId), payloadAccess);
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000614 if (retStatus != ccSuccess)
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000615 {
616 return ipmi::response(retStatus);
617 }
618 constexpr uint8_t res8bits = 0;
619 return ipmi::responseSuccess(payloadAccess.stdPayloadEnables1.test(0),
620 payloadAccess.stdPayloadEnables1.test(1),
621 payloadAccess.stdPayloadEnables1.test(2),
622 payloadAccess.stdPayloadEnables1.test(3),
623 payloadAccess.stdPayloadEnables1.test(4),
624 payloadAccess.stdPayloadEnables1.test(5),
625 payloadAccess.stdPayloadEnables1.test(6),
626 payloadAccess.stdPayloadEnables1.test(7),
627
628 res8bits,
629
630 payloadAccess.oemPayloadEnables1.test(0),
631 payloadAccess.oemPayloadEnables1.test(1),
632 payloadAccess.oemPayloadEnables1.test(2),
633 payloadAccess.oemPayloadEnables1.test(3),
634 payloadAccess.oemPayloadEnables1.test(4),
635 payloadAccess.oemPayloadEnables1.test(5),
636 payloadAccess.oemPayloadEnables1.test(6),
637 payloadAccess.oemPayloadEnables1.test(7),
638
639 res8bits);
640}
641
William A. Kennington III343d0612018-12-10 15:56:24 -0800642void registerUserIpmiFunctions() __attribute__((constructor));
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530643void registerUserIpmiFunctions()
644{
Richard Marian Thomaiyar0be80bd2020-01-10 12:20:16 +0530645 post_work([]() { ipmiUserInit(); });
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530646 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
647 ipmi::app::cmdSetUserAccessCommand,
648 ipmi::Privilege::Admin, ipmiSetUserAccess);
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530649
Richard Marian Thomaiyar5b2535f2019-04-04 22:01:36 +0530650 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
651 ipmi::app::cmdGetUserAccessCommand,
652 ipmi::Privilege::Operator, ipmiGetUserAccess);
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530653
Vernon Mauery3c89de12021-08-05 11:08:23 -0700654 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
655 ipmi::app::cmdGetUserNameCommand,
656 ipmi::Privilege::Operator, ipmiGetUserName);
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530657
Vernon Maueryac30b392021-08-05 11:08:23 -0700658 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
659 ipmi::app::cmdSetUserName, ipmi::Privilege::Admin,
660 ipmiSetUserName);
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530661
Vernon Mauery7a3296d2021-08-05 11:08:23 -0700662 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
663 ipmi::app::cmdSetUserPasswordCommand,
664 ipmi::Privilege::Admin, ipmiSetUserPassword);
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530665
smritic46f6cd2019-03-20 14:09:41 +0530666 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
667 ipmi::app::cmdGetChannelAuthCapabilities,
668 ipmi::Privilege::Callback,
669 ipmiGetChannelAuthenticationCapabilities);
Saravanan Palanisamy77381f12019-05-15 22:33:17 +0000670
671 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
672 ipmi::app::cmdSetUserPayloadAccess,
673 ipmi::Privilege::Admin, ipmiSetUserPayloadAccess);
674
675 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
676 ipmi::app::cmdGetUserPayloadAccess,
677 ipmi::Privilege::Operator, ipmiGetUserPayloadAccess);
678
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530679 return;
680}
681} // namespace ipmi