This commit is contained in:
Aria 2025-03-21 22:23:30 +11:00
commit 9c94d113d3
Signed by untrusted user who does not match committer: aria
GPG key ID: 19AB7AA462B8AB3B
10260 changed files with 1237388 additions and 0 deletions

View file

@ -0,0 +1,23 @@
INCLUDE_DIRECTORIES (
${STAR_CORE_INCLUDES}
${STAR_GAME_INCLUDES}
${STAR_AUTHENTICATION_INCLUDES}
)
SET (authentication_server_HEADERS
StarAuthenticationDatabase.hpp
StarAuthenticationServer.hpp
StarDatabaseConnector.hpp
)
SET (authentication_server_SOURCES
StarAuthenticationDatabase.cpp
StarAuthenticationServer.cpp
StarDatabaseConnector.cpp
)
ADD_EXECUTABLE (starbound_auth_keygen keygen.cpp ${authentication_server_SOURCES} ${authentication_server_HEADERS})
ADD_EXECUTABLE (starbound_auth main.cpp ${authentication_server_SOURCES} ${authentication_server_HEADERS})
TARGET_LINK_LIBRARIES (starbound_auth_keygen star_authentication ${PQ_LIBRARY})
TARGET_LINK_LIBRARIES (starbound_auth star_authentication ${PQ_LIBRARY})

View file

@ -0,0 +1,160 @@
#include "StarAuthenticationDatabase.hpp"
#include "StarLogging.hpp"
#include "StarDatabaseConnector.hpp"
#include "StarAlgorithm.hpp"
using namespace std;
namespace Star {
namespace Auth {
AuthenticationDatabase::AuthenticationDatabase(String const& connectionString) :m_connectionString(connectionString) {
/*
if (validateUser("none"))
throw StarException("User none should not exist");
if (!validateUser("test"))
throw StarException("User test should exist");
if (!validateUserAndPassword("test", preHashPassword("test", "test")))
throw StarException("User test should be able to login using the password 'test'");
if (validateUserAndPassword("test", preHashPassword("test", "none")))
throw StarException("User test should not be able to login using the password 'none'");
*/
}
AuthenticationDatabase::~AuthenticationDatabase() {
}
bool AuthenticationDatabase::validateUser(String const& username) {
DatabaseConnector conn(m_connectionString);
{
conn.exec("BEGIN");
bool success = false;
auto transactionScope = finally([&]() {
if (success)
conn.exec("END");
else
conn.exec("ROLLBACK");
});
auto rows = conn.fetch("SELECT id_user, active FROM users WHERE username=$1", { username });
bool result;
if (rows.size() == 0) {
result = false;
}
else
{
starAssert(rows.size() == 1);
auto row = rows[0];
result = row.get("active").toBool();
}
conn.exec("INSERT INTO validations (username, timestamp, result) VALUES ($1, $2, $3)", { username, Thread::currentTime(), result });
success = true;
return result;
}
}
bool AuthenticationDatabase::validateUserAndPassword(String const& username, String const& password) {
DatabaseConnector conn(m_connectionString);
{
conn.exec("BEGIN");
bool success = false;
auto transactionScope = finally([&]() {
if (success)
conn.exec("END");
else
conn.exec("ROLLBACK");
});
auto rows = conn.fetch("SELECT id_user, active, salt, rounds, hash FROM users WHERE username=$1", { username });
bool result;
if (rows.size() == 0) {
result = false;
}
else {
starAssert(rows.size() == 1);
auto row = rows[0];
result = row.get("active").toBool();
if (result)
result = bcryptValidate(password, row.get("salt").toString(), row.get("hash").toString(), row.get("rounds").toInt());
}
conn.exec("INSERT INTO validations (username, timestamp, result) VALUES ($1, $2, $3)", { username, Thread::currentTime(), result });
success = true;
return result;
}
}
bool AuthenticationDatabase::setUserRecord(String const& username, String const& passwordPreHashed, bool active) {
DatabaseConnector conn(m_connectionString);
{
conn.exec("BEGIN");
bool success = false;
auto transactionScope = finally([&]() {
if (success)
conn.exec("END");
else
conn.exec("ROLLBACK");
});
String salt = generateKey();
int rounds = 0;
String hash = bcrypt(passwordPreHashed, salt, rounds);
auto rows = conn.fetch("SELECT id_user FROM users WHERE username=$1", { username });
if (rows.size() == 1) {
conn.exec("UPDATE users SET salt=$2, rounds=$3, hash=$4, active=$5 WHERE id_user=$1", { rows[0].get("id_user"), salt, rounds, hash, active });
}
else {
long since = Thread::currentTime();
conn.exec("INSERT INTO users (username, salt, rounds, hash, since, active) VALUES ($1, $2, $3, $4, $5, $6)", { username, salt, rounds, hash, since, active });
}
success = true;
return true;
}
}
bool AuthenticationDatabase::activateUserRecord(String const& username, bool active) {
DatabaseConnector conn(m_connectionString);
{
conn.exec("BEGIN");
bool success = false;
bool result;
auto transactionScope = finally([&]() {
if (success)
conn.exec("END");
else
conn.exec("ROLLBACK");
});
auto rows = conn.fetch("SELECT id_user FROM users WHERE username=$1", { username });
if (rows.size() == 1) {
conn.exec("UPDATE users SET active=$2 WHERE id_user=$1", { rows[0].get("id_user"), active });
result = true;
}
else
result = false;
success = true;
return result;
}
}
int AuthenticationDatabase::usersCount() {
DatabaseConnector conn(m_connectionString);
{
conn.exec("BEGIN");
int result = 0;
bool success = false;
auto transactionScope = finally([&]() {
if (success)
conn.exec("END");
else
conn.exec("ROLLBACK");
});
auto rows = conn.fetch("SELECT count(*) as amount FROM users", {});
if (rows.size() == 1) {
success = true;
result = rows[0].get("amount").toInt();
}
return result;
}
}
}
}

