blob: 338a81592a83c87ab1711403cd7cabc273e87381 [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"
7#include "socket_channel.hpp"
8
Tom Josephf0ca5132016-08-09 08:16:12 -05009#include <chrono>
10#include <exception>
11#include <list>
12#include <memory>
13#include <string>
14#include <vector>
15
Tom Josephf0ca5132016-08-09 08:16:12 -050016namespace session
17{
18
19using namespace std::chrono_literals;
20using SessionID = uint32_t;
21
22enum class Privilege : uint8_t
23{
24 HIGHEST_MATCHING,
25 CALLBACK,
26 USER,
27 OPERATOR,
28 ADMIN,
29 OEM,
30};
31
32enum class State
33{
Vernon Mauery9e801a22018-10-12 13:20:49 -070034 INACTIVE, // Session is not in use
35 SETUP_IN_PROGRESS, // Session Setup Sequence is progressing
36 ACTIVE, // Session is active
37 TEAR_DOWN_IN_PROGRESS, // When Closing Session
Tom Josephf0ca5132016-08-09 08:16:12 -050038};
39
40// Seconds of inactivity allowed during session setup stage
41constexpr auto SESSION_SETUP_TIMEOUT = 5s;
42// Seconds of inactivity allowed when session is active
43constexpr auto SESSION_INACTIVITY_TIMEOUT = 60s;
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 */
94class Session
95{
Vernon Mauery9e801a22018-10-12 13:20:49 -070096 public:
97 Session() = default;
98 ~Session() = default;
99 Session(const Session&) = delete;
100 Session& operator=(const Session&) = delete;
101 Session(Session&&) = default;
102 Session& operator=(Session&&) = default;
Tom Josephf0ca5132016-08-09 08:16:12 -0500103
Vernon Mauery9e801a22018-10-12 13:20:49 -0700104 /**
105 * @brief Session Constructor
106 *
107 * This is issued by the Session Manager when a session is started for
108 * the Open SessionRequest command
109 *
110 * @param[in] inRemoteConsoleSessID - Remote Console Session ID
111 * @param[in] priv - Privilege Level requested in the Command
112 */
113 Session(SessionID inRemoteConsoleSessID, Privilege priv) :
114 curPrivLevel(priv), bmcSessionID(std::rand()),
115 remoteConsoleSessionID(inRemoteConsoleSessID)
116 {
117 }
Tom Josephf0ca5132016-08-09 08:16:12 -0500118
Vernon Mauery9e801a22018-10-12 13:20:49 -0700119 auto getBMCSessionID() const
120 {
121 return bmcSessionID;
122 }
Tom Josephf0ca5132016-08-09 08:16:12 -0500123
Vernon Mauery9e801a22018-10-12 13:20:49 -0700124 auto getRCSessionID() const
125 {
126 return remoteConsoleSessionID;
127 }
128
129 auto getAuthAlgo() const
130 {
131 if (authAlgoInterface)
Tom Josephf0ca5132016-08-09 08:16:12 -0500132 {
Vernon Mauery9e801a22018-10-12 13:20:49 -0700133 return authAlgoInterface.get();
Tom Josephf0ca5132016-08-09 08:16:12 -0500134 }
Vernon Mauery9e801a22018-10-12 13:20:49 -0700135 else
Tom Josephf0ca5132016-08-09 08:16:12 -0500136 {
Vernon Mauery9e801a22018-10-12 13:20:49 -0700137 throw std::runtime_error("Authentication Algorithm Empty");
Tom Josephf0ca5132016-08-09 08:16:12 -0500138 }
Vernon Mauery9e801a22018-10-12 13:20:49 -0700139 }
Tom Josephf0ca5132016-08-09 08:16:12 -0500140
Vernon Mauery9e801a22018-10-12 13:20:49 -0700141 void setAuthAlgo(std::unique_ptr<cipher::rakp_auth::Interface>&& inAuthAlgo)
142 {
143 authAlgoInterface = std::move(inAuthAlgo);
144 }
145
146 /**
147 * @brief Get Session's Integrity Algorithm
148 *
149 * @return pointer to the integrity algorithm
150 */
151 auto getIntegrityAlgo() const
152 {
153 if (integrityAlgoInterface)
Tom Josephf0ca5132016-08-09 08:16:12 -0500154 {
Vernon Mauery9e801a22018-10-12 13:20:49 -0700155 return integrityAlgoInterface.get();
Tom Josephf0ca5132016-08-09 08:16:12 -0500156 }
Vernon Mauery9e801a22018-10-12 13:20:49 -0700157 else
Tom Josephf0ca5132016-08-09 08:16:12 -0500158 {
Vernon Mauery9e801a22018-10-12 13:20:49 -0700159 throw std::runtime_error("Integrity Algorithm Empty");
Tom Josephf0ca5132016-08-09 08:16:12 -0500160 }
Vernon Mauery9e801a22018-10-12 13:20:49 -0700161 }
Tom Josephf0ca5132016-08-09 08:16:12 -0500162
Vernon Mauery9e801a22018-10-12 13:20:49 -0700163 /**
164 * @brief Set Session's Integrity Algorithm
165 *
166 * @param[in] integrityAlgo - unique pointer to integrity algorithm
167 * instance
168 */
169 void setIntegrityAlgo(
170 std::unique_ptr<cipher::integrity::Interface>&& integrityAlgo)
171 {
172 integrityAlgoInterface = std::move(integrityAlgo);
173 }
174
175 /** @brief Check if integrity algorithm is enabled for this session.
176 *
177 * @return true if integrity algorithm is enabled else false.
178 */
179 auto isIntegrityAlgoEnabled()
180 {
181 return integrityAlgoInterface ? true : false;
182 }
183
184 /**
185 * @brief Get Session's Confidentiality Algorithm
186 *
187 * @return pointer to the confidentiality algorithm
188 */
189 auto getCryptAlgo() const
190 {
191 if (cryptAlgoInterface)
Tom Joseph638d0662017-01-10 16:02:07 +0530192 {
Vernon Mauery9e801a22018-10-12 13:20:49 -0700193 return cryptAlgoInterface.get();
Tom Joseph638d0662017-01-10 16:02:07 +0530194 }
Vernon Mauery9e801a22018-10-12 13:20:49 -0700195 else
Tom Joseph638d0662017-01-10 16:02:07 +0530196 {
Vernon Mauery9e801a22018-10-12 13:20:49 -0700197 throw std::runtime_error("Confidentiality Algorithm Empty");
Tom Joseph638d0662017-01-10 16:02:07 +0530198 }
Vernon Mauery9e801a22018-10-12 13:20:49 -0700199 }
Tom Joseph638d0662017-01-10 16:02:07 +0530200
Vernon Mauery9e801a22018-10-12 13:20:49 -0700201 /**
202 * @brief Set Session's Confidentiality Algorithm
203 *
204 * @param[in] confAlgo - unique pointer to confidentiality algorithm
205 * instance
206 */
207 void setCryptAlgo(std::unique_ptr<cipher::crypt::Interface>&& cryptAlgo)
208 {
209 cryptAlgoInterface = std::move(cryptAlgo);
210 }
Tom Josephd8c78612017-03-31 10:17:30 +0530211
Vernon Mauery9e801a22018-10-12 13:20:49 -0700212 /** @brief Check if confidentiality algorithm is enabled for this
213 * session.
214 *
215 * @return true if confidentiality algorithm is enabled else false.
216 */
217 auto isCryptAlgoEnabled()
218 {
219 return cryptAlgoInterface ? true : false;
220 }
Tom Joseph491dbd02017-01-24 18:20:41 +0530221
Vernon Mauery9e801a22018-10-12 13:20:49 -0700222 void updateLastTransactionTime()
223 {
224 lastTime = std::chrono::steady_clock::now();
225 }
Tom Joseph491dbd02017-01-24 18:20:41 +0530226
Vernon Mauery9e801a22018-10-12 13:20:49 -0700227 /**
228 * @brief Session Active Status
229 *
230 * Session Active status is decided upon the Session State and the last
231 * transaction time is compared against the session inactivity timeout.
232 *
233 */
234 bool isSessionActive();
Tom Joseph895df942017-03-31 10:19:40 +0530235
Vernon Mauery9e801a22018-10-12 13:20:49 -0700236 /**
237 * @brief Session's Current Privilege Level
238 */
239 Privilege curPrivLevel;
Tom Josephf0ca5132016-08-09 08:16:12 -0500240
Vernon Mauery9e801a22018-10-12 13:20:49 -0700241 /**
242 * @brief Session's Maximum Privilege Level
243 */
244 Privilege maxPrivLevel = Privilege::CALLBACK;
Tom Josephf0ca5132016-08-09 08:16:12 -0500245
Vernon Mauery9e801a22018-10-12 13:20:49 -0700246 SequenceNumbers sequenceNums; // Session Sequence Numbers
247 State state = State::INACTIVE; // Session State
248 std::string userName{}; // User Name
Tom Josephf0ca5132016-08-09 08:16:12 -0500249
Vernon Mauery9e801a22018-10-12 13:20:49 -0700250 /** @brief Socket channel for communicating with the remote client.*/
251 std::shared_ptr<udpsocket::Channel> channelPtr;
Tom Josephf0ca5132016-08-09 08:16:12 -0500252
Vernon Mauery9e801a22018-10-12 13:20:49 -0700253 private:
254 SessionID bmcSessionID = 0; // BMC Session ID
255 SessionID remoteConsoleSessionID = 0; // Remote Console Session ID
Tom Josephf0ca5132016-08-09 08:16:12 -0500256
Vernon Mauery9e801a22018-10-12 13:20:49 -0700257 // Authentication Algorithm Interface for the Session
258 std::unique_ptr<cipher::rakp_auth::Interface> authAlgoInterface;
Tom Josephcc27e122017-03-31 10:21:04 +0530259
Vernon Mauery9e801a22018-10-12 13:20:49 -0700260 // Integrity Algorithm Interface for the Session
261 std::unique_ptr<cipher::integrity::Interface> integrityAlgoInterface =
262 nullptr;
Tom Josephf0ca5132016-08-09 08:16:12 -0500263
Vernon Mauery9e801a22018-10-12 13:20:49 -0700264 // Confidentiality Algorithm Interface for the Session
265 std::unique_ptr<cipher::crypt::Interface> cryptAlgoInterface = nullptr;
Tom Josephf0ca5132016-08-09 08:16:12 -0500266
Vernon Mauery9e801a22018-10-12 13:20:49 -0700267 // Last Transaction Time
268 decltype(std::chrono::steady_clock::now()) lastTime;
Tom Josephf0ca5132016-08-09 08:16:12 -0500269};
270
271} // namespace session