1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
|
#include "server/pch.hh"
#include "server/whitelist.hh"
#include "core/config/boolean.hh"
#include "core/config/string.hh"
#include "core/io/config_map.hh"
#include "core/io/physfs.hh"
#include "core/math/crc64.hh"
#include "core/utils/string.hh"
#include "server/game.hh"
#include "server/globals.hh"
constexpr static std::string_view DEFAULT_FILENAME = "whitelist.txt";
constexpr static char SEPARATOR_CHAR = ':';
config::Boolean whitelist::enabled(false);
config::String whitelist::filename(DEFAULT_FILENAME);
static emhash8::HashMap<std::string, std::uint64_t> whitelist_map;
void whitelist::init(void)
{
globals::server_config.add_value("whitelist.enabled", whitelist::enabled);
globals::server_config.add_value("whitelist.filename", whitelist::filename);
}
void whitelist::init_late(void)
{
whitelist_map.clear();
if(!whitelist::enabled.get_value()) {
// Not enabled, shouldn't
// even bother with parsing
// the whitelist file
return;
}
if(utils::is_whitespace(whitelist::filename.get_value())) {
spdlog::warn("whitelist: enabled but filename is empty, using default ({})", DEFAULT_FILENAME);
whitelist::filename.set(DEFAULT_FILENAME);
}
PHYSFS_File* file = PHYSFS_openRead(whitelist::filename.c_str());
if(file == nullptr) {
spdlog::warn("whitelist: {}: {}", whitelist::filename.get(), physfs_error());
whitelist::enabled.set_value(false);
return;
}
auto source = std::string(PHYSFS_fileLength(file), char(0x00));
PHYSFS_readBytes(file, source.data(), source.size());
PHYSFS_close(file);
std::istringstream stream(source);
std::string line;
while(std::getline(stream, line)) {
const auto location = line.find_last_of(SEPARATOR_CHAR);
if(location == std::string::npos) {
// Entries that don't define a password field default
// to the global server password; this allows easier adding
// of guest accounts which can later be edited to use a better password
whitelist_map[line] = server_game::password_hash;
}
else {
const auto username = line.substr(0, location);
const auto password = line.substr(location + 1);
whitelist_map[username] = math::crc64(password);
}
}
PHYSFS_close(file);
}
void whitelist::shutdown(void)
{
// UNDONE: implement saving
}
bool whitelist::contains(std::string_view username)
{
return whitelist_map.contains(std::string(username));
}
bool whitelist::matches(std::string_view username, std::uint64_t password_hash)
{
const auto it = whitelist_map.find(std::string(username));
if(it == whitelist_map.cend()) {
// Not whitelisted, no match
return false;
}
return it->second == password_hash;
}
|