View file

@ -0,0 +1,34 @@
#ifndef _STAR_AUTHENTICATOR_DATABASE_HPP_
#define _STAR_AUTHENTICATOR_DATABASE_HPP_
#include "StarAuthenticationKey.hpp"
#include "StarAuthenticationService.hpp"
#include "StarException.hpp"
#include "StarVariant.hpp"
#include "StarRoot.hpp"
#include "StarTcp.hpp"
#include "StarThread.hpp"
namespace Star {
namespace Auth {
class AuthenticationDatabase: public Database {
public:
AuthenticationDatabase(String const& connectionString);
~AuthenticationDatabase();
virtual bool validateUser(String const& username) override;
virtual bool validateUserAndPassword(String const& username, String const& passwordPreHashed) override;
virtual bool setUserRecord(String const& username, String const& passwordPreHashed, bool active) override;
virtual bool activateUserRecord(String const& username, bool active) override;
virtual int usersCount() override;
private:
String m_connectionString;
};
}
}
#endif

View file

@ -0,0 +1,325 @@
#include "StarAuthenticationServer.hpp"
#include "StarLogging.hpp"
#include "StarAuthenticationDatabase.hpp"
namespace Star {
namespace Auth {
AuthenticationConnectionHandler::AuthenticationConnectionHandler(TcpSocketPtr socket, AuthenticationServer* server)
: Thread("AuthenticationConnectionHandler") {
Logger::info("Connection thread constructor.");
m_socket = socket;
m_server = server;
m_stop = false;
m_closed = false;
}
AuthenticationConnectionHandler::~AuthenticationConnectionHandler() {
Logger::info("Connection thread destructor.");
}
void AuthenticationConnectionHandler::stop() {
m_stop = true;
try {
m_socket->close();
} catch (StarException const&) {
// bartwe: I'm a jerk, close is not supposed to be called during calls to the socket on other threads, not really seeing a good way to interrupt that i care about enough to implement atm.
}
}
bool AuthenticationConnectionHandler::isClosed() {
return m_closed;
}
void AuthenticationConnectionHandler::writeResponse(String const& response) {
String body = "HTTP/1.1 200 OK\r\nConnection: close\r\nContent-Type: text/html; charset=UTF-8\r\nCache-Control: no-cache, no-store\r\n\r\n" + response + "\r\n\r\n";
m_socket->write(body.utf8Ptr(), body.utf8Size());
Logger::info("Connection thread write response.");
}
void AuthenticationConnectionHandler::writeErrorResponse(String const& response) {
String body = "HTTP/1.1 200 OK\r\nConnection: close\r\nContent-Type: text/html; charset=UTF-8\r\nCache-Control: no-cache, no-store\r\n\r\n" + response + "\r\n\r\n";
m_socket->write(body.utf8Ptr(), body.utf8Size());
Logger::info("Connection thread write error.");
}
void AuthenticationConnectionHandler::run() {
Logger::info("Connection thread.run");
try {
m_socket->setNoDelay(true);
m_socket->setSocketTimeout(ClientSocketTimeout);
int64_t deadline = Thread::currentTime() + ClientSocketTimeout;
bool headerMode = true;
Buffer buffer(BufferCapacity);
int newlineCounter = 0;
while (!m_stop && m_socket->isOpen()) {
if (Thread::currentTime() >= deadline) {
// client too slow, or a slow lorris attack
writeErrorResponse("Client too slow.");
break;
}
char c;
if (m_socket->read(&c, 1) != 1)
throw StarException("Unexpected result from socket read\n");
if (c == '\r')
continue; // hello dos
buffer.write(&c, 1);
if (buffer.pos() >= BufferCapacity) {
// request too long
writeErrorResponse("Request too long.");
break;
}
if (c == '\n')
newlineCounter++;
else
newlineCounter = 0;
if (newlineCounter == 2) {
if (headerMode) {
String header = String(buffer.ptr(), buffer.pos());
if (!header.beginsWith("POST /auth.sb HTTP/1.1\n")) {
writeErrorResponse("Page not found.");
break;
}
headerMode = false;
buffer.clear();
newlineCounter = 0;
} else {
String body = String(buffer.ptr(), buffer.pos() - 2); // remove trailing newlines, guaranteed to be there
auto message = make_shared<MessageToken>(body);
Logger::info("Connection thread.message received.");
m_server->addMessage(message);
if (!message->waitForResponse(ClientProcessingTimeout))
writeErrorResponse("Timed out.");
writeResponse(message->response());
break;
}
}
}
m_socket->flush();
}
catch (NetworkException const&) {
goto finally;
}
catch (StarException const& e) {
Logger::error("AuthenticationConnectionHandler: Exception caught: %s", e.what());
}
catch (std::exception const& e) {
Logger::error("AuthenticationConnectionHandler: Exception caught: %s", e.what());
goto finally;
}
catch (...) {
goto finally;
}
finally: {
m_closed = true;
if (m_socket->isOpen())
m_socket->close();
}
m_server->addMessage( { });
Logger::info("Connection thread.run.end");
}
AuthenticationServer::AuthenticationServer() {
m_stop = false;
String connectionString = Variant::parseJson(File::readFileString("connectionstring.config")).getString("connectionString");
DatabasePtr db = as<Database>(make_shared<AuthenticationDatabase>(connectionString));
m_service = make_shared<AuthenticationService>(db);
m_requestCount = 0;
m_getAuthKeyCounter = 0;
m_authorizeClientCounter = 0;
m_authorizeClientFailure = 0;
m_validateClientCounter = 0;
m_validateClientFailure = 0;
m_munin = make_shared<MuninNode>(Variant::parseJson(File::readFileString("authmunin.config")));
m_munin->setCallback([=]() {
MutexLocker locker(m_mainLock);
m_munin->set("sbauth", "users", db->usersCount());
m_munin->set("sbauth", "requests", m_requestCount);
m_munin->set("sbauth", "getAuthKey", m_getAuthKeyCounter);
m_munin->set("sbauth", "authorizeClient", m_authorizeClientCounter);
m_munin->set("sbauth", "authorizeClientFailure", m_authorizeClientFailure);
m_munin->set("sbauth", "validateClient", m_validateClientCounter);
m_munin->set("sbauth", "validateClientFailure", m_validateClientFailure);
});
}
AuthenticationServer::~AuthenticationServer() {}
void AuthenticationServer::acceptConnection(TcpSocketPtr socket) {
MutexLocker locker(m_mainLock);
if (m_stop) {
socket->close();
} else {
auto handler = make_shared<AuthenticationConnectionHandler>(socket, this);
m_handlers.add(handler);
handler->start();
}
}
void AuthenticationServer::run() {
TcpServer tcpServer(ListenPort);
tcpServer.setAcceptCallback(std::bind(&AuthenticationServer::acceptConnection, this, std::placeholders::_1));
Logger::info("Auth server started.");
List<AuthenticationConnectionHandlerPtr> cleanup;
while (true) {
try {
MessageTokenPtr message;
{
MutexLocker locker(m_mainLock);
if (m_stop)
break;
for (auto& handler : m_handlers) {
if (handler->isClosed())
cleanup.append(handler);
}
m_handlers.removeAll(cleanup);
if (m_messages.empty() && cleanup.empty())
m_signal.wait(m_mainLock);
if (!m_messages.empty())
message = m_messages.takeFirst();
}
cleanup.clear();
if (message) {
try {
handleMessage(message);
if (!message->hasResponse())
message->setResponse("");
}
catch (std::exception const&) {
if (!message->hasResponse())
message->setResponse("");
throw;
}
}
}
catch (std::exception const& e) {
Logger::error("AuthenticationServer exception caught: %s", e.what());
}
}
Logger::info("Finishing remaining connections.");
try {
MutexLocker locker(m_mainLock);
m_stop = true;
tcpServer.close();
} catch (std::exception const& e) {
Logger::error("AuthenticationServer exception caught cleaning up: %s", e.what());
}
{
MutexLocker locker(m_mainLock);
for (auto & message : m_messages)
message->setResponse("stopping");
m_messages.clear();
}
// locking should no longer be needed at this point
// unused to avoid deadlock scenario where the handler calls addMessage
for (auto& handler : m_handlers)
handler->stop();
m_handlers.clear();
}
void AuthenticationServer::stop() {
Logger::info("Auth server stopping.");
MutexLocker locker(m_mainLock);
m_stop = true;
m_signal.signal();
}
void AuthenticationServer::addMessage(MessageTokenPtr const& message) {
MutexLocker locker(m_mainLock);
m_requestCount++;
if (m_stop) {
if (message)
message->setResponse("stopped");
} else {
m_messages.append(message);
m_signal.signal();
}
}
void AuthenticationServer::handleMessage(MessageTokenPtr const& message) {
Variant command = Variant::parse(message->request());
if (command.getString("command") == "getAuthKey") {
m_getAuthKeyCounter++;
auto response = m_service->getCertificate();
message->setResponse(response.repr(0, true));
} else if (command.getString("command") == "authorizeClient") {
m_authorizeClientCounter++;
try {
auto response = m_service->authorizeClient(command.getMap("body"));
message->setResponse(response.repr(0, true));
}
catch (...) {
m_authorizeClientFailure++;
throw;
}
} else if (command.getString("command") == "validateClient") {
m_validateClientCounter++;
try {
auto response = m_service->validateClient(command.getMap("body"));
message->setResponse(response.repr(0, true));
}
catch (...) {
m_validateClientFailure++;
throw;
}
}
}
MessageToken::MessageToken(String const& request) {
m_request = request;
m_hasResponse = false;
}
bool MessageToken::hasResponse() {
MutexLocker locker(m_lock);
return m_hasResponse;
}
bool MessageToken::waitForResponse(unsigned millis) {
MutexLocker locker(m_lock);
int64_t timeout = millis;
while (true) {
if (m_hasResponse)
return true;
if (timeout <= 0)
return false;
int64_t startTime = Thread::currentTime();
m_signal.wait(m_lock, (unsigned)timeout);
timeout -= Thread::currentTime() - startTime;
}
}
void MessageToken::setResponse(String const& response) {
{
MutexLocker locker(m_lock);
starAssert(!m_hasResponse);
m_response = response;
m_hasResponse = true;
}
m_signal.signal();
}
String MessageToken::response() {
MutexLocker locker(m_lock);
starAssert(m_hasResponse);
return m_response;
}
String MessageToken::request() {
return m_request;
}
}
}

