1 #pragma once
2 
3 #include "main.hpp"
4 #include "session.hpp"
5 
6 #include <boost/asio/steady_timer.hpp>
7 #include <ipmid/api.hpp>
8 #include <ipmid/sessiondef.hpp>
9 
10 #include <chrono>
11 #include <map>
12 #include <memory>
13 #include <mutex>
14 #include <string>
15 
16 namespace session
17 {
18 
19 enum class RetrieveOption
20 {
21     BMC_SESSION_ID,
22     RC_SESSION_ID,
23 };
24 
25 static constexpr size_t maxSessionHandles = multiIntfaceSessionHandleMask;
26 
27 /**
28  * @class Manager
29  *
30  * Manager class acts a manager for the IPMI sessions and provides interfaces
31  * to start a session, stop a session and get reference to the session objects.
32  *
33  */
34 
35 class Manager
36 {
37   private:
38     struct Private
39     {};
40 
41   public:
42     // BMC Session ID is the key for the map
43     using SessionMap = std::map<SessionID, std::shared_ptr<Session>>;
44 
45     Manager() = delete;
Manager(std::shared_ptr<boost::asio::io_context> & io,const Private &)46     Manager(std::shared_ptr<boost::asio::io_context>& io, const Private&) :
47         io(io), timer(*io){};
48     ~Manager() = default;
49     Manager(const Manager&) = delete;
50     Manager& operator=(const Manager&) = delete;
51     Manager(Manager&&) = default;
52     Manager& operator=(Manager&&) = default;
53 
54     /**
55      * @brief Get a reference to the singleton Manager
56      *
57      * @return Manager reference
58      */
get()59     static Manager& get()
60     {
61         static std::shared_ptr<Manager> ptr = nullptr;
62         if (!ptr)
63         {
64             std::shared_ptr<boost::asio::io_context> io = getIo();
65             ptr = std::make_shared<Manager>(io, Private());
66             if (!ptr)
67             {
68                 throw std::runtime_error("failed to create session manager");
69             }
70         }
71         return *ptr;
72     }
73 
74     /**
75      * @brief Start an IPMI session
76      *
77      * @param[in] remoteConsoleSessID - Remote Console Session ID mentioned
78      *            in the Open SessionRequest Command
79      * @param[in] priv - Privilege level requested
80      * @param[in] authAlgo - Authentication Algorithm
81      * @param[in] intAlgo - Integrity Algorithm
82      * @param[in] cryptAlgo - Confidentiality Algorithm
83      *
84      * @return session handle on success and nullptr on failure
85      *
86      */
87     std::shared_ptr<Session>
88         startSession(SessionID remoteConsoleSessID, Privilege priv,
89                      cipher::rakp_auth::Algorithms authAlgo,
90                      cipher::integrity::Algorithms intAlgo,
91                      cipher::crypt::Algorithms cryptAlgo);
92 
93     /**
94      * @brief Stop IPMI Session
95      *
96      * @param[in] bmcSessionID - BMC Session ID
97      *
98      * @return true on success and failure if session ID is invalid
99      *
100      */
101     bool stopSession(SessionID bmcSessionID);
102 
103     /**
104      * @brief Get Session Handle
105      *
106      * @param[in] sessionID - Session ID
107      * @param[in] option - Select between BMC Session ID and Remote Console
108      *            Session ID, Default option is BMC Session ID
109      *
110      * @return session handle on success and nullptr on failure
111      *
112      */
113     std::shared_ptr<Session>
114         getSession(SessionID sessionID,
115                    RetrieveOption option = RetrieveOption::BMC_SESSION_ID);
116     uint8_t getActiveSessionCount() const;
117     uint8_t getSessionHandle(SessionID bmcSessionID) const;
118     uint8_t storeSessionHandle(SessionID bmcSessionID);
119     uint32_t getSessionIDbyHandle(uint8_t sessionHandle) const;
120 
121     void managerInit(const std::string& channel);
122 
123     uint8_t getNetworkInstance(void);
124 
125     /**
126      * @brief Clean Session Stale Entries
127      *
128      *  Schedules cleaning the inactive sessions entries from the Session Map
129      */
130     void scheduleSessionCleaner(const std::chrono::microseconds& grace);
131 
132   private:
133     /**
134      * @brief reclaim system resources by limiting idle sessions
135      *
136      * Limits on active, authenticated sessions are calculated independently
137      * from in-setup sessions, which are not required to be authenticated. This
138      * will prevent would-be DoS attacks by calling a bunch of Open Session
139      * requests to fill up all available sessions. Too many active sessions will
140      * trigger a shorter timeout, but is unaffected by setup session counts.
141      *
142      * For active sessions, grace time is inversely proportional to (the number
143      * of active sessions beyond max sessions per channel)^3
144      *
145      * For sessions in setup, grace time is inversely proportional to (the
146      * number of total sessions beyond max sessions per channel)^3, with a max
147      * of 3 seconds
148      */
149     void cleanStaleEntries();
150 
151     std::shared_ptr<boost::asio::io_context> io;
152     boost::asio::steady_timer timer;
153 
154     std::array<uint32_t, session::maxSessionHandles> sessionHandleMap = {0};
155 
156     /**
157      * @brief Session Manager keeps the session objects as a sorted
158      *        associative container with Session ID as the unique key
159      */
160     SessionMap sessionsMap;
161     std::unique_ptr<sdbusplus::server::manager_t> objManager = nullptr;
162     std::string chName{}; // Channel Name
163     uint8_t ipmiNetworkInstance = 0;
164     void setNetworkInstance(void);
165 };
166 
167 } // namespace session
168