blob: a01d4785f6653b1b7c60f0103e2a8cb5ae358eb3 [file] [log] [blame]
Tom Josephf0ca5132016-08-09 08:16:12 -05001#pragma once
2
Vernon Mauery9e801a22018-10-12 13:20:49 -07003#include "auth_algo.hpp"
4#include "crypt_algo.hpp"
5#include "endian.hpp"
6#include "integrity_algo.hpp"
Vernon Mauery8977d122018-10-24 14:02:16 -07007#include "prng.hpp"
Vernon Mauery9e801a22018-10-12 13:20:49 -07008#include "socket_channel.hpp"
9
Tom Josephf0ca5132016-08-09 08:16:12 -050010#include <chrono>
11#include <exception>
Suryakanth Sekarf8a34fc2019-06-12 20:59:18 +053012#include <ipmid/api.hpp>
13#include <ipmid/sessiondef.hpp>
Tom Josephf0ca5132016-08-09 08:16:12 -050014#include <list>
15#include <memory>
Suryakanth Sekarf8a34fc2019-06-12 20:59:18 +053016#include <sdbusplus/bus.hpp>
17#include <sdbusplus/server/object.hpp>
Tom Josephf0ca5132016-08-09 08:16:12 -050018#include <string>
Suryakanth Sekarf8a34fc2019-06-12 20:59:18 +053019#include <unordered_map>
Richard Marian Thomaiyar992e53c2019-03-03 13:30:46 +053020#include <user_channel/channel_layer.hpp>
21#include <user_channel/user_layer.hpp>
Tom Josephf0ca5132016-08-09 08:16:12 -050022#include <vector>
Suryakanth Sekarf8a34fc2019-06-12 20:59:18 +053023#include <xyz/openbmc_project/Ipmi/SessionInfo/server.hpp>
Tom Josephf0ca5132016-08-09 08:16:12 -050024
Tom Josephf0ca5132016-08-09 08:16:12 -050025namespace session
26{
27
28using namespace std::chrono_literals;
29using SessionID = uint32_t;
30
31enum class Privilege : uint8_t
32{
33 HIGHEST_MATCHING,
34 CALLBACK,
35 USER,
36 OPERATOR,
37 ADMIN,
38 OEM,
39};
40
Richard Marian Thomaiyar127748a2018-09-06 07:08:51 +053041// Mask to get only the privilege from requested maximum privlege (RAKP message
42// 1)
43constexpr uint8_t reqMaxPrivMask = 0xF;
44
Tom Joseph3563f8f2017-05-08 15:42:54 +053045/**
Tom Josephf0ca5132016-08-09 08:16:12 -050046 * @struct SequenceNumbers Session Sequence Numbers
47 *
48 * IPMI v2.0 RMCP+ Session Sequence Numbers are used for rejecting packets that
49 * may have been duplicated by the network or intentionally replayed. There are
50 * two sets of Session SequenceNumbers for a given session.One set of inbound
51 * and outbound sequence numbers is used for authenticated (signed) packets,
52 * and the other set is used for unauthenticated packets.
53 *
54 * The individual Session Sequence Numbers is are initialized to zero whenever
55 * a session is created and incremented by one at the start of outbound
56 * processing for a given packet (i.e. the first transmitted packet has a ‘1’
57 * as the sequence number, not 0). Session Sequence numbers are incremented for
58 * every packet that is transmitted by a given sender, regardless of whether
59 * the payload for the packet is a ‘retry’ or not.
60 */
61struct SequenceNumbers
62{
Vernon Mauery9e801a22018-10-12 13:20:49 -070063 auto get(bool inbound = true) const
64 {
65 return inbound ? in : out;
66 }
Tom Josephf0ca5132016-08-09 08:16:12 -050067
Vernon Mauery9e801a22018-10-12 13:20:49 -070068 void set(uint32_t seqNumber, bool inbound = true)
69 {
70 inbound ? (in = seqNumber) : (out = seqNumber);
71 }
Tom Josephf0ca5132016-08-09 08:16:12 -050072
Vernon Mauery9e801a22018-10-12 13:20:49 -070073 auto increment()
74 {
75 return ++out;
76 }
Tom Josephf0ca5132016-08-09 08:16:12 -050077
Vernon Mauery9e801a22018-10-12 13:20:49 -070078 private:
79 uint32_t in = 0;
80 uint32_t out = 0;
Tom Josephf0ca5132016-08-09 08:16:12 -050081};
Tom Joseph3563f8f2017-05-08 15:42:54 +053082/**
Tom Josephf0ca5132016-08-09 08:16:12 -050083 * @class Session
84 *
85 * Encapsulates the data related to an IPMI Session
86 *
87 * Authenticated IPMI communication to the BMC is accomplished by establishing
88 * a session. Once established, a session is identified by a Session ID. The
89 * Session ID may be thought of as a handle that identifies a connection between
90 * a given remote user and the BMC. The specification supports having multiple
91 * active sessions established with the BMC. It is recommended that a BMC
92 * implementation support at least four simultaneous sessions
93 */
Suryakanth Sekarf8a34fc2019-06-12 20:59:18 +053094
95using SessionIface = sdbusplus::server::object::object<
96 sdbusplus::xyz::openbmc_project::Ipmi::server::SessionInfo>;
97
98class Session : public SessionIface
Tom Josephf0ca5132016-08-09 08:16:12 -050099{
Vernon Mauery9e801a22018-10-12 13:20:49 -0700100 public:
101 Session() = default;
102 ~Session() = default;
103 Session(const Session&) = delete;
104 Session& operator=(const Session&) = delete;
105 Session(Session&&) = default;
106 Session& operator=(Session&&) = default;
Tom Josephf0ca5132016-08-09 08:16:12 -0500107
Vernon Mauery9e801a22018-10-12 13:20:49 -0700108 /**
109 * @brief Session Constructor
110 *
111 * This is issued by the Session Manager when a session is started for
112 * the Open SessionRequest command
113 *
114 * @param[in] inRemoteConsoleSessID - Remote Console Session ID
115 * @param[in] priv - Privilege Level requested in the Command
116 */
Suryakanth Sekarf8a34fc2019-06-12 20:59:18 +0530117 Session(sdbusplus::bus::bus& bus, const char* path,
118 SessionID inRemoteConsoleSessID, SessionID BMCSessionID,
119 char priv) :
120 SessionIface(bus, path)
Vernon Mauery9e801a22018-10-12 13:20:49 -0700121 {
Suryakanth Sekarf8a34fc2019-06-12 20:59:18 +0530122 reqMaxPrivLevel = static_cast<session::Privilege>(priv);
123 bmcSessionID = BMCSessionID;
124 remoteConsoleSessionID = inRemoteConsoleSessID;
Vernon Mauery9e801a22018-10-12 13:20:49 -0700125 }
Tom Josephf0ca5132016-08-09 08:16:12 -0500126
Vernon Mauery9e801a22018-10-12 13:20:49 -0700127 auto getBMCSessionID() const
128 {
129 return bmcSessionID;
130 }
Tom Josephf0ca5132016-08-09 08:16:12 -0500131
Vernon Mauery9e801a22018-10-12 13:20:49 -0700132 auto getRCSessionID() const
133 {
134 return remoteConsoleSessionID;
135 }
136
137 auto getAuthAlgo() const
138 {
139 if (authAlgoInterface)
Tom Josephf0ca5132016-08-09 08:16:12 -0500140 {
Vernon Mauery9e801a22018-10-12 13:20:49 -0700141 return authAlgoInterface.get();
Tom Josephf0ca5132016-08-09 08:16:12 -0500142 }
Vernon Mauery9e801a22018-10-12 13:20:49 -0700143 else
Tom Josephf0ca5132016-08-09 08:16:12 -0500144 {
Vernon Mauery9e801a22018-10-12 13:20:49 -0700145 throw std::runtime_error("Authentication Algorithm Empty");
Tom Josephf0ca5132016-08-09 08:16:12 -0500146 }
Vernon Mauery9e801a22018-10-12 13:20:49 -0700147 }
Tom Josephf0ca5132016-08-09 08:16:12 -0500148
Vernon Mauery9e801a22018-10-12 13:20:49 -0700149 void setAuthAlgo(std::unique_ptr<cipher::rakp_auth::Interface>&& inAuthAlgo)
150 {
151 authAlgoInterface = std::move(inAuthAlgo);
152 }
153
154 /**
155 * @brief Get Session's Integrity Algorithm
156 *
157 * @return pointer to the integrity algorithm
158 */
159 auto getIntegrityAlgo() const
160 {
161 if (integrityAlgoInterface)
Tom Josephf0ca5132016-08-09 08:16:12 -0500162 {
Vernon Mauery9e801a22018-10-12 13:20:49 -0700163 return integrityAlgoInterface.get();
Tom Josephf0ca5132016-08-09 08:16:12 -0500164 }
Vernon Mauery9e801a22018-10-12 13:20:49 -0700165 else
Tom Josephf0ca5132016-08-09 08:16:12 -0500166 {
Vernon Mauery9e801a22018-10-12 13:20:49 -0700167 throw std::runtime_error("Integrity Algorithm Empty");
Tom Josephf0ca5132016-08-09 08:16:12 -0500168 }
Vernon Mauery9e801a22018-10-12 13:20:49 -0700169 }
Tom Josephf0ca5132016-08-09 08:16:12 -0500170
Vernon Mauery9e801a22018-10-12 13:20:49 -0700171 /**
172 * @brief Set Session's Integrity Algorithm
173 *
174 * @param[in] integrityAlgo - unique pointer to integrity algorithm
175 * instance
176 */
177 void setIntegrityAlgo(
178 std::unique_ptr<cipher::integrity::Interface>&& integrityAlgo)
179 {
180 integrityAlgoInterface = std::move(integrityAlgo);
181 }
182
183 /** @brief Check if integrity algorithm is enabled for this session.
184 *
185 * @return true if integrity algorithm is enabled else false.
186 */
187 auto isIntegrityAlgoEnabled()
188 {
189 return integrityAlgoInterface ? true : false;
190 }
191
192 /**
193 * @brief Get Session's Confidentiality Algorithm
194 *
195 * @return pointer to the confidentiality algorithm
196 */
197 auto getCryptAlgo() const
198 {
199 if (cryptAlgoInterface)
Tom Joseph638d0662017-01-10 16:02:07 +0530200 {
Vernon Mauery9e801a22018-10-12 13:20:49 -0700201 return cryptAlgoInterface.get();
Tom Joseph638d0662017-01-10 16:02:07 +0530202 }
Vernon Mauery9e801a22018-10-12 13:20:49 -0700203 else
Tom Joseph638d0662017-01-10 16:02:07 +0530204 {
Vernon Mauery9e801a22018-10-12 13:20:49 -0700205 throw std::runtime_error("Confidentiality Algorithm Empty");
Tom Joseph638d0662017-01-10 16:02:07 +0530206 }
Vernon Mauery9e801a22018-10-12 13:20:49 -0700207 }
Tom Joseph638d0662017-01-10 16:02:07 +0530208
Vernon Mauery9e801a22018-10-12 13:20:49 -0700209 /**
210 * @brief Set Session's Confidentiality Algorithm
211 *
212 * @param[in] confAlgo - unique pointer to confidentiality algorithm
213 * instance
214 */
215 void setCryptAlgo(std::unique_ptr<cipher::crypt::Interface>&& cryptAlgo)
216 {
217 cryptAlgoInterface = std::move(cryptAlgo);
218 }
Tom Josephd8c78612017-03-31 10:17:30 +0530219
Vernon Mauery9e801a22018-10-12 13:20:49 -0700220 /** @brief Check if confidentiality algorithm is enabled for this
221 * session.
222 *
223 * @return true if confidentiality algorithm is enabled else false.
224 */
225 auto isCryptAlgoEnabled()
226 {
227 return cryptAlgoInterface ? true : false;
228 }
Tom Joseph491dbd02017-01-24 18:20:41 +0530229
Vernon Mauery9e801a22018-10-12 13:20:49 -0700230 void updateLastTransactionTime()
231 {
232 lastTime = std::chrono::steady_clock::now();
233 }
Tom Joseph491dbd02017-01-24 18:20:41 +0530234
Vernon Mauery9e801a22018-10-12 13:20:49 -0700235 /**
236 * @brief Session Active Status
237 *
238 * Session Active status is decided upon the Session State and the last
239 * transaction time is compared against the session inactivity timeout.
240 *
Vernon Maueryecc8efa2021-06-12 12:52:23 -0700241 * @param[in] activeGrace - microseconds of idle time for active sessions
242 * @param[in] setupGrace - microseconds of idle time for sessions in setup
243 *
Vernon Mauery9e801a22018-10-12 13:20:49 -0700244 */
Vernon Maueryecc8efa2021-06-12 12:52:23 -0700245 bool isSessionActive(const std::chrono::microseconds& activeGrace,
246 const std::chrono::microseconds& setupGrace)
Vernon Mauery07e5b282018-10-24 13:11:23 -0700247 {
248 auto currentTime = std::chrono::steady_clock::now();
Vernon Maueryecc8efa2021-06-12 12:52:23 -0700249 auto elapsedMicros =
250 std::chrono::duration_cast<std::chrono::microseconds>(currentTime -
251 lastTime);
Vernon Mauery07e5b282018-10-24 13:11:23 -0700252
Vernon Maueryecc8efa2021-06-12 12:52:23 -0700253 State state = static_cast<session::State>(this->state());
Suryakanth Sekarf8a34fc2019-06-12 20:59:18 +0530254
Vernon Mauery07e5b282018-10-24 13:11:23 -0700255 switch (state)
256 {
Vernon Maueryecc8efa2021-06-12 12:52:23 -0700257 case State::active:
258 if (elapsedMicros < activeGrace)
Vernon Mauery07e5b282018-10-24 13:11:23 -0700259 {
260 return true;
261 }
262 break;
Vernon Maueryecc8efa2021-06-12 12:52:23 -0700263 case State::setupInProgress:
264 if (elapsedMicros < setupGrace)
Vernon Mauery07e5b282018-10-24 13:11:23 -0700265 {
266 return true;
267 }
268 break;
Vernon Maueryecc8efa2021-06-12 12:52:23 -0700269 case State::tearDownInProgress:
270 break;
Vernon Mauery07e5b282018-10-24 13:11:23 -0700271 default:
Vernon Maueryecc8efa2021-06-12 12:52:23 -0700272 break;
Vernon Mauery07e5b282018-10-24 13:11:23 -0700273 }
274 return false;
275 }
Tom Joseph895df942017-03-31 10:19:40 +0530276
Vernon Mauery9e801a22018-10-12 13:20:49 -0700277 /**
Richard Marian Thomaiyar127748a2018-09-06 07:08:51 +0530278 * @brief Session's Requested Maximum Privilege Level
Vernon Mauery9e801a22018-10-12 13:20:49 -0700279 */
Tom Joseph4021b1f2019-02-12 10:10:12 +0530280 Privilege reqMaxPrivLevel;
Tom Josephf0ca5132016-08-09 08:16:12 -0500281
Richard Marian Thomaiyar992e53c2019-03-03 13:30:46 +0530282 /**
283 * @brief session's user & channel access details
284 */
285 ipmi::PrivAccess sessionUserPrivAccess{};
286 ipmi::ChannelAccess sessionChannelAccess{};
287
Suryakanth Sekarf8a34fc2019-06-12 20:59:18 +0530288 SequenceNumbers sequenceNums; // Session Sequence Numbers
289 std::string userName{}; // User Name
Tom Josephf0ca5132016-08-09 08:16:12 -0500290
Vernon Mauery9e801a22018-10-12 13:20:49 -0700291 /** @brief Socket channel for communicating with the remote client.*/
292 std::shared_ptr<udpsocket::Channel> channelPtr;
Tom Josephf0ca5132016-08-09 08:16:12 -0500293
Vernon Mauery9e801a22018-10-12 13:20:49 -0700294 private:
295 SessionID bmcSessionID = 0; // BMC Session ID
296 SessionID remoteConsoleSessionID = 0; // Remote Console Session ID
Tom Josephf0ca5132016-08-09 08:16:12 -0500297
Vernon Mauery9e801a22018-10-12 13:20:49 -0700298 // Authentication Algorithm Interface for the Session
299 std::unique_ptr<cipher::rakp_auth::Interface> authAlgoInterface;
Tom Josephcc27e122017-03-31 10:21:04 +0530300
Vernon Mauery9e801a22018-10-12 13:20:49 -0700301 // Integrity Algorithm Interface for the Session
302 std::unique_ptr<cipher::integrity::Interface> integrityAlgoInterface =
303 nullptr;
Tom Josephf0ca5132016-08-09 08:16:12 -0500304
Vernon Mauery9e801a22018-10-12 13:20:49 -0700305 // Confidentiality Algorithm Interface for the Session
306 std::unique_ptr<cipher::crypt::Interface> cryptAlgoInterface = nullptr;
Tom Josephf0ca5132016-08-09 08:16:12 -0500307
Vernon Mauery9e801a22018-10-12 13:20:49 -0700308 // Last Transaction Time
309 decltype(std::chrono::steady_clock::now()) lastTime;
Tom Josephf0ca5132016-08-09 08:16:12 -0500310};
311
312} // namespace session