View file

@ -0,0 +1,111 @@
#ifndef _STAR_AUTHENTICATOR_SERVER_HPP_
#define _STAR_AUTHENTICATOR_SERVER_HPP_
#include "StarAuthenticationKey.hpp"
#include "StarAuthenticationService.hpp"
#include "StarException.hpp"
#include "StarVariant.hpp"
#include "StarRoot.hpp"
#include "StarTcp.hpp"
#include "StarThread.hpp"
#include "StarMunin.hpp"
namespace Star {
namespace Auth {
//todo, port 80, hide behind a normal httpd, etc.
static int const ListenPort = 21027;
static unsigned const ClientSocketTimeout = 10000; // 10 seconds
static unsigned const ClientProcessingTimeout = 30000; // 30 seconds
static int const BufferCapacity = 15*1024;
class AuthenticationServer;
typedef shared_ptr<AuthenticationServer> AuthenticationServerPtr;
//todo: bad on purpose, replace with a httpd frontend and deliver zmq messages
// interops with the main thread using MessageToken, suitable to attach to zmq style, think mongrel httpd
class AuthenticationConnectionHandler: public Thread {
public:
AuthenticationConnectionHandler(TcpSocketPtr socket, AuthenticationServer* server);
~AuthenticationConnectionHandler();
// requests a stop, doesn't actually stop the, for that you'll need to finalize or join()
// which may take a long while due to socket operations not being interrupted.
void stop();
bool isClosed();
virtual void run();
private:
TcpSocketPtr m_socket;
AuthenticationServer* m_server;
bool m_stop;
bool m_closed;
Mutex m_lock;
void writeResponse(String const& response);
void writeErrorResponse(String const& response);
};
typedef shared_ptr<AuthenticationConnectionHandler> AuthenticationConnectionHandlerPtr;
class MessageToken {
public:
MessageToken(String const& request);
bool hasResponse();
bool waitForResponse(unsigned millis);
void setResponse(String const& response);
String request();
String response();
private:
Mutex m_lock;
ConditionVariable m_signal;
bool m_hasResponse;
String m_request;
String m_response;
};
typedef shared_ptr<MessageToken> MessageTokenPtr;
class AuthenticationServer {
public:
AuthenticationServer();
~AuthenticationServer();
void run();
void stop();
void addMessage(MessageTokenPtr const& message);
private:
shared_ptr<AuthenticationService> m_service;
Set<AuthenticationConnectionHandlerPtr> m_handlers;
List<MessageTokenPtr> m_messages;
ConditionVariable m_signal;
Mutex m_mainLock;
bool m_stop;
MuninNodePtr m_munin;
int m_requestCount;
int m_getAuthKeyCounter;
int m_authorizeClientCounter;
int m_authorizeClientFailure;
int m_validateClientCounter;
int m_validateClientFailure;
void acceptConnection(TcpSocketPtr socket);
void handleMessage(MessageTokenPtr const& message);
};
}
}
#endif

