summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--session.cpp33
-rw-r--r--session.hpp185
2 files changed, 218 insertions, 0 deletions
diff --git a/session.cpp b/session.cpp
new file mode 100644
index 0000000..b80f51a
--- /dev/null
+++ b/session.cpp
@@ -0,0 +1,33 @@
+#include "session.hpp"
+
+#include <ctime>
+
+#include "endian.hpp"
+
+namespace session
+{
+
+bool Session::isSessionActive()
+{
+ auto currentTime = std::chrono::steady_clock::now();
+ auto elapsedSeconds = std::chrono::duration_cast<std::chrono::seconds>
+ (currentTime - lastTime);
+
+ switch (state)
+ {
+ case State::SETUP_IN_PROGRESS:
+ if (elapsedSeconds < SESSION_SETUP_TIMEOUT)
+ {
+ return true;
+ }
+ case State::ACTIVE:
+ if (elapsedSeconds < SESSION_INACTIVITY_TIMEOUT)
+ {
+ return true;
+ }
+ default:
+ return false;
+ }
+}
+
+} // namespace session
diff --git a/session.hpp b/session.hpp
new file mode 100644
index 0000000..390d305
--- /dev/null
+++ b/session.hpp
@@ -0,0 +1,185 @@
+#pragma once
+
+#include <chrono>
+#include <exception>
+#include <list>
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "auth_algo.hpp"
+#include "endian.hpp"
+#include "socket_channel.hpp"
+
+namespace session
+{
+
+using namespace std::chrono_literals;
+using SessionID = uint32_t;
+
+enum class Privilege : uint8_t
+{
+ HIGHEST_MATCHING,
+ CALLBACK,
+ USER,
+ OPERATOR,
+ ADMIN,
+ OEM,
+};
+
+enum class State
+{
+ INACTIVE, // Session is not in use
+ SETUP_IN_PROGRESS, // Session Setup Sequence is progressing
+ ACTIVE, // Session is active
+ TEAR_DOWN_IN_PROGRESS,// When Closing Session
+};
+
+// Seconds of inactivity allowed during session setup stage
+constexpr auto SESSION_SETUP_TIMEOUT = 5s;
+// Seconds of inactivity allowed when session is active
+constexpr auto SESSION_INACTIVITY_TIMEOUT = 60s;
+
+/*
+ * @struct SequenceNumbers Session Sequence Numbers
+ *
+ * IPMI v2.0 RMCP+ Session Sequence Numbers are used for rejecting packets that
+ * may have been duplicated by the network or intentionally replayed. There are
+ * two sets of Session SequenceNumbers for a given session.One set of inbound
+ * and outbound sequence numbers is used for authenticated (signed) packets,
+ * and the other set is used for unauthenticated packets.
+ *
+ * The individual Session Sequence Numbers is are initialized to zero whenever
+ * a session is created and incremented by one at the start of outbound
+ * processing for a given packet (i.e. the first transmitted packet has a ‘1’
+ * as the sequence number, not 0). Session Sequence numbers are incremented for
+ * every packet that is transmitted by a given sender, regardless of whether
+ * the payload for the packet is a ‘retry’ or not.
+ */
+struct SequenceNumbers
+{
+ auto get(bool inbound = true) const
+ {
+ return inbound ? in : out;
+ }
+
+ void set(uint32_t seqNumber, bool inbound = true)
+ {
+ inbound ? (in = seqNumber) : (out = seqNumber);
+ }
+
+ auto increment()
+ {
+ return ++out;
+ }
+
+ private:
+ uint32_t in;
+ uint32_t out;
+};
+/*
+ * @class Session
+ *
+ * Encapsulates the data related to an IPMI Session
+ *
+ * Authenticated IPMI communication to the BMC is accomplished by establishing
+ * a session. Once established, a session is identified by a Session ID. The
+ * Session ID may be thought of as a handle that identifies a connection between
+ * a given remote user and the BMC. The specification supports having multiple
+ * active sessions established with the BMC. It is recommended that a BMC
+ * implementation support at least four simultaneous sessions
+ */
+class Session
+{
+ public:
+
+ Session() = default;
+ ~Session() = default;
+ Session(const Session&) = delete;
+ Session& operator=(const Session&) = delete;
+ Session(Session&&) = default;
+ Session& operator=(Session&&) = default;
+
+ /*
+ * @brief Session Constructor
+ *
+ * This is issued by the Session Manager when a session is started for
+ * the Open SessionRequest command
+ *
+ * @param[in] inRemoteConsoleSessID - Remote Console Session ID
+ * @param[in] priv - Privilege Level requested in the Command
+ */
+ Session(SessionID inRemoteConsoleSessID, Privilege priv):
+ curPrivLevel(priv),
+ bmcSessionID(std::rand()),
+ remoteConsoleSessionID(inRemoteConsoleSessID) {}
+
+ auto getBMCSessionID() const
+ {
+ return bmcSessionID;
+ }
+
+ auto getRCSessionID() const
+ {
+ return remoteConsoleSessionID;
+ }
+
+ auto getAuthAlgo() const
+ {
+ if(authAlgoInterface)
+ {
+ return authAlgoInterface.get();
+ }
+ else
+ {
+ throw std::runtime_error("Authentication Algorithm Empty");
+ }
+ }
+
+ void setAuthAlgo(std::unique_ptr<cipher::rakp_auth::Interface>&&
+ inAuthAlgo)
+ {
+ authAlgoInterface = std::move(inAuthAlgo);
+ }
+
+ void updateLastTransactionTime()
+ {
+ lastTime = std::chrono::steady_clock::now();
+ }
+
+ /*
+ * @brief Session Active Status
+ *
+ * Session Active status is decided upon the Session State and the last
+ * transaction time is compared against the session inactivity timeout.
+ *
+ */
+ bool isSessionActive();
+
+ /*
+ * @brief Session's Current Privilege Level
+ */
+ Privilege curPrivLevel;
+
+ /*
+ * @brief Session's Maximum Privilege Level
+ */
+ Privilege maxPrivLevel = Privilege::CALLBACK;
+
+ SequenceNumbers sequenceNums; // Session Sequence Numbers
+ State state = State::INACTIVE; // Session State
+ std::vector<char> userName; // User Name
+
+ private:
+
+ SessionID bmcSessionID = 0; //BMC Session ID
+ SessionID remoteConsoleSessionID = 0; //Remote Console Session ID
+
+ // Authentication Algorithm Interface for the Session
+ std::unique_ptr<cipher::rakp_auth::Interface> authAlgoInterface;
+
+ // Last Transaction Time
+ decltype(std::chrono::steady_clock::now()) lastTime;
+};
+
+} // namespace session
OpenPOWER on IntegriCloud