blob: 7b0222110f9e494eba2336ce66a86b9c2f849bbd [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>
12#include <list>
13#include <memory>
14#include <string>
Richard Marian Thomaiyar992e53c2019-03-03 13:30:46 +053015#include <user_channel/channel_layer.hpp>
16#include <user_channel/user_layer.hpp>
Tom Josephf0ca5132016-08-09 08:16:12 -050017#include <vector>
18
Tom Josephf0ca5132016-08-09 08:16:12 -050019namespace session
20{
21
22using namespace std::chrono_literals;
23using SessionID = uint32_t;
24
25enum class Privilege : uint8_t
26{
27 HIGHEST_MATCHING,
28 CALLBACK,
29 USER,
30 OPERATOR,
31 ADMIN,
32 OEM,
33};
34
35enum class State
36{
Vernon Mauery9e801a22018-10-12 13:20:49 -070037 INACTIVE, // Session is not in use
38 SETUP_IN_PROGRESS, // Session Setup Sequence is progressing
39 ACTIVE, // Session is active
40 TEAR_DOWN_IN_PROGRESS, // When Closing Session
Tom Josephf0ca5132016-08-09 08:16:12 -050041};
42
43// Seconds of inactivity allowed during session setup stage
44constexpr auto SESSION_SETUP_TIMEOUT = 5s;
45// Seconds of inactivity allowed when session is active
46constexpr auto SESSION_INACTIVITY_TIMEOUT = 60s;
47
Richard Marian Thomaiyar127748a2018-09-06 07:08:51 +053048// Mask to get only the privilege from requested maximum privlege (RAKP message
49// 1)
50constexpr uint8_t reqMaxPrivMask = 0xF;
51
Tom Joseph3563f8f2017-05-08 15:42:54 +053052/**
Tom Josephf0ca5132016-08-09 08:16:12 -050053 * @struct SequenceNumbers Session Sequence Numbers
54 *
55 * IPMI v2.0 RMCP+ Session Sequence Numbers are used for rejecting packets that
56 * may have been duplicated by the network or intentionally replayed. There are
57 * two sets of Session SequenceNumbers for a given session.One set of inbound
58 * and outbound sequence numbers is used for authenticated (signed) packets,
59 * and the other set is used for unauthenticated packets.
60 *
61 * The individual Session Sequence Numbers is are initialized to zero whenever
62 * a session is created and incremented by one at the start of outbound
63 * processing for a given packet (i.e. the first transmitted packet has a ‘1’
64 * as the sequence number, not 0). Session Sequence numbers are incremented for
65 * every packet that is transmitted by a given sender, regardless of whether
66 * the payload for the packet is a ‘retry’ or not.
67 */
68struct SequenceNumbers
69{
Vernon Mauery9e801a22018-10-12 13:20:49 -070070 auto get(bool inbound = true) const
71 {
72 return inbound ? in : out;
73 }
Tom Josephf0ca5132016-08-09 08:16:12 -050074
Vernon Mauery9e801a22018-10-12 13:20:49 -070075 void set(uint32_t seqNumber, bool inbound = true)
76 {
77 inbound ? (in = seqNumber) : (out = seqNumber);
78 }
Tom Josephf0ca5132016-08-09 08:16:12 -050079
Vernon Mauery9e801a22018-10-12 13:20:49 -070080 auto increment()
81 {
82 return ++out;
83 }
Tom Josephf0ca5132016-08-09 08:16:12 -050084
Vernon Mauery9e801a22018-10-12 13:20:49 -070085 private:
86 uint32_t in = 0;
87 uint32_t out = 0;
Tom Josephf0ca5132016-08-09 08:16:12 -050088};
Tom Joseph3563f8f2017-05-08 15:42:54 +053089/**
Tom Josephf0ca5132016-08-09 08:16:12 -050090 * @class Session
91 *
92 * Encapsulates the data related to an IPMI Session
93 *
94 * Authenticated IPMI communication to the BMC is accomplished by establishing
95 * a session. Once established, a session is identified by a Session ID. The
96 * Session ID may be thought of as a handle that identifies a connection between
97 * a given remote user and the BMC. The specification supports having multiple
98 * active sessions established with the BMC. It is recommended that a BMC
99 * implementation support at least four simultaneous sessions
100 */
101class Session
102{
Vernon Mauery9e801a22018-10-12 13:20:49 -0700103 public:
104 Session() = default;
105 ~Session() = default;
106 Session(const Session&) = delete;
107 Session& operator=(const Session&) = delete;
108 Session(Session&&) = default;
109 Session& operator=(Session&&) = default;
Tom Josephf0ca5132016-08-09 08:16:12 -0500110
Vernon Mauery9e801a22018-10-12 13:20:49 -0700111 /**
112 * @brief Session Constructor
113 *
114 * This is issued by the Session Manager when a session is started for
115 * the Open SessionRequest command
116 *
117 * @param[in] inRemoteConsoleSessID - Remote Console Session ID
118 * @param[in] priv - Privilege Level requested in the Command
119 */
120 Session(SessionID inRemoteConsoleSessID, Privilege priv) :
Tom Joseph4021b1f2019-02-12 10:10:12 +0530121 reqMaxPrivLevel(priv), bmcSessionID(crypto::prng::rand()),
Vernon Mauery9e801a22018-10-12 13:20:49 -0700122 remoteConsoleSessionID(inRemoteConsoleSessID)
123 {
124 }
Tom Josephf0ca5132016-08-09 08:16:12 -0500125
Vernon Mauery9e801a22018-10-12 13:20:49 -0700126 auto getBMCSessionID() const
127 {
128 return bmcSessionID;
129 }
Tom Josephf0ca5132016-08-09 08:16:12 -0500130
Vernon Mauery9e801a22018-10-12 13:20:49 -0700131 auto getRCSessionID() const
132 {
133 return remoteConsoleSessionID;
134 }
135
136 auto getAuthAlgo() const
137 {
138 if (authAlgoInterface)
Tom Josephf0ca5132016-08-09 08:16:12 -0500139 {
Vernon Mauery9e801a22018-10-12 13:20:49 -0700140 return authAlgoInterface.get();
Tom Josephf0ca5132016-08-09 08:16:12 -0500141 }
Vernon Mauery9e801a22018-10-12 13:20:49 -0700142 else
Tom Josephf0ca5132016-08-09 08:16:12 -0500143 {
Vernon Mauery9e801a22018-10-12 13:20:49 -0700144 throw std::runtime_error("Authentication Algorithm Empty");
Tom Josephf0ca5132016-08-09 08:16:12 -0500145 }
Vernon Mauery9e801a22018-10-12 13:20:49 -0700146 }
Tom Josephf0ca5132016-08-09 08:16:12 -0500147
Vernon Mauery9e801a22018-10-12 13:20:49 -0700148 void setAuthAlgo(std::unique_ptr<cipher::rakp_auth::Interface>&& inAuthAlgo)
149 {
150 authAlgoInterface = std::move(inAuthAlgo);
151 }
152
153 /**
154 * @brief Get Session's Integrity Algorithm
155 *
156 * @return pointer to the integrity algorithm
157 */
158 auto getIntegrityAlgo() const
159 {
160 if (integrityAlgoInterface)
Tom Josephf0ca5132016-08-09 08:16:12 -0500161 {
Vernon Mauery9e801a22018-10-12 13:20:49 -0700162 return integrityAlgoInterface.get();
Tom Josephf0ca5132016-08-09 08:16:12 -0500163 }
Vernon Mauery9e801a22018-10-12 13:20:49 -0700164 else
Tom Josephf0ca5132016-08-09 08:16:12 -0500165 {
Vernon Mauery9e801a22018-10-12 13:20:49 -0700166 throw std::runtime_error("Integrity Algorithm Empty");
Tom Josephf0ca5132016-08-09 08:16:12 -0500167 }
Vernon Mauery9e801a22018-10-12 13:20:49 -0700168 }
Tom Josephf0ca5132016-08-09 08:16:12 -0500169
Vernon Mauery9e801a22018-10-12 13:20:49 -0700170 /**
171 * @brief Set Session's Integrity Algorithm
172 *
173 * @param[in] integrityAlgo - unique pointer to integrity algorithm
174 * instance
175 */
176 void setIntegrityAlgo(
177 std::unique_ptr<cipher::integrity::Interface>&& integrityAlgo)
178 {
179 integrityAlgoInterface = std::move(integrityAlgo);
180 }
181
182 /** @brief Check if integrity algorithm is enabled for this session.
183 *
184 * @return true if integrity algorithm is enabled else false.
185 */
186 auto isIntegrityAlgoEnabled()
187 {
188 return integrityAlgoInterface ? true : false;
189 }
190
191 /**
192 * @brief Get Session's Confidentiality Algorithm
193 *
194 * @return pointer to the confidentiality algorithm
195 */
196 auto getCryptAlgo() const
197 {
198 if (cryptAlgoInterface)
Tom Joseph638d0662017-01-10 16:02:07 +0530199 {
Vernon Mauery9e801a22018-10-12 13:20:49 -0700200 return cryptAlgoInterface.get();
Tom Joseph638d0662017-01-10 16:02:07 +0530201 }
Vernon Mauery9e801a22018-10-12 13:20:49 -0700202 else
Tom Joseph638d0662017-01-10 16:02:07 +0530203 {
Vernon Mauery9e801a22018-10-12 13:20:49 -0700204 throw std::runtime_error("Confidentiality Algorithm Empty");
Tom Joseph638d0662017-01-10 16:02:07 +0530205 }
Vernon Mauery9e801a22018-10-12 13:20:49 -0700206 }
Tom Joseph638d0662017-01-10 16:02:07 +0530207
Vernon Mauery9e801a22018-10-12 13:20:49 -0700208 /**
209 * @brief Set Session's Confidentiality Algorithm
210 *
211 * @param[in] confAlgo - unique pointer to confidentiality algorithm
212 * instance
213 */
214 void setCryptAlgo(std::unique_ptr<cipher::crypt::Interface>&& cryptAlgo)
215 {
216 cryptAlgoInterface = std::move(cryptAlgo);
217 }
Tom Josephd8c78612017-03-31 10:17:30 +0530218
Vernon Mauery9e801a22018-10-12 13:20:49 -0700219 /** @brief Check if confidentiality algorithm is enabled for this
220 * session.
221 *
222 * @return true if confidentiality algorithm is enabled else false.
223 */
224 auto isCryptAlgoEnabled()
225 {
226 return cryptAlgoInterface ? true : false;
227 }
Tom Joseph491dbd02017-01-24 18:20:41 +0530228
Vernon Mauery9e801a22018-10-12 13:20:49 -0700229 void updateLastTransactionTime()
230 {
231 lastTime = std::chrono::steady_clock::now();
232 }
Tom Joseph491dbd02017-01-24 18:20:41 +0530233
Vernon Mauery9e801a22018-10-12 13:20:49 -0700234 /**
235 * @brief Session Active Status
236 *
237 * Session Active status is decided upon the Session State and the last
238 * transaction time is compared against the session inactivity timeout.
239 *
240 */
Vernon Mauery07e5b282018-10-24 13:11:23 -0700241 bool isSessionActive()
242 {
243 auto currentTime = std::chrono::steady_clock::now();
244 auto elapsedSeconds = std::chrono::duration_cast<std::chrono::seconds>(
245 currentTime - lastTime);
246
247 switch (state)
248 {
249 case State::SETUP_IN_PROGRESS:
250 if (elapsedSeconds < SESSION_SETUP_TIMEOUT)
251 {
252 return true;
253 }
254 break;
255 case State::ACTIVE:
256 if (elapsedSeconds < SESSION_INACTIVITY_TIMEOUT)
257 {
258 return true;
259 }
260 break;
261 default:
262 return false;
263 }
264 return false;
265 }
Tom Joseph895df942017-03-31 10:19:40 +0530266
Vernon Mauery9e801a22018-10-12 13:20:49 -0700267 /**
268 * @brief Session's Current Privilege Level
269 */
Richard Marian Thomaiyar127748a2018-09-06 07:08:51 +0530270 Privilege curPrivLevel = Privilege::CALLBACK;
Tom Josephf0ca5132016-08-09 08:16:12 -0500271
Vernon Mauery9e801a22018-10-12 13:20:49 -0700272 /**
Richard Marian Thomaiyar127748a2018-09-06 07:08:51 +0530273 * @brief Session's Requested Maximum Privilege Level
Vernon Mauery9e801a22018-10-12 13:20:49 -0700274 */
Tom Joseph4021b1f2019-02-12 10:10:12 +0530275 Privilege reqMaxPrivLevel;
Tom Josephf0ca5132016-08-09 08:16:12 -0500276
Richard Marian Thomaiyar992e53c2019-03-03 13:30:46 +0530277 /**
278 * @brief session's user & channel access details
279 */
280 ipmi::PrivAccess sessionUserPrivAccess{};
281 ipmi::ChannelAccess sessionChannelAccess{};
282
Vernon Mauery9e801a22018-10-12 13:20:49 -0700283 SequenceNumbers sequenceNums; // Session Sequence Numbers
284 State state = State::INACTIVE; // Session State
285 std::string userName{}; // User Name
Tom Josephf0ca5132016-08-09 08:16:12 -0500286
Vernon Mauery9e801a22018-10-12 13:20:49 -0700287 /** @brief Socket channel for communicating with the remote client.*/
288 std::shared_ptr<udpsocket::Channel> channelPtr;
Richard Marian Thomaiyar127748a2018-09-06 07:08:51 +0530289 uint8_t chNum;
Tom Josephf0ca5132016-08-09 08:16:12 -0500290
Vernon Mauery9e801a22018-10-12 13:20:49 -0700291 private:
292 SessionID bmcSessionID = 0; // BMC Session ID
293 SessionID remoteConsoleSessionID = 0; // Remote Console Session ID
Tom Josephf0ca5132016-08-09 08:16:12 -0500294
Vernon Mauery9e801a22018-10-12 13:20:49 -0700295 // Authentication Algorithm Interface for the Session
296 std::unique_ptr<cipher::rakp_auth::Interface> authAlgoInterface;
Tom Josephcc27e122017-03-31 10:21:04 +0530297
Vernon Mauery9e801a22018-10-12 13:20:49 -0700298 // Integrity Algorithm Interface for the Session
299 std::unique_ptr<cipher::integrity::Interface> integrityAlgoInterface =
300 nullptr;
Tom Josephf0ca5132016-08-09 08:16:12 -0500301
Vernon Mauery9e801a22018-10-12 13:20:49 -0700302 // Confidentiality Algorithm Interface for the Session
303 std::unique_ptr<cipher::crypt::Interface> cryptAlgoInterface = nullptr;
Tom Josephf0ca5132016-08-09 08:16:12 -0500304
Vernon Mauery9e801a22018-10-12 13:20:49 -0700305 // Last Transaction Time
306 decltype(std::chrono::steady_clock::now()) lastTime;
Tom Josephf0ca5132016-08-09 08:16:12 -0500307};
308
309} // namespace session