View file

@ -0,0 +1,83 @@
#include "StarDatabaseConnector.hpp"
#include "StarLogging.hpp"
//todo, ifdef for database type or something ?
#include <iostream>
#include "libpq-fe.h"
using namespace std;
namespace Star {
class DatabaseConnectionImpl {
public:
PGconn* conn;
};
DatabaseConnector::DatabaseConnector(String const& connectionString) {
m_impl = new DatabaseConnectionImpl;
m_impl->conn = PQconnectdb(connectionString.utf8Ptr());
if (PQstatus(m_impl->conn) != CONNECTION_OK) {
throw StarException(strf("Fail to connect to the database. %s", PQerrorMessage(m_impl->conn)));
}
}
DatabaseConnector::~DatabaseConnector() {
PQfinish(m_impl->conn);
delete m_impl;
}
List<VariantMap> DatabaseConnector::fetch(String const& command, VariantList const& arguments) {
int nParams = arguments.size();
List<String> paramValuesBacking(nParams);
DynamicArray<const char*> paramValues(nParams, (const char*)nullptr);
for (int i = 0; i < nParams; i++) {
if (arguments[i].type() == Variant::Type::BOOL)
paramValuesBacking[i] = arguments[i].toBool()?"t":"f";
else
paramValuesBacking[i] = arguments[i].toString();
paramValues[i] = paramValuesBacking[i].utf8Ptr();
}
auto res = PQexecParams(m_impl->conn, command.utf8Ptr(), nParams, NULL, paramValues.ptr(), NULL, NULL, 0);
if (PQresultStatus(res) == PGRES_COMMAND_OK) {
PQclear(res);
return {};
}
if (PQresultStatus(res) != PGRES_TUPLES_OK) {
auto message = strf("Command failed. Error: (%d) %s", PQresultStatus(res), PQresultErrorMessage(res));
PQclear(res);
throw StarException(message);
}
List<String> columns;
int nFields = PQnfields(res);
for (int i = 0; i < nFields; i++)
columns.append(PQfname(res, i));
List<VariantMap> result;
for (int i = 0; i < PQntuples(res); i++)
{
result.append({});
VariantMap& row = result.last();
for (int j = 0; j < nFields; j++)
row.insert(columns[j], PQgetvalue(res, i, j));
}
PQclear(res);
return result;
}
VariantMap DatabaseConnector::fetchRow(String const& command, VariantList const& arguments) {
auto result = fetch(command, arguments);
if (result.size() != 1)
throw StarException(strf("Command failed. Expected single row. Got %s", result.size()));
return result[0];
}
void DatabaseConnector::exec(String const& command, VariantList const& arguments) {
auto result = fetch(command, arguments);
if (result.size() != 0)
throw StarException(strf("Command failed. Expected no result row. Got %s", result.size()));
}
}

