#include "rakp12.hpp" #include #include #include #include #include "comm_module.hpp" #include "endian.hpp" #include "guid.hpp" #include "main.hpp" namespace command { std::vector RAKP12(std::vector& inPayload, const message::Handler& handler) { std::cout << ">> RAKP12\n"; std::vector outPayload(sizeof(RAKP2response)); auto request = reinterpret_cast(inPayload.data()); auto response = reinterpret_cast(outPayload.data()); // Session ID zero is reserved for Session Setup if(endian::from_ipmi(request->managedSystemSessionID) == session::SESSION_ZERO) { std::cerr << "RAKP12: BMC invalid Session ID\n"; response->rmcpStatusCode = static_cast(RAKP_ReturnCode::INVALID_SESSION_ID); return outPayload; } std::shared_ptr session; try { session = (std::get(singletonPool).getSession( endian::from_ipmi(request->managedSystemSessionID))).lock(); } catch (std::exception& e) { std::cerr << e.what() << "\n"; response->rmcpStatusCode = static_cast(RAKP_ReturnCode::INVALID_SESSION_ID); return outPayload; } // Update transaction time session->updateLastTransactionTime(); auto rcSessionID = endian::to_ipmi(session->getRCSessionID()); auto bmcSessionID = endian::to_ipmi(session->getBMCSessionID()); auto authAlgo = session->getAuthAlgo(); /* * Generate Key Authentication Code - RAKP 2 * * 1) Remote Console Session ID - 4 bytes * 2) Managed System Session ID - 4 bytes * 3) Remote Console Random Number - 16 bytes * 4) Managed System Random Number - 16 bytes * 5) Managed System GUID - 16 bytes * 6) Requested Privilege Level - 1 byte * 7) User Name Length Byte - 1 byte (0 for 'null' username) * 8) User Name - variable (absent for 'null' username) */ std::vector input; input.resize(sizeof(rcSessionID) + sizeof(bmcSessionID) + cipher::rakp_auth::REMOTE_CONSOLE_RANDOM_NUMBER_LEN + cipher::rakp_auth::BMC_RANDOM_NUMBER_LEN + BMC_GUID_LEN + sizeof(request->req_max_privilege_level) + sizeof(request->user_name_len)); auto iter = input.begin(); // Remote Console Session ID std::copy_n(reinterpret_cast(&rcSessionID), sizeof(rcSessionID), iter); std::advance(iter, sizeof(rcSessionID)); // Managed System Session ID std::copy_n(reinterpret_cast(&bmcSessionID), sizeof(bmcSessionID), iter); std::advance(iter, sizeof(bmcSessionID)); // Copy the Remote Console Random Number from the RAKP1 request to the // Authentication Algorithm std::copy_n(reinterpret_cast (request->remote_console_random_number), cipher::rakp_auth::REMOTE_CONSOLE_RANDOM_NUMBER_LEN, authAlgo->rcRandomNum.begin()); std::copy(authAlgo->rcRandomNum.begin(), authAlgo->rcRandomNum.end(), iter); std::advance(iter, cipher::rakp_auth::REMOTE_CONSOLE_RANDOM_NUMBER_LEN); // Generate the Managed System Random Number if (!RAND_bytes(input.data() + sizeof(rcSessionID) + sizeof(bmcSessionID) + cipher::rakp_auth::REMOTE_CONSOLE_RANDOM_NUMBER_LEN, cipher::rakp_auth::BMC_RANDOM_NUMBER_LEN)) { response->rmcpStatusCode = static_cast(RAKP_ReturnCode::INSUFFICIENT_RESOURCE); return outPayload; } // Copy the Managed System Random Number to the Authentication Algorithm std::copy_n(iter, cipher::rakp_auth::BMC_RANDOM_NUMBER_LEN, authAlgo->bmcRandomNum.begin()); std::advance(iter, cipher::rakp_auth::BMC_RANDOM_NUMBER_LEN); // Managed System GUID auto guid = getSystemGUID(); std::copy_n(guid.data(), guid.size(), iter); std::advance(iter, BMC_GUID_LEN); // Requested Privilege Level session->curPrivLevel = static_cast (request->req_max_privilege_level); std::copy_n(&(request->req_max_privilege_level), sizeof(request->req_max_privilege_level), iter); std::advance(iter, sizeof(request->req_max_privilege_level)); // Set Max Privilege to ADMIN session->maxPrivLevel = session::Privilege::ADMIN; // User Name Length Byte std::copy_n(&(request->user_name_len), sizeof(request->user_name_len), iter); // Generate Key Exchange Authentication Code - RAKP2 auto output = authAlgo->generateHMAC(input); response->messageTag = request->messageTag; response->rmcpStatusCode = static_cast(RAKP_ReturnCode::NO_ERROR); response->reserved = 0; response->remoteConsoleSessionID = rcSessionID ; // Copy Managed System Random Number to the Response std::copy(authAlgo->bmcRandomNum.begin(), authAlgo->bmcRandomNum.end(), response->managed_system_random_number); // Copy System GUID to the Response std::copy_n(guid.data(), guid.size(), response->managed_system_guid); // Insert the HMAC output into the payload outPayload.insert(outPayload.end(), output.begin(), output.end()); std::cout << "<< RAKP12\n"; return outPayload; } } // namespace command