Some minor changes

This commit is contained in:
WolverinDEV 2019-10-13 17:12:50 +02:00
parent 7822d20efe
commit e39f01bde5
8 changed files with 198 additions and 47 deletions

@ -1 +1 @@
Subproject commit 2c928229b1aab0306a02d2b7820fd93f3a3623b9
Subproject commit 6b6e8774b8cb37158d6ee09658559e7dff4dd1c3

@ -4,6 +4,7 @@
#include <event2/thread.h>
#include <random>
#include <ed25519/ed25519.h>
#include <misc/base64.h>
using namespace std;
using namespace std::chrono;
@ -23,12 +24,43 @@ using namespace license;
inline bool isValid() { return (end.time_since_epoch().count() == 0 || std::chrono::system_clock::now() < this->end); }
};
*/
std::array<uint8_t, 195> intermediate_key{0x02, 0x00, 0x2d, 0x6b, 0xe3, 0x4d, 0x3c, 0xbb, 0x19, 0x1e, 0x46, 0x25, 0x72, 0x22, 0xa3, 0x53, 0x6d, 0x2d, 0xc3, 0xd1, 0x2c, 0xc8, 0xea, 0xf2, 0xf8, 0xe5, 0xd5, 0x0f, 0x6c, 0x7f, 0xeb, 0x63, 0x8a, 0xc4, 0x37, 0xb2, 0x33, 0x5e, 0x06, 0x31, 0xcf, 0x2c, 0xc6, 0xbe, 0x5e, 0x9c, 0xf1, 0xe6, 0xb3, 0xc3, 0x69, 0xd7, 0xf0, 0x05, 0x90, 0x2f, 0x65, 0x03, 0x60, 0x12, 0xa0, 0x20, 0x83, 0xe2, 0x6b, 0x4f, 0x46, 0xab, 0xfd, 0xa6, 0x22, 0x0b, 0x11, 0x9a, 0x34, 0xfe, 0x7b, 0xa3, 0x1b, 0x12, 0xce, 0x30, 0xf7, 0x0a, 0x32, 0x26, 0x23, 0x10, 0xfe, 0x58, 0xb6, 0xc7, 0x5d, 0x3d, 0xc6, 0x14, 0xdc, 0x10, 0xa0, 0xc0, 0x78, 0x10, 0x45, 0x41, 0x36, 0x1a, 0x1c, 0x9f, 0x60, 0x25, 0xd9, 0x69, 0xc9, 0x0b, 0xb7, 0xb4, 0x64, 0xab, 0x6c, 0x22, 0xff, 0xaf, 0x86, 0x26, 0x94, 0xcc, 0x7f, 0x59, 0x52, 0xa3, 0x56, 0x7f, 0x3e, 0x86, 0x04, 0x4c, 0xe0, 0x0e, 0xb3, 0xb1, 0x23, 0x51, 0xf7, 0xf0, 0x14, 0x5d, 0xfd, 0x48, 0xfb, 0x16, 0xe6, 0xc6, 0xca, 0xf2, 0x8d, 0xc8, 0xce, 0xf1, 0x2b, 0x12, 0x9e, 0xd1, 0x7a, 0x80, 0x3a, 0x9b, 0x46, 0xe7, 0xca, 0x34, 0x04, 0xae, 0x3d, 0x12, 0xcd, 0x4a, 0xc6, 0xe1, 0xf1, 0xe4, 0xd8, 0xca, 0x68, 0x36, 0xd3, 0x94, 0x0d, 0xef, 0x93, 0x86, 0xb9, 0x3a, 0xa4, 0x10, 0x52};
int main(int ac, char** av){
auto state = evthread_use_pthreads();
assert(state == 0);
string error;
uint8_t errc = 0;
#if 0
std::array<uint8_t, 32> prv_key{};
auto license = v2::License::create({}, prv_key);
assert(license->private_data_editable());
license->push_entry<v2::hierarchy::Intermediate>(system_clock::now(), system_clock::now() + hours{24 * 365 * 1000}, "TeaSpeak (Test)");
assert(license->write_private_data({0}));
error = license->write(errc);
assert(errc == 0);
cout << "Intermediate: " << hex;
for(size_t index = 0; index < error.length(); index++) {
uint8_t e = error[index];
cout << " 0x" << (e <= 0xF ? "0" : "") << (uint32_t) e << ",";
}
cout << endl;
cout << "Intermediate: " << base64::encode(error) << endl;
#endif
auto license = v2::License::read(intermediate_key.data(), intermediate_key.size(), errc);
license->push_entry<v2::hierarchy::Server>(system_clock::now(), system_clock::now() + hours{24 * 365 * 1000}, "TeaSpeak Official server", "contact@teaspeak.de");
assert(license->write_private_data({0}));
error = license->write(errc);
assert(errc == 0);
__asm__("nop");
cout << "Errc: " << errc << endl;
cout << "Write: " << base64::encode(error) << endl;
#if 0
std::array<uint8_t, 32> private_key, public_key;
std::random_device rd;
@ -51,6 +83,7 @@ int main(int ac, char** av){
cout << endl;
return true;
#endif
#if 0
srand(system_clock::now().time_since_epoch().count());

@ -119,7 +119,6 @@ namespace license::v2 {
}
std::shared_ptr<License> License::create(const std::vector<std::shared_ptr<const license::v2::HierarchyEntry>> &hierarchy, const std::array<uint8_t, 32> &prv_key) {
assert(!hierarchy.empty());
auto result = shared_ptr<License>(new License{});
result->_version = 2;
@ -175,20 +174,24 @@ namespace license::v2 {
/* "decode" the data */
{
auto index = 0;
while(index + 4 < decoded_buffer_length) {
auto& memory = *(uint32_t*) (&*decoded_buffer + index);
auto index = sizeof(header);
auto index_decoded = 0;
while(index + 4 < length) {
auto& memory = *(uint32_t*) (&*decoded_buffer + index_decoded);
memory = *(uint32_t*) (buffer + index);
memory ^= (uint32_t) crypt_key_gen();
index += 4;
index_decoded += 4;
}
while(index < decoded_buffer_length) {
auto& memory = *(uint8_t*) (&*decoded_buffer + index);
while(index < length) {
auto& memory = *(uint8_t*) (&*decoded_buffer + index_decoded);
memory = *(uint8_t*) (buffer + index);
memory ^= (uint8_t) crypt_key_gen();
index++;
index_decoded++;
}
}
memcpy(&body_header, &*decoded_buffer, sizeof(body_header));
if(decoded_buffer_length < sizeof(body_header) + body_header.length_hierarchy + body_header.length_private_data) {
error = 2; /* buffer too small */
@ -243,7 +246,7 @@ namespace license::v2 {
return result;
}
std::string License::write(int &error) {
std::string License::write(uint8_t &error) {
if(!this->private_data || !this->private_buffer_length) {
error = 2; /* missing private data */
return "";
@ -278,8 +281,8 @@ namespace license::v2 {
error = 3; /* failed to write hierarchy */
return "";
}
body_header.length_hierarchy = offset - begin_offset;
body_header.length_hierarchy = offset - begin_offset;
digest::sha1((char*) &*buffer + begin_offset, body_header.length_hierarchy, body_header.checksum_hierarchy);
}
@ -335,6 +338,8 @@ namespace license::v2 {
}
bool License::write_private_data(const LicensePrivateWriteOptions& write_options) {
if(this->_hierarchy.empty()) return false;
uint8_t private_key[64]; //ed25519_sign requires 64 bytes (may it expects a public key in front?)
if(!this->private_data->calculate_private_key(private_key, this->_hierarchy.size() - 1))
return false;
@ -409,7 +414,7 @@ namespace license::v2 {
std::array<uint8_t, 32> result{};
ge_p3_tobytes((uint8_t*) result.data(), &parent_key);
return {};
return result;
}
bool License::push_entry(const std::shared_ptr<const HierarchyEntry> &entry, size_t* index) {
@ -542,7 +547,7 @@ namespace license::v2 {
bool LicensePrivate::write(uint8_t *buffer, size_t &offset, size_t length, const LicensePrivateWriteOptions& options) {
if(options.precalculated_key_index < -1) {
if(buffer) {
if((offset + 2) < length) return false;
if((offset + 2) > length) return false;
*(buffer + offset++) = 0; /* no precalculated private key */
*(buffer + offset++) = 0; /* no raw private keys */
} else {
@ -553,23 +558,24 @@ namespace license::v2 {
if(index < 0) return false; /* we will NEVER write the root key */
if(buffer) {
if((offset + 2 + 32) < length) return false;
if((offset + 2 + 32) > length) return false;
*(buffer + offset++) = 1;
{
*(buffer + offset++) = index;
if(!this->calculate_private_key(buffer + offset, index))
return false;
offset += 32;
}
if((offset + 1) < length) return false;
if((offset + 1) > length) return false;
auto& private_key_count = *(buffer + offset++);
private_key_count = 0;
for(auto& [key_index, key] : this->private_keys) {
if(key_index <= index)
continue;
if((offset + 1 + key.size()) < length) return false;
if((offset + 1 + key.size()) > length) return false;
*(buffer + offset++) = key_index;
memcpy(buffer + offset, key.data(), key.size());
@ -592,12 +598,12 @@ namespace license::v2 {
}
if(buffer) {
if((offset + 4) < length) return false;
if((offset + 4) > length) return false;
*(uint32_t*) (buffer + offset) = this->meta_data.size();
offset += 4;
for(auto& [key, value] : this->meta_data) {
if((offset + 3 + key.length() + value.length()) < length) return false;
if((offset + 3 + key.length() + value.length()) > length) return false;
*(buffer + offset++) = key.length();
*(uint16_t*)(buffer + offset) = value.length();
@ -625,7 +631,7 @@ namespace license::v2 {
auto hierarchy = handle->hierarchy();
auto base_index = this->precalculated_private_key_index;
if(base_index >= hierarchy.size()) return false;
if(base_index >= (int64_t) hierarchy.size()) return false;
if(base_index < -1) return true; /* means we don't have a private key */
while(base_index < hierarchy.size()) {
@ -635,12 +641,12 @@ namespace license::v2 {
return true;
}
bool LicensePrivate::private_key_calculable(uint8_t index) const {
bool LicensePrivate::private_key_calculable(int index) const {
auto handle = this->_handle.lock();
if(!handle) return false;
auto hierarchy = handle->hierarchy();
if(index >= hierarchy.size()) return false;
if(index >= (int64_t) hierarchy.size()) return false;
auto base_index = this->precalculated_private_key_index;
@ -726,6 +732,9 @@ namespace license::v2 {
if(!result->allocate_read_body(body_length)) return nullptr;
if(body_length > 0) {
result->allocate_read_body(body_length);
if(!result->read_body) return nullptr;
result->read_body_length = body_length;
memcpy(result->read_body, buffer + offset, body_length);
offset += body_length;
}
@ -779,11 +788,11 @@ namespace license::v2 {
return true;
}
size_t length = 42 + this->read_body_length, offset = 0;
auto buffer = (uint8_t*) malloc(length);
size_t length = 43 + this->read_body_length, offset = 0;
auto buffer = unique_ptr<uint8_t, decltype(::free)*>((uint8_t*) malloc(length), ::free);
if(!buffer) return false;
if(this->write(buffer, offset, length)) {
digest::sha512((char*) buffer, length, this->_hash.data());
if(this->write(&*buffer, offset, length)) {
digest::sha512((char*) &*buffer, length, this->_hash.data());
this->_hash_set = true;
}
@ -800,14 +809,53 @@ namespace license::v2 {
std::shared_ptr<const HierarchyEntry> Intermediate::create(const uint8_t *pub_key, const std::chrono::system_clock::time_point &begin, const std::chrono::system_clock::time_point & end, const std::string &description) {
assert(description.size() < 256);
auto result = shared_ptr<HierarchyEntry>(new HierarchyEntry{hierarchy::Intermediate::type, pub_key, begin, end});
auto buffer_length = description.size() + 1;
if(!result || !result->allocate_read_body(description.size() + 1)) return nullptr;
memcpy(result->read_body + 1, description.data(), description.length());
*result->read_body = (uint8_t) description.length();
uint8_t* buffer;
auto result = BodyInterpreter::_create<Intermediate>(pub_key, begin, end, buffer_length, buffer);
if(!result) return nullptr;
memcpy(buffer + 1, description.data(), description.length());
*buffer = (uint8_t) description.length();
return result;
}
bool Server::has_username() {
return *(this->_memory + 1) > 0;
}
std::string_view Server::contact_email() {
return {(const char*) this->_memory + 2, *this->_memory};
}
std::string_view Server::username() {
return {(const char*) this->_memory + 2 + *this->_memory, *(this->_memory + 1)};
}
std::shared_ptr<const HierarchyEntry> Server::create(const uint8_t *pub_key, const std::chrono::system_clock::time_point &begin, const std::chrono::system_clock::time_point & end, const std::string &email, const std::optional<std::string> &username) {
assert(email.size() < 256);
assert(!username.has_value() || username->size() < 256);
auto buffer_length = 2 + email.size() + (username.has_value() ? username->length() : 0);
uint8_t* buffer;
auto result = BodyInterpreter::_create<Intermediate>(pub_key, begin, end, buffer_length, buffer);
if(!result) return nullptr;
memcpy(buffer + 2, email.data(), email.length());
*buffer = (uint8_t) email.length();
if(username.has_value())
memcpy(buffer + 2 + email.length(), username->data(), username->length());
*(buffer + 1) = (uint8_t) (username.has_value() ? username->length() : 0);
return result;
}
std::shared_ptr<const HierarchyEntry> Ephemeral::create(const uint8_t *pub_key, const std::chrono::system_clock::time_point &begin, const std::chrono::system_clock::time_point & end) {
uint8_t* buffer;
return BodyInterpreter::_create<Ephemeral>(pub_key, begin, end, 0, buffer);
}
}
static int test() {

@ -84,7 +84,7 @@ namespace license {
std::array<uint8_t, 32> generate_public_key(const uint8_t* /* public key root */, int /* length */ = -1) const;
std::string write(int& /* error */);
std::string write(uint8_t& /* error */);
bool private_data_editable() const;
bool write_private_data(const LicensePrivateWriteOptions& /* write options */);
@ -128,7 +128,7 @@ namespace license {
void register_raw_private_key(uint8_t /* index */, const uint8_t* /* key */);
bool has_raw_private_key(uint8_t /* index */) const;
bool private_key_calculable(uint8_t /* index */) const;
bool private_key_calculable(int /* index */) const;
bool calculate_private_key(uint8_t* /* response */, uint8_t /* index */) const;
private:
std::weak_ptr<License> _handle;
@ -141,11 +141,11 @@ namespace license {
};
namespace hierarchy {
struct Intermediate;
struct BodyInterpreter;
}
struct HierarchyEntry {
friend struct hierarchy::Intermediate;
friend struct hierarchy::BodyInterpreter;
public:
~HierarchyEntry();
@ -172,12 +172,12 @@ namespace license {
template <typename I>
inline I interpret_as() const {
assert(this->interpret_as<I>());
assert(this->interpretable_as<I>());
return I{this->read_body, this->read_body_length};
}
template <typename I>
inline bool interpretable_as() const { return I::type == this->_entry_type; }
inline bool interpretable_as() const { return I::_type == this->_entry_type; }
inline bool hash(uint8_t* /* hash result [64] */) const;
protected:
@ -207,20 +207,54 @@ namespace license {
};
namespace hierarchy {
struct type {
enum value : uint8_t {
Intermediate = 1,
Server = 2,
Ephemeral = 8
};
static constexpr const char* name(const value& value) {
switch (value) {
case Intermediate:
return "Intermediate";
case Server:
return "Server";
case Ephemeral:
return "Ephemeral";
default:
return "Unknown";
}
}
};
struct BodyInterpreter {
public:
BodyInterpreter() = delete;
protected:
template <typename T>
static std::shared_ptr<HierarchyEntry> _create(
const uint8_t *pub_key,
const std::chrono::system_clock::time_point &begin,
const std::chrono::system_clock::time_point &end,
size_t buffer_size, uint8_t*& buffer_ptr
) {
auto result = std::shared_ptr<HierarchyEntry>(new HierarchyEntry{T::_type, pub_key, begin, end});
if(!result || !result->allocate_read_body(buffer_size)) return nullptr;
result->read_body_length = buffer_size;
buffer_ptr = result->read_body;
return result;
}
BodyInterpreter(const uint8_t* memory, size_t length) { this->_memory = memory; this->_length = length; }
const uint8_t* _memory = nullptr;
size_t _length = 0;
};
struct Intermediate : public BodyInterpreter {
friend struct HierarchyEntry;
public:
static constexpr uint8_t type = 1;
static constexpr uint8_t _type = type::Intermediate;
static std::shared_ptr<const HierarchyEntry> create(
const uint8_t* /* public key */,
const std::chrono::system_clock::time_point& /* begin */,
@ -232,6 +266,38 @@ namespace license {
private:
Intermediate(const uint8_t* memory, size_t length) : BodyInterpreter(memory, length) {}
};
struct Server : public BodyInterpreter {
public:
static constexpr uint8_t _type = type::Server;
static std::shared_ptr<const HierarchyEntry> create(
const uint8_t* /* public key */,
const std::chrono::system_clock::time_point& /* begin */,
const std::chrono::system_clock::time_point& /* end */,
const std::string& /* email */,
const std::optional<std::string>& /* value */
);
std::string_view contact_email();
bool has_username();
std::string_view username();
private:
Server(const uint8_t* memory, size_t length) : BodyInterpreter(memory, length) {}
};
struct Ephemeral : public BodyInterpreter {
public:
static constexpr uint8_t _type = type::Ephemeral;
static std::shared_ptr<const HierarchyEntry> create(
const uint8_t* /* public key */,
const std::chrono::system_clock::time_point& /* begin */,
const std::chrono::system_clock::time_point& /* end */
);
private:
Ephemeral(const uint8_t* memory, size_t length) : BodyInterpreter(memory, length) {}
};
}
}

@ -160,7 +160,7 @@ bool ConnectedClient::notifyClientPermList(ClientDbId cldbid, const std::shared_
bool ConnectedClient::notifyChannelGroupList() {
Command cmd(this->getExternalType() == CLIENT_TEAMSPEAK ? "notifychannelgrouplist" : "");
int index = 0;
for (const auto &group : (this->server ? this->server->groups : serverInstance->getGroupManager().get())->availableChannelGroups(false)) {
for (const auto &group : (this->server ? this->server->groups : serverInstance->getGroupManager().get())->availableChannelGroups(true)) {
if(group->target() == GroupTarget::GROUPTARGET_CHANNEL) {
cmd[index]["cgid"] = group->groupId();
} else {

@ -106,6 +106,19 @@ void VoiceIOManager::adjustExecutors(size_t size) {
}
}
IOEventLoop::~IOEventLoop() {
if(this->executor.joinable()) {
auto handle = this->executor.native_handle();
timespec timeout{};
clock_gettime(CLOCK_REALTIME, &timeout);
timeout.tv_sec += 5;
auto join_result = pthread_timedjoin_np(handle, nullptr, &timeout);
if(join_result == EBUSY)
logError(LOG_INSTANCE, "Failed to shutdown IO event loop. Error: {}", join_result);
}
assert(!this->executor.joinable());
}
/**
* @warning executor lock must be locked!
*/

@ -53,16 +53,7 @@ namespace ts {
struct IOEventLoop {
IOEventLoop() = default;
~IOEventLoop() {
if(this->executor.joinable()) {
auto handle = this->executor.native_handle();
timespec timeout{};
clock_gettime(CLOCK_REALTIME, &timeout);
timeout.tv_sec += 5;
auto join_result = pthread_timedjoin_np(handle, nullptr, &timeout);
}
assert(!this->executor.joinable());
}
~IOEventLoop();
int bound_thread = -1; /* -1 represents that this loop is bound to no thread at all */

2
shared

@ -1 +1 @@
Subproject commit cb73d9df3258eaf59e4799c9e54d5f865e891734
Subproject commit e30c03029fb2be1a84a2706cf9bdd4f28cce9051