blob: 390d30526380a667942a45860f5c5f57d7667efa [file] [log] [blame]
Tom Josephf0ca5132016-08-09 08:16:12 -05001#pragma once
2
3#include <chrono>
4#include <exception>
5#include <list>
6#include <memory>
7#include <string>
8#include <vector>
9
10#include "auth_algo.hpp"
11#include "endian.hpp"
12#include "socket_channel.hpp"
13
14namespace session
15{
16
17using namespace std::chrono_literals;
18using SessionID = uint32_t;
19
20enum class Privilege : uint8_t
21{
22 HIGHEST_MATCHING,
23 CALLBACK,
24 USER,
25 OPERATOR,
26 ADMIN,
27 OEM,
28};
29
30enum class State
31{
32 INACTIVE, // Session is not in use
33 SETUP_IN_PROGRESS, // Session Setup Sequence is progressing
34 ACTIVE, // Session is active
35 TEAR_DOWN_IN_PROGRESS,// When Closing Session
36};
37
38// Seconds of inactivity allowed during session setup stage
39constexpr auto SESSION_SETUP_TIMEOUT = 5s;
40// Seconds of inactivity allowed when session is active
41constexpr auto SESSION_INACTIVITY_TIMEOUT = 60s;
42
43/*
44 * @struct SequenceNumbers Session Sequence Numbers
45 *
46 * IPMI v2.0 RMCP+ Session Sequence Numbers are used for rejecting packets that
47 * may have been duplicated by the network or intentionally replayed. There are
48 * two sets of Session SequenceNumbers for a given session.One set of inbound
49 * and outbound sequence numbers is used for authenticated (signed) packets,
50 * and the other set is used for unauthenticated packets.
51 *
52 * The individual Session Sequence Numbers is are initialized to zero whenever
53 * a session is created and incremented by one at the start of outbound
54 * processing for a given packet (i.e. the first transmitted packet has a ‘1’
55 * as the sequence number, not 0). Session Sequence numbers are incremented for
56 * every packet that is transmitted by a given sender, regardless of whether
57 * the payload for the packet is a ‘retry’ or not.
58 */
59struct SequenceNumbers
60{
61 auto get(bool inbound = true) const
62 {
63 return inbound ? in : out;
64 }
65
66 void set(uint32_t seqNumber, bool inbound = true)
67 {
68 inbound ? (in = seqNumber) : (out = seqNumber);
69 }
70
71 auto increment()
72 {
73 return ++out;
74 }
75
76 private:
77 uint32_t in;
78 uint32_t out;
79};
80/*
81 * @class Session
82 *
83 * Encapsulates the data related to an IPMI Session
84 *
85 * Authenticated IPMI communication to the BMC is accomplished by establishing
86 * a session. Once established, a session is identified by a Session ID. The
87 * Session ID may be thought of as a handle that identifies a connection between
88 * a given remote user and the BMC. The specification supports having multiple
89 * active sessions established with the BMC. It is recommended that a BMC
90 * implementation support at least four simultaneous sessions
91 */
92class Session
93{
94 public:
95
96 Session() = default;
97 ~Session() = default;
98 Session(const Session&) = delete;
99 Session& operator=(const Session&) = delete;
100 Session(Session&&) = default;
101 Session& operator=(Session&&) = default;
102
103 /*
104 * @brief Session Constructor
105 *
106 * This is issued by the Session Manager when a session is started for
107 * the Open SessionRequest command
108 *
109 * @param[in] inRemoteConsoleSessID - Remote Console Session ID
110 * @param[in] priv - Privilege Level requested in the Command
111 */
112 Session(SessionID inRemoteConsoleSessID, Privilege priv):
113 curPrivLevel(priv),
114 bmcSessionID(std::rand()),
115 remoteConsoleSessionID(inRemoteConsoleSessID) {}
116
117 auto getBMCSessionID() const
118 {
119 return bmcSessionID;
120 }
121
122 auto getRCSessionID() const
123 {
124 return remoteConsoleSessionID;
125 }
126
127 auto getAuthAlgo() const
128 {
129 if(authAlgoInterface)
130 {
131 return authAlgoInterface.get();
132 }
133 else
134 {
135 throw std::runtime_error("Authentication Algorithm Empty");
136 }
137 }
138
139 void setAuthAlgo(std::unique_ptr<cipher::rakp_auth::Interface>&&
140 inAuthAlgo)
141 {
142 authAlgoInterface = std::move(inAuthAlgo);
143 }
144
145 void updateLastTransactionTime()
146 {
147 lastTime = std::chrono::steady_clock::now();
148 }
149
150 /*
151 * @brief Session Active Status
152 *
153 * Session Active status is decided upon the Session State and the last
154 * transaction time is compared against the session inactivity timeout.
155 *
156 */
157 bool isSessionActive();
158
159 /*
160 * @brief Session's Current Privilege Level
161 */
162 Privilege curPrivLevel;
163
164 /*
165 * @brief Session's Maximum Privilege Level
166 */
167 Privilege maxPrivLevel = Privilege::CALLBACK;
168
169 SequenceNumbers sequenceNums; // Session Sequence Numbers
170 State state = State::INACTIVE; // Session State
171 std::vector<char> userName; // User Name
172
173 private:
174
175 SessionID bmcSessionID = 0; //BMC Session ID
176 SessionID remoteConsoleSessionID = 0; //Remote Console Session ID
177
178 // Authentication Algorithm Interface for the Session
179 std::unique_ptr<cipher::rakp_auth::Interface> authAlgoInterface;
180
181 // Last Transaction Time
182 decltype(std::chrono::steady_clock::now()) lastTime;
183};
184
185} // namespace session