View file

@ -0,0 +1,31 @@
#ifndef _STAR_DATABASE_CONNECTOR_HPP_
#define _STAR_DATABASE_CONNECTOR_HPP_
#include "StarAuthenticationKey.hpp"
#include "StarAuthenticationService.hpp"
#include "StarException.hpp"
#include "StarVariant.hpp"
#include "StarRoot.hpp"
#include "StarTcp.hpp"
#include "StarThread.hpp"
namespace Star {
class DatabaseConnectionImpl;
class DatabaseConnector
{
public:
DatabaseConnector(String const& connectionString);
~DatabaseConnector();
List<VariantMap> fetch(String const& command, VariantList const& arguments = VariantList());
VariantMap fetchRow(String const& command, VariantList const& arguments = VariantList());
void exec(String const& command, VariantList const& arguments = VariantList());
private:
DatabaseConnectionImpl* m_impl;
};
}
#endif

View file

@ -0,0 +1,80 @@
#include "StarString.hpp"
#include "StarThread.hpp"
#include "StarRandom.hpp"
#include "StarAuthenticationKey.hpp"
#include "StarAuthenticationService.hpp"
#include "StarAuthenticationDatabase.hpp"
#include <iostream>
#include <fstream>
#include <string>
#include <ctime>
using namespace std;
using namespace Star;
int usage(int rc) {
std::cout
<< "USAGE: " << std::endl
<< " keygen rootkey <rootPrivateFile> <rootPublicFile>" << std::endl
<< " keygen authkey <rootPrivateFile> <authPrivateFile>" << std::endl
<< " keygen hashpass <username> <password>" << std::endl
<< " keygen insertuser <username> <passhash>" << std::endl
<< " keygen enableuser <username>" << std::endl
<< " keygen disableuser <username>" << std::endl;
return rc;
}
int main(int argc, char ** argv) {
try {
Random::randu32();
StringList args;
for (int i = 1; i < argc; i++)
args.append(argv[i]);
String connectionString = Variant::parseJson(File::readFileString("connectionstring.config")).getString("connectionString");
if (argc == 4 && !String("rootkey").compare(args[0])) {
Star::Auth::Key rootKey(true);
std::ofstream oFile;
oFile.open(args[1].utf8());
oFile << rootKey.privateKey();
oFile.close();
oFile.open(args[2].utf8());
oFile << rootKey.publicKey();
oFile.close();
return 0;
} else if (argc == 4 && !String("authkey").compare(args[0])) {
std::ifstream iFile(args[1].utf8());
String rootPrivateKey;
iFile >> rootPrivateKey;
iFile.close();
std::ofstream oFile(args[2].utf8());
oFile << Star::Auth::AuthenticationService::generateAuthenticationConfig(rootPrivateKey, Thread::currentTime() - 1LL * 25LL * 60LL * 60LL * 1000LL, Thread::currentTime() + 38LL * 24LL * 60LL * 60LL * 1000LL).repr(0, true);
oFile.close();
return 0;
} else if (argc == 4 && !String("hashpass").compare(args[0])) {
cout << Auth::preHashPassword(args[1], args[2]);
} else if (argc == 4 && !String("insertuser").compare(args[0])) {
Auth::AuthenticationDatabase database(connectionString);
database.setUserRecord(args[1], args[2], true);
cout << "Enabled user: " << args[1] << "\n";
} else if (argc == 3 && !String("disableuser").compare(args[0])) {
Auth::AuthenticationDatabase database(connectionString);
if (database.activateUserRecord(args[1], false))
cout << "Disabled user: " << args[1] << "\n";
else
cout << "No such user\n";
} else if (argc == 3 && !String("enableuser").compare(args[0])) {
Auth::AuthenticationDatabase database(connectionString);
if (database.activateUserRecord(args[1], true))
cout << "Enabled user: " << args[1] << "\n";
else
cout << "No such user\n";
} else {
return usage(-1);
}
} catch (std::exception const& e) {
cerr << e.what() << "\n";
return -1;
}
}

40
attic/authserver/main.cpp Normal file
View file

@ -0,0 +1,40 @@
#include "StarAuthenticationServer.hpp"
#include "StarRandom.hpp"
#include "StarLexicalCast.hpp"
#include "StarLogging.hpp"
#include "StarSignalHandler.hpp"
using namespace Star;
using namespace Star::Auth;
int main(int argc, char **argv) {
_unused(argc);
_unused(argv);
SignalHandler signalHandler;
try {
Logger::addSink(make_shared<FileLogSink>("starbound_auth.log", Logger::Debug));
Thread::prepareThread();
Auth::initializeKeyLogic();
StarException::initialize();
Logger::info("Auth server starting.");
auto authServer = make_shared<AuthenticationServer>();
signalHandler.setInterruptHandler([&authServer]() {
Logger::info("Interrupt received.");
if (authServer)
authServer->stop();
});
authServer->run();
authServer.reset();
Logger::info("Server shutdown gracefully");
} catch (std::exception const& e) {
fatalException(e);
}
return 0;
}