implemented LoginRequest handler, changed ErrorMessage and ServerPublicInfoResponse
This commit is contained in:
parent
ef2531c63b
commit
9942d94c94
2
dependencies/tlibc
vendored
2
dependencies/tlibc
vendored
@ -1 +1 @@
|
|||||||
Subproject commit adaf5cc31199b8b70404f30b51a0e4ef822d6fab
|
Subproject commit ae0fa95d6aee2a7427c3e3575d74af1ed360e6e5
|
||||||
@ -66,8 +66,8 @@ Result(ServerConnection*) ServerConnection_open(cstr server_link_cstr){
|
|||||||
|
|
||||||
// send PacketHeader and ClientHandshake
|
// send PacketHeader and ClientHandshake
|
||||||
// encryption by server public key
|
// encryption by server public key
|
||||||
PacketHeader packet_header = {0};
|
PacketHeader packet_header;
|
||||||
ClientHandshake client_handshake = {0};
|
ClientHandshake client_handshake;
|
||||||
try_void(ClientHandshake_tryConstruct(&client_handshake, &packet_header,
|
try_void(ClientHandshake_tryConstruct(&client_handshake, &packet_header,
|
||||||
conn->session_key));
|
conn->session_key));
|
||||||
try_void(EncryptedSocketTCP_sendStructRSA(&conn->sock, &conn->rsa_enc, &packet_header));
|
try_void(EncryptedSocketTCP_sendStructRSA(&conn->sock, &conn->rsa_enc, &packet_header));
|
||||||
@ -80,26 +80,24 @@ Result(ServerConnection*) ServerConnection_open(cstr server_link_cstr){
|
|||||||
// handle server response
|
// handle server response
|
||||||
switch(packet_header.type){
|
switch(packet_header.type){
|
||||||
case PacketType_ErrorMessage: {
|
case PacketType_ErrorMessage: {
|
||||||
u32 err_msg_size = packet_header.content_size;
|
ErrorMessage err_msg;
|
||||||
if(err_msg_size > conn->sock.recv_buf.size)
|
try_void(EncryptedSocketTCP_recvStruct(&conn->sock, &err_msg));
|
||||||
err_msg_size = conn->sock.recv_buf.size;
|
if(err_msg.msg_size > conn->sock.recv_buf.size)
|
||||||
Array(u8) err_buf = Array_alloc_size(err_msg_size + 1);
|
err_msg.msg_size = conn->sock.recv_buf.size;
|
||||||
|
Array(u8) err_buf = Array_alloc_size(err_msg.msg_size + 1);
|
||||||
bool err_msg_completed = false;
|
bool err_msg_completed = false;
|
||||||
Defer(
|
Defer(if(!err_msg_completed) free(err_buf.data));
|
||||||
if(!err_msg_completed)
|
|
||||||
free(err_buf.data);
|
|
||||||
);
|
|
||||||
|
|
||||||
// receive error message
|
// receive message content
|
||||||
try_void(
|
try_void(
|
||||||
EncryptedSocketTCP_recv(
|
EncryptedSocketTCP_recv(
|
||||||
&conn->sock,
|
&conn->sock,
|
||||||
Array_sliceTo(err_buf, err_msg_size),
|
Array_sliceTo(err_buf, err_msg.msg_size),
|
||||||
SocketRecvFlag_WholeBuffer
|
SocketRecvFlag_WholeBuffer
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
((u8*)err_buf.data)[err_msg_size] = 0;
|
((u8*)err_buf.data)[err_msg.msg_size] = 0;
|
||||||
err_msg_completed = true;
|
err_msg_completed = true;
|
||||||
Return RESULT_ERROR((char*)err_buf.data, true);
|
Return RESULT_ERROR((char*)err_buf.data, true);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
#include "tlibc/std.h"
|
#include "tlibc/std.h"
|
||||||
|
|
||||||
#define USERNAME_SIZE_MIN 2
|
#define USERNAME_SIZE_MIN 2
|
||||||
#define USERNAME_SIZE_MAX 63
|
#define USERNAME_SIZE_MAX 31
|
||||||
#define PASSWORD_SIZE_MIN 8
|
#define PASSWORD_SIZE_MIN 8
|
||||||
#define PASSWORD_SIZE_MAX 31
|
#define PASSWORD_SIZE_MAX 31
|
||||||
#define PASSWORD_HASH_SIZE 32
|
#define PASSWORD_HASH_SIZE 32
|
||||||
|
|||||||
@ -15,7 +15,6 @@
|
|||||||
#define AESStream_DEFAULT_CLASS (&br_aes_big_ctr_vtable)
|
#define AESStream_DEFAULT_CLASS (&br_aes_big_ctr_vtable)
|
||||||
|
|
||||||
|
|
||||||
//TODO: use PKS#7 instead of this garbage
|
|
||||||
typedef struct EncryptedBlockHeader {
|
typedef struct EncryptedBlockHeader {
|
||||||
u8 padding_size;
|
u8 padding_size;
|
||||||
} ATTRIBUTE_ALIGNED(16) EncryptedBlockHeader;
|
} ATTRIBUTE_ALIGNED(16) EncryptedBlockHeader;
|
||||||
|
|||||||
@ -286,8 +286,8 @@ Result(void) idb_getRows(Table* t, u64 id, void* dst, u64 count){
|
|||||||
|
|
||||||
if(id + count > t->row_count){
|
if(id + count > t->row_count){
|
||||||
Return RESULT_ERROR_FMT(
|
Return RESULT_ERROR_FMT(
|
||||||
"Can't read " IFWIN("%llu", "%lu") " rows at index " IFWIN("%llu", "%lu")
|
"Can't read "FMT_u64" rows at index "FMT_u64
|
||||||
" because table '%s' has only " IFWIN("%llu", "%lu") " rows",
|
" because table '%s' has only "FMT_u64" rows",
|
||||||
count, id, t->name.data, t->row_count);
|
count, id, t->name.data, t->row_count);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -325,8 +325,8 @@ Result(void) idb_updateRows(Table* t, u64 id, const void* src, u64 count){
|
|||||||
|
|
||||||
if(id + count >= t->row_count){
|
if(id + count >= t->row_count){
|
||||||
Return RESULT_ERROR_FMT(
|
Return RESULT_ERROR_FMT(
|
||||||
"Can't update " IFWIN("%llu", "%lu") " rows at index " IFWIN("%llu", "%lu")
|
"Can't update "FMT_u64" rows at index "FMT_u64
|
||||||
" because table '%s' has only " IFWIN("%llu", "%lu") " rows",
|
" because table '%s' has only "FMT_u64" rows",
|
||||||
count, id, t->name.data, t->row_count);
|
count, id, t->name.data, t->row_count);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -21,14 +21,15 @@ Result(void) PacketHeader_validateType(PacketHeader* ptr, u16 expected_type){
|
|||||||
Result(void) PacketHeader_validateContentSize(PacketHeader* ptr, u64 expected_size){
|
Result(void) PacketHeader_validateContentSize(PacketHeader* ptr, u64 expected_size){
|
||||||
if(ptr->content_size != expected_size){
|
if(ptr->content_size != expected_size){
|
||||||
return RESULT_ERROR_FMT(
|
return RESULT_ERROR_FMT(
|
||||||
"expected message with content_size " IFWIN("%llu", "%lu")
|
"expected message with content_size "FMT_u64
|
||||||
", but received with content_size " IFWIN("%llu", "%lu"),
|
", but received with content_size "FMT_u64,
|
||||||
expected_size, ptr->content_size);
|
expected_size, ptr->content_size);
|
||||||
}
|
}
|
||||||
return RESULT_VOID;
|
return RESULT_VOID;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PacketHeader_construct(PacketHeader* ptr, u8 protocol_version, u16 type, u64 content_size){
|
void PacketHeader_construct(PacketHeader* ptr, u8 protocol_version, u16 type, u64 content_size){
|
||||||
|
memset(ptr, 0, sizeof(*ptr));
|
||||||
ptr->magic.n = PacketHeader_MAGIC.n;
|
ptr->magic.n = PacketHeader_MAGIC.n;
|
||||||
ptr->protocol_version = protocol_version;
|
ptr->protocol_version = protocol_version;
|
||||||
ptr->type = type;
|
ptr->type = type;
|
||||||
|
|||||||
@ -1,13 +1,55 @@
|
|||||||
#include "v1.h"
|
#include "v1.h"
|
||||||
|
|
||||||
|
str validateUsername_cstr(char username[USERNAME_SIZE_MAX+1], str* out_username_str){
|
||||||
|
// must end with 0
|
||||||
|
if(username[USERNAME_SIZE_MAX] != '\0'){
|
||||||
|
return STR("Username string doesn't end correctly");
|
||||||
|
}
|
||||||
|
|
||||||
|
str u = str_from_cstr(username);
|
||||||
|
str error_str = validateUsername_str(u);
|
||||||
|
if(error_str.data)
|
||||||
|
return error_str;
|
||||||
|
|
||||||
|
*out_username_str = u;
|
||||||
|
return str_null;
|
||||||
|
}
|
||||||
|
|
||||||
|
str validateUsername_str(str username){
|
||||||
|
if(username.size < USERNAME_SIZE_MIN){
|
||||||
|
return STR("Username length is too small");
|
||||||
|
}
|
||||||
|
|
||||||
|
for(u32 i = 0; i < username.size; i++){
|
||||||
|
char c = username.data[i];
|
||||||
|
if (char_isLatinLower(c) ||
|
||||||
|
char_isLatinUpper(c) ||
|
||||||
|
char_isDigit(c) ||
|
||||||
|
c == '.' || c == '_' || c == '-')
|
||||||
|
continue;
|
||||||
|
|
||||||
|
return STR("Username contains restricted characters. "
|
||||||
|
"Allowed characters: latin, digits, ._-");
|
||||||
|
}
|
||||||
|
|
||||||
|
return str_null;
|
||||||
|
}
|
||||||
|
|
||||||
#define _PacketHeader_construct(T) \
|
#define _PacketHeader_construct(T) \
|
||||||
PacketHeader_construct(header, PROTOCOL_VERSION, PacketType_##T, sizeof(T))
|
PacketHeader_construct(header, PROTOCOL_VERSION, PacketType_##T, sizeof(T))
|
||||||
|
|
||||||
|
void ErrorMessage_construct(ErrorMessage* ptr, PacketHeader* header, u32 msg_size){
|
||||||
|
_PacketHeader_construct(ErrorMessage);
|
||||||
|
memset(ptr, 0, sizeof(*ptr));
|
||||||
|
ptr->msg_size = msg_size;
|
||||||
|
}
|
||||||
|
|
||||||
Result(void) ClientHandshake_tryConstruct(ClientHandshake* ptr, PacketHeader* header,
|
Result(void) ClientHandshake_tryConstruct(ClientHandshake* ptr, PacketHeader* header,
|
||||||
Array(u8) session_key)
|
Array(u8) session_key)
|
||||||
{
|
{
|
||||||
Deferral(1);
|
Deferral(1);
|
||||||
_PacketHeader_construct(ClientHandshake);
|
_PacketHeader_construct(ClientHandshake);
|
||||||
|
memset(ptr, 0, sizeof(*ptr));
|
||||||
|
|
||||||
try_assert(session_key.size == sizeof(ptr->session_key));
|
try_assert(session_key.size == sizeof(ptr->session_key));
|
||||||
memcpy(ptr->session_key, session_key.data, session_key.size);
|
memcpy(ptr->session_key, session_key.data, session_key.size);
|
||||||
@ -19,6 +61,7 @@ void ServerHandshake_construct(ServerHandshake* ptr, PacketHeader* header,
|
|||||||
u64 session_id)
|
u64 session_id)
|
||||||
{
|
{
|
||||||
_PacketHeader_construct(ServerHandshake);
|
_PacketHeader_construct(ServerHandshake);
|
||||||
|
memset(ptr, 0, sizeof(*ptr));
|
||||||
ptr->session_id = session_id;
|
ptr->session_id = session_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -26,14 +69,31 @@ void ServerPublicInfoRequest_construct(ServerPublicInfoRequest *ptr, PacketHeade
|
|||||||
ServerPublicInfo property)
|
ServerPublicInfo property)
|
||||||
{
|
{
|
||||||
_PacketHeader_construct(ServerPublicInfoRequest);
|
_PacketHeader_construct(ServerPublicInfoRequest);
|
||||||
|
memset(ptr, 0, sizeof(*ptr));
|
||||||
ptr->property = property;
|
ptr->property = property;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ServerPublicInfoResponse_construct(ServerPublicInfoResponse* ptr, PacketHeader* header,
|
||||||
|
u32 data_size)
|
||||||
|
{
|
||||||
|
_PacketHeader_construct(ServerPublicInfoResponse);
|
||||||
|
memset(ptr, 0, sizeof(*ptr));
|
||||||
|
ptr->data_size = data_size;
|
||||||
|
}
|
||||||
|
|
||||||
Result(void) LoginRequest_tryConstruct(LoginRequest *ptr, PacketHeader* header,
|
Result(void) LoginRequest_tryConstruct(LoginRequest *ptr, PacketHeader* header,
|
||||||
Array(u8) token)
|
str username, Array(u8) token)
|
||||||
{
|
{
|
||||||
Deferral(1);
|
Deferral(1);
|
||||||
_PacketHeader_construct(LoginRequest);
|
_PacketHeader_construct(LoginRequest);
|
||||||
|
memset(ptr, 0, sizeof(*ptr));
|
||||||
|
|
||||||
|
str username_check_error = validateUsername_str(username);
|
||||||
|
if(username_check_error.data){
|
||||||
|
Return RESULT_ERROR(username_check_error.data, false);
|
||||||
|
}
|
||||||
|
memcpy(ptr->username, username.data, username.size);
|
||||||
|
ptr->username[username.size] = 0;
|
||||||
|
|
||||||
try_assert(token.size == sizeof(ptr->token));
|
try_assert(token.size == sizeof(ptr->token));
|
||||||
memcpy(ptr->token, token.data, token.size);
|
memcpy(ptr->token, token.data, token.size);
|
||||||
@ -45,6 +105,8 @@ void LoginResponse_construct(LoginResponse* ptr, PacketHeader* header,
|
|||||||
u64 user_id, u64 landing_channel_id)
|
u64 user_id, u64 landing_channel_id)
|
||||||
{
|
{
|
||||||
_PacketHeader_construct(LoginResponse);
|
_PacketHeader_construct(LoginResponse);
|
||||||
|
memset(ptr, 0, sizeof(*ptr));
|
||||||
|
|
||||||
ptr->user_id = user_id;
|
ptr->user_id = user_id;
|
||||||
ptr->landing_channel_id = landing_channel_id;
|
ptr->landing_channel_id = landing_channel_id;
|
||||||
}
|
}
|
||||||
@ -54,8 +116,12 @@ Result(void) RegisterRequest_tryConstruct(RegisterRequest *ptr, PacketHeader* he
|
|||||||
{
|
{
|
||||||
Deferral(1);
|
Deferral(1);
|
||||||
_PacketHeader_construct(RegisterRequest);
|
_PacketHeader_construct(RegisterRequest);
|
||||||
|
memset(ptr, 0, sizeof(*ptr));
|
||||||
|
|
||||||
try_assert(username.size >= USERNAME_SIZE_MIN && username.size <= USERNAME_SIZE_MAX);
|
str username_check_error = validateUsername_str(username);
|
||||||
|
if(username_check_error.data){
|
||||||
|
Return RESULT_ERROR(username_check_error.data, false);
|
||||||
|
}
|
||||||
memcpy(ptr->username, username.data, username.size);
|
memcpy(ptr->username, username.data, username.size);
|
||||||
ptr->username[username.size] = 0;
|
ptr->username[username.size] = 0;
|
||||||
|
|
||||||
@ -69,5 +135,6 @@ void RegisterResponse_construct(RegisterResponse *ptr, PacketHeader* header,
|
|||||||
u64 user_id)
|
u64 user_id)
|
||||||
{
|
{
|
||||||
_PacketHeader_construct(RegisterResponse);
|
_PacketHeader_construct(RegisterResponse);
|
||||||
|
memset(ptr, 0, sizeof(*ptr));
|
||||||
ptr->user_id = user_id;
|
ptr->user_id = user_id;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,6 +8,18 @@
|
|||||||
|
|
||||||
#define ALIGN_PACKET_STRUCT ATTRIBUTE_ALIGNED(8)
|
#define ALIGN_PACKET_STRUCT ATTRIBUTE_ALIGNED(8)
|
||||||
|
|
||||||
|
/*
|
||||||
|
Valid username:
|
||||||
|
- must end with '\0'
|
||||||
|
- USERNAME_SIZE_MIN <= size <= USERNAME_SIZE_MAX
|
||||||
|
- allowed characters: latin, digits, ._-
|
||||||
|
*/
|
||||||
|
/// validates username char[] and constructs str from it
|
||||||
|
/// @return str_null on success, stack-allocated error message on fail
|
||||||
|
str validateUsername_cstr(char username[USERNAME_SIZE_MAX+1], str* out_username_str) ATTRIBUTE_WARN_UNUSED_RESULT;
|
||||||
|
|
||||||
|
str validateUsername_str(str username) ATTRIBUTE_WARN_UNUSED_RESULT;
|
||||||
|
|
||||||
|
|
||||||
typedef enum PacketType {
|
typedef enum PacketType {
|
||||||
PacketType_Invalid,
|
PacketType_Invalid,
|
||||||
@ -23,9 +35,15 @@ typedef enum PacketType {
|
|||||||
} ATTRIBUTE_PACKED PacketType;
|
} ATTRIBUTE_PACKED PacketType;
|
||||||
|
|
||||||
|
|
||||||
// typedef struct ErrorMessage {
|
#define ERROR_MESSAGE_MAX_SIZE 8192
|
||||||
// /* stream of size header.content_size */
|
|
||||||
// } ErrorMessage;
|
typedef struct ErrorMessage {
|
||||||
|
u32 msg_size; // <= ERROR_MESSAGE_MAX_SIZE
|
||||||
|
/* stream of size msg_size */
|
||||||
|
} ErrorMessage;
|
||||||
|
|
||||||
|
void ErrorMessage_construct(ErrorMessage* ptr, PacketHeader* header,
|
||||||
|
u32 msg_size);
|
||||||
|
|
||||||
|
|
||||||
typedef struct ClientHandshake {
|
typedef struct ClientHandshake {
|
||||||
@ -57,17 +75,22 @@ void ServerPublicInfoRequest_construct(ServerPublicInfoRequest* ptr, PacketHeade
|
|||||||
ServerPublicInfo property);
|
ServerPublicInfo property);
|
||||||
|
|
||||||
|
|
||||||
// typedef struct ServerPublicInfoResponse {
|
typedef struct ServerPublicInfoResponse {
|
||||||
// /* stream of size header.content_size */
|
u32 data_size;
|
||||||
// } ServerPublicInfoResponse;
|
/* stream of size data_size */
|
||||||
|
} ServerPublicInfoResponse;
|
||||||
|
|
||||||
|
void ServerPublicInfoResponse_construct(ServerPublicInfoResponse* ptr, PacketHeader* header,
|
||||||
|
u32 data_size);
|
||||||
|
|
||||||
|
|
||||||
typedef struct LoginRequest {
|
typedef struct LoginRequest {
|
||||||
|
char username[USERNAME_SIZE_MAX + 1]; // null-terminated
|
||||||
u8 token[PASSWORD_HASH_SIZE];
|
u8 token[PASSWORD_HASH_SIZE];
|
||||||
} ALIGN_PACKET_STRUCT LoginRequest;
|
} ALIGN_PACKET_STRUCT LoginRequest;
|
||||||
|
|
||||||
Result(void) LoginRequest_tryConstruct(LoginRequest* ptr, PacketHeader* header,
|
Result(void) LoginRequest_tryConstruct(LoginRequest* ptr, PacketHeader* header,
|
||||||
Array(u8) token);
|
str username, Array(u8) token);
|
||||||
|
|
||||||
|
|
||||||
typedef struct LoginResponse {
|
typedef struct LoginResponse {
|
||||||
|
|||||||
@ -32,14 +32,14 @@ Result(ClientConnection*) ClientConnection_accept(ConnectionHandlerArgs* args)
|
|||||||
RSADecryptor_construct(&rsa_dec, &args->server->cred.rsa_sk);
|
RSADecryptor_construct(&rsa_dec, &args->server->cred.rsa_sk);
|
||||||
|
|
||||||
// receive PacketHeader
|
// receive PacketHeader
|
||||||
PacketHeader packet_header = {0};
|
PacketHeader packet_header;
|
||||||
try_void(EncryptedSocketTCP_recvStructRSA(&conn->sock, &rsa_dec, &packet_header));
|
try_void(EncryptedSocketTCP_recvStructRSA(&conn->sock, &rsa_dec, &packet_header));
|
||||||
try_void(PacketHeader_validateMagic(&packet_header));
|
try_void(PacketHeader_validateMagic(&packet_header));
|
||||||
try_void(PacketHeader_validateType(&packet_header, PacketType_ClientHandshake));
|
try_void(PacketHeader_validateType(&packet_header, PacketType_ClientHandshake));
|
||||||
try_void(PacketHeader_validateContentSize(&packet_header, sizeof(ClientHandshake)));
|
try_void(PacketHeader_validateContentSize(&packet_header, sizeof(ClientHandshake)));
|
||||||
|
|
||||||
// receive ClientHandshake
|
// receive ClientHandshake
|
||||||
ClientHandshake client_handshake = {0};
|
ClientHandshake client_handshake;
|
||||||
try_void(EncryptedSocketTCP_recvStructRSA(&conn->sock, &rsa_dec, &client_handshake));
|
try_void(EncryptedSocketTCP_recvStructRSA(&conn->sock, &rsa_dec, &client_handshake));
|
||||||
|
|
||||||
// use received session key
|
// use received session key
|
||||||
@ -47,7 +47,7 @@ Result(ClientConnection*) ClientConnection_accept(ConnectionHandlerArgs* args)
|
|||||||
EncryptedSocketTCP_changeKey(&conn->sock, conn->session_key);
|
EncryptedSocketTCP_changeKey(&conn->sock, conn->session_key);
|
||||||
|
|
||||||
// send PacketHeader and ServerHandshake over encrypted TCP socket
|
// send PacketHeader and ServerHandshake over encrypted TCP socket
|
||||||
ServerHandshake server_handshake = {0};
|
ServerHandshake server_handshake;
|
||||||
ServerHandshake_construct(&server_handshake, &packet_header,
|
ServerHandshake_construct(&server_handshake, &packet_header,
|
||||||
conn->session_id);
|
conn->session_id);
|
||||||
try_void(EncryptedSocketTCP_sendStruct(&conn->sock, &packet_header));
|
try_void(EncryptedSocketTCP_sendStruct(&conn->sock, &packet_header));
|
||||||
|
|||||||
@ -4,22 +4,74 @@
|
|||||||
declare_RequestHandler(Login)
|
declare_RequestHandler(Login)
|
||||||
{
|
{
|
||||||
Deferral(4);
|
Deferral(4);
|
||||||
logDebug(log_ctx, "requested %s", req_type_name);
|
logInfo(log_ctx, "requested %s", req_type_name);
|
||||||
|
|
||||||
LoginRequest req = {0};
|
// receive request
|
||||||
|
LoginRequest req;
|
||||||
try_void(PacketHeader_validateContentSize(req_head, sizeof(req)));
|
try_void(PacketHeader_validateContentSize(req_head, sizeof(req)));
|
||||||
try_void(EncryptedSocketTCP_recvStruct(&conn->sock, &req));
|
try_void(EncryptedSocketTCP_recvStruct(&conn->sock, &req));
|
||||||
|
|
||||||
//TODO: try authorize client
|
if(conn->authorized){
|
||||||
u64 user_id;
|
try_void(sendErrorMessage(log_ctx, false, conn, res_head,
|
||||||
u64 landing_channel_id;
|
STR("is logged in already")));
|
||||||
|
Return RESULT_VOID;
|
||||||
|
}
|
||||||
|
|
||||||
LoginResponse res = {0};
|
// validate username
|
||||||
LoginResponse_construct(&res, res_head, user_id, landing_channel_id);
|
str username_str = str_null;
|
||||||
|
str username_check_error = validateUsername_cstr(req.username, &username_str);
|
||||||
|
if(username_check_error.data){
|
||||||
|
try_void(sendErrorMessage(log_ctx, false, conn, res_head, username_check_error));
|
||||||
|
Return RESULT_VOID;
|
||||||
|
}
|
||||||
|
|
||||||
|
// cakculate hash of received token
|
||||||
|
u8 token_hash[PASSWORD_HASH_SIZE];
|
||||||
|
hash_password(
|
||||||
|
Array_construct_size(req.token, sizeof(req.token)),
|
||||||
|
token_hash,
|
||||||
|
PASSWORD_HASH_LVL_ROUNDS
|
||||||
|
);
|
||||||
|
|
||||||
|
// lock users cache
|
||||||
|
try_stderrcode(pthread_mutex_lock(&server->users_cache_mutex));
|
||||||
|
bool unlocked_users_cache_mutex = false;
|
||||||
|
Defer(if(!unlocked_users_cache_mutex) pthread_mutex_unlock(&server->users_cache_mutex));
|
||||||
|
|
||||||
|
// try get id from name cache
|
||||||
|
u64* id_ptr = HashMap_tryGetPtr(&server->users_name_id_map, username_str);
|
||||||
|
if(id_ptr == NULL){
|
||||||
|
try_void(sendErrorMessage_f(log_ctx, false, conn, res_head,
|
||||||
|
"Username '%s' is not registered\n",
|
||||||
|
username_str.data));
|
||||||
|
Return RESULT_VOID;
|
||||||
|
}
|
||||||
|
u64 user_id = *id_ptr;
|
||||||
|
|
||||||
|
// get user by id
|
||||||
|
try_assert(List_len(server->users_cache_list, User) < user_id);
|
||||||
|
User* u = &List_index(server->users_cache_list, User, user_id);
|
||||||
|
|
||||||
|
// validate token hash
|
||||||
|
if(memcmp(token_hash, u->token_hash, sizeof(token_hash)) != 0){
|
||||||
|
try_void(sendErrorMessage(log_ctx, false, conn, res_head,
|
||||||
|
STR("wrong password")));
|
||||||
|
Return RESULT_VOID;
|
||||||
|
}
|
||||||
|
|
||||||
|
// manually unlock mutex
|
||||||
|
pthread_mutex_unlock(&server->users_cache_mutex);
|
||||||
|
unlocked_users_cache_mutex = true;
|
||||||
|
|
||||||
|
// authorize
|
||||||
|
conn->authorized = true;
|
||||||
|
logInfo(log_ctx, "authorized user '%s'", username_str.data);
|
||||||
|
|
||||||
|
// send response
|
||||||
|
LoginResponse res;
|
||||||
|
LoginResponse_construct(&res, res_head, user_id, server->landing_channel_id);
|
||||||
try_void(EncryptedSocketTCP_sendStruct(&conn->sock, res_head));
|
try_void(EncryptedSocketTCP_sendStruct(&conn->sock, res_head));
|
||||||
try_void(EncryptedSocketTCP_sendStruct(&conn->sock, &res));
|
try_void(EncryptedSocketTCP_sendStruct(&conn->sock, &res));
|
||||||
conn->authorized = true;
|
|
||||||
logInfo(log_ctx, "client authorized");
|
|
||||||
|
|
||||||
Return RESULT_VOID;
|
Return RESULT_VOID;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,29 +3,18 @@
|
|||||||
declare_RequestHandler(Register)
|
declare_RequestHandler(Register)
|
||||||
{
|
{
|
||||||
Deferral(4);
|
Deferral(4);
|
||||||
logDebug(log_ctx, "requested %s", req_type_name);
|
logInfo(log_ctx, "requested %s", req_type_name);
|
||||||
|
|
||||||
RegisterRequest req = {0};
|
// receive request
|
||||||
|
RegisterRequest req;
|
||||||
try_void(PacketHeader_validateContentSize(req_head, sizeof(req)));
|
try_void(PacketHeader_validateContentSize(req_head, sizeof(req)));
|
||||||
try_void(EncryptedSocketTCP_recvStruct(&conn->sock, &req));
|
try_void(EncryptedSocketTCP_recvStruct(&conn->sock, &req));
|
||||||
|
|
||||||
//TODO: reject usernames with restricted characters
|
// validate username
|
||||||
// must end with 0
|
str username_str = str_null;
|
||||||
if(req.username[sizeof(req.username - 1)] != 0){
|
str username_check_error = validateUsername_cstr(req.username, &username_str);
|
||||||
try(char* err_msg, p, sendErrorMessage(conn, res_head,
|
if(username_check_error.data){
|
||||||
"Username is incorrect\n"));
|
try_void(sendErrorMessage(log_ctx, false, conn, res_head, username_check_error));
|
||||||
logWarn(log_ctx, "%s", err_msg);
|
|
||||||
free(err_msg);
|
|
||||||
Return RESULT_VOID;
|
|
||||||
}
|
|
||||||
// check username size
|
|
||||||
str username_str = str_from_cstr(req.username);
|
|
||||||
if(username_str.size < USERNAME_SIZE_MIN){
|
|
||||||
try(char* err_msg, p, sendErrorMessage(conn, res_head,
|
|
||||||
"Username length (in bytes) must be >= %i and <= %i\n",
|
|
||||||
USERNAME_SIZE_MIN, USERNAME_SIZE_MAX));
|
|
||||||
logWarn(log_ctx, "%s", err_msg);
|
|
||||||
free(err_msg);
|
|
||||||
Return RESULT_VOID;
|
Return RESULT_VOID;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -36,11 +25,9 @@ declare_RequestHandler(Register)
|
|||||||
|
|
||||||
// check if name is taken
|
// check if name is taken
|
||||||
if(HashMap_tryGetPtr(&server->users_name_id_map, username_str) != NULL){
|
if(HashMap_tryGetPtr(&server->users_name_id_map, username_str) != NULL){
|
||||||
try(char* err_msg, p, sendErrorMessage(conn, res_head,
|
try_void(sendErrorMessage_f(log_ctx, false, conn, res_head,
|
||||||
"User with name '%s' already exists\n",
|
"Username'%s' already exists\n",
|
||||||
username_str.data));
|
username_str.data));
|
||||||
logWarn(log_ctx, "%s", err_msg);
|
|
||||||
free(err_msg);
|
|
||||||
Return RESULT_VOID;
|
Return RESULT_VOID;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -66,7 +53,10 @@ declare_RequestHandler(Register)
|
|||||||
pthread_mutex_unlock(&server->users_cache_mutex);
|
pthread_mutex_unlock(&server->users_cache_mutex);
|
||||||
unlocked_users_cache_mutex = true;
|
unlocked_users_cache_mutex = true;
|
||||||
|
|
||||||
RegisterResponse res = {0};
|
logInfo(log_ctx, "registered user '%s'", username_str.data);
|
||||||
|
|
||||||
|
// send response
|
||||||
|
RegisterResponse res;
|
||||||
RegisterResponse_construct(&res, res_head, user_id);
|
RegisterResponse_construct(&res, res_head, user_id);
|
||||||
try_void(EncryptedSocketTCP_sendStruct(&conn->sock, res_head));
|
try_void(EncryptedSocketTCP_sendStruct(&conn->sock, res_head));
|
||||||
try_void(EncryptedSocketTCP_sendStruct(&conn->sock, &res));
|
try_void(EncryptedSocketTCP_sendStruct(&conn->sock, &res));
|
||||||
|
|||||||
@ -3,21 +3,20 @@
|
|||||||
declare_RequestHandler(ServerPublicInfo)
|
declare_RequestHandler(ServerPublicInfo)
|
||||||
{
|
{
|
||||||
Deferral(4);
|
Deferral(4);
|
||||||
logDebug(log_ctx, "requested %s", req_type_name);
|
logInfo(log_ctx, "requested %s", req_type_name);
|
||||||
|
|
||||||
ServerPublicInfoRequest req = {0};
|
// receive request
|
||||||
|
ServerPublicInfoRequest req;
|
||||||
try_void(PacketHeader_validateContentSize(req_head, sizeof(req)));
|
try_void(PacketHeader_validateContentSize(req_head, sizeof(req)));
|
||||||
try_void(EncryptedSocketTCP_recvStruct(&conn->sock, &req));
|
try_void(EncryptedSocketTCP_recvStruct(&conn->sock, &req));
|
||||||
|
|
||||||
//TODO: try find requested info
|
// find requested info
|
||||||
Array(u8) content;
|
Array(u8) content;
|
||||||
switch(req.property){
|
switch(req.property){
|
||||||
default:{
|
default:{
|
||||||
try(char* err_msg, p, sendErrorMessage(conn, res_head,
|
try_void(sendErrorMessage_f(log_ctx, false, conn, res_head,
|
||||||
"Unknown ServerPublicInfo property %u",
|
"Unknown ServerPublicInfo property %u",
|
||||||
req.property));
|
req.property));
|
||||||
logWarn(log_ctx, "%s", err_msg);
|
|
||||||
free(err_msg);
|
|
||||||
Return RESULT_VOID;
|
Return RESULT_VOID;
|
||||||
}
|
}
|
||||||
case ServerPublicInfo_Name:
|
case ServerPublicInfo_Name:
|
||||||
@ -28,9 +27,11 @@ declare_RequestHandler(ServerPublicInfo)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
PacketHeader_construct(res_head,
|
// send response
|
||||||
PROTOCOL_VERSION, PacketType_ServerPublicInfoResponse, content.size);
|
ServerPublicInfoResponse res;
|
||||||
|
ServerPublicInfoResponse_construct(&res, res_head, content.size);
|
||||||
try_void(EncryptedSocketTCP_sendStruct(&conn->sock, res_head));
|
try_void(EncryptedSocketTCP_sendStruct(&conn->sock, res_head));
|
||||||
|
try_void(EncryptedSocketTCP_sendStruct(&conn->sock, &res));
|
||||||
try_void(EncryptedSocketTCP_send(&conn->sock, content));
|
try_void(EncryptedSocketTCP_send(&conn->sock, content));
|
||||||
|
|
||||||
Return RESULT_VOID;
|
Return RESULT_VOID;
|
||||||
|
|||||||
@ -4,10 +4,17 @@
|
|||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
|
||||||
|
|
||||||
Result(char*) __sendErrorMessage_va(ClientConnection* conn, PacketHeader* res_head,
|
Result(void) sendErrorMessage(cstr log_ctx, bool logAsError,
|
||||||
|
ClientConnection* conn, PacketHeader* res_head,
|
||||||
|
str msg);
|
||||||
|
|
||||||
|
Result(void) __sendErrorMessage_fv(cstr log_ctx, bool logAsError,
|
||||||
|
ClientConnection* conn, PacketHeader* res_head,
|
||||||
cstr format, va_list argv);
|
cstr format, va_list argv);
|
||||||
Result(char*) sendErrorMessage(ClientConnection* conn, PacketHeader* res_head,
|
|
||||||
cstr format, ...) ATTRIBUTE_CHECK_FORMAT_PRINTF(3, 4);
|
Result(void) sendErrorMessage_f(cstr log_ctx, bool logAsError,
|
||||||
|
ClientConnection* conn, PacketHeader* res_head,
|
||||||
|
cstr format, ...) ATTRIBUTE_CHECK_FORMAT_PRINTF(5, 6);
|
||||||
|
|
||||||
|
|
||||||
#define declare_RequestHandler(TYPE) \
|
#define declare_RequestHandler(TYPE) \
|
||||||
|
|||||||
@ -1,34 +1,54 @@
|
|||||||
#include "request_handlers.h"
|
#include "request_handlers.h"
|
||||||
|
#include "log.h"
|
||||||
|
|
||||||
Result(char*) __sendErrorMessage_va(ClientConnection* conn, PacketHeader* res_head,
|
Result(void) sendErrorMessage(cstr log_ctx, bool logAsError,
|
||||||
|
ClientConnection* conn, PacketHeader* res_head,
|
||||||
|
str msg)
|
||||||
|
{
|
||||||
|
Deferral(1);
|
||||||
|
|
||||||
|
//limit ErrorMessage size to fit into EncryptedSocketTCP.internal_buffer_size
|
||||||
|
if(msg.size > ERROR_MESSAGE_MAX_SIZE)
|
||||||
|
msg.size = ERROR_MESSAGE_MAX_SIZE;
|
||||||
|
|
||||||
|
if(logAsError){
|
||||||
|
logError(log_ctx, FMT_str, msg.size, msg.data);
|
||||||
|
} else {
|
||||||
|
logWarn(log_ctx, FMT_str, msg.size, msg.data);
|
||||||
|
}
|
||||||
|
|
||||||
|
ErrorMessage res;
|
||||||
|
ErrorMessage_construct(&res, res_head, msg.size);
|
||||||
|
try_void(EncryptedSocketTCP_sendStruct(&conn->sock, res_head));
|
||||||
|
try_void(EncryptedSocketTCP_sendStruct(&conn->sock, &res));
|
||||||
|
try_void(EncryptedSocketTCP_send(&conn->sock, str_castTo_Array(msg)));
|
||||||
|
|
||||||
|
Return RESULT_VOID;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result(void) __sendErrorMessage_fv(cstr log_ctx, bool logAsError,
|
||||||
|
ClientConnection* conn, PacketHeader* res_head,
|
||||||
cstr format, va_list argv)
|
cstr format, va_list argv)
|
||||||
{
|
{
|
||||||
Deferral(4);
|
Deferral(4);
|
||||||
|
|
||||||
Array(u8) err_buf;
|
|
||||||
err_buf.data = vsprintf_malloc(format, argv);
|
|
||||||
err_buf.size = strlen(err_buf.data);
|
|
||||||
//limit ErrorMessage size to fit into EncryptedSocketTCP.internal_buffer_size
|
|
||||||
if(err_buf.size > NETWORK_BUFFER_SIZE)
|
|
||||||
err_buf.size = NETWORK_BUFFER_SIZE;
|
|
||||||
bool err_complete = false;
|
|
||||||
Defer(if(!err_complete) free(err_buf.data));
|
|
||||||
|
|
||||||
PacketHeader_construct(res_head,
|
str msg = str_from_cstr(vsprintf_malloc(format, argv));
|
||||||
PROTOCOL_VERSION, PacketType_ErrorMessage, err_buf.size);
|
Defer(free(msg.data));
|
||||||
try_void(EncryptedSocketTCP_sendStruct(&conn->sock, res_head));
|
try_void(sendErrorMessage(log_ctx, logAsError, conn, res_head, msg));
|
||||||
try_void(EncryptedSocketTCP_send(&conn->sock, err_buf));
|
|
||||||
|
|
||||||
err_complete = true;
|
Return RESULT_VOID;
|
||||||
Return RESULT_VALUE(p, err_buf.data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Result(char*) sendErrorMessage(ClientConnection* conn, PacketHeader* res_head,
|
Result(void) sendErrorMessage_f(cstr log_ctx, bool logAsError,
|
||||||
|
ClientConnection* conn, PacketHeader* res_head,
|
||||||
cstr format, ...)
|
cstr format, ...)
|
||||||
{
|
{
|
||||||
|
Deferral(1);
|
||||||
|
|
||||||
va_list argv;
|
va_list argv;
|
||||||
va_start(argv, format);
|
va_start(argv, format);
|
||||||
ResultVar(char*) err_msg = __sendErrorMessage_va(conn, res_head, format, argv);
|
Defer(va_end(argv));
|
||||||
va_end(argv);
|
try_void(__sendErrorMessage_fv(log_ctx, logAsError, conn, res_head, format, argv));
|
||||||
return err_msg;
|
|
||||||
|
return RESULT_VOID;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,9 +1,20 @@
|
|||||||
#include "request_handlers.h"
|
#include "request_handlers.h"
|
||||||
|
|
||||||
declare_RequestHandler(T)
|
declare_RequestHandler(NAME)
|
||||||
{
|
{
|
||||||
Deferral(4);
|
Deferral(4);
|
||||||
logDebug(log_ctx, "requested %s", req_type_name);
|
logInfo(log_ctx, "requested %s", req_type_name);
|
||||||
|
|
||||||
|
// receive request
|
||||||
|
NAME##Request req;
|
||||||
|
try_void(PacketHeader_validateContentSize(req_head, sizeof(req)));
|
||||||
|
try_void(EncryptedSocketTCP_recvStruct(&conn->sock, &req));
|
||||||
|
|
||||||
|
// send response
|
||||||
|
NAME##Response res;
|
||||||
|
NAME##Response_construct(&res, res_head, );
|
||||||
|
try_void(EncryptedSocketTCP_sendStruct(&conn->sock, res_head));
|
||||||
|
try_void(EncryptedSocketTCP_sendStruct(&conn->sock, &res));
|
||||||
|
|
||||||
Return RESULT_VOID;
|
Return RESULT_VOID;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -52,6 +52,14 @@ Result(Server*) Server_createFromConfig(cstr config_path){
|
|||||||
try_void(config_findValue(config_str, STR("description"), &tmp_str, true));
|
try_void(config_findValue(config_str, STR("description"), &tmp_str, true));
|
||||||
server->description = str_copy(tmp_str);
|
server->description = str_copy(tmp_str);
|
||||||
|
|
||||||
|
// parse landing_channel_id
|
||||||
|
try_void(config_findValue(config_str, STR("landing_channel_id"), &tmp_str, true));
|
||||||
|
char* lci_cstr = str_copy(tmp_str).data;
|
||||||
|
Defer(free(lci_cstr));
|
||||||
|
if(sscanf(lci_cstr, FMT_u64, &server->landing_channel_id) != 1){
|
||||||
|
Return RESULT_ERROR("can't parse 'landing_channel_id' value as number", false);
|
||||||
|
}
|
||||||
|
|
||||||
// parse local_address
|
// parse local_address
|
||||||
try_void(config_findValue(config_str, STR("local_address"), &tmp_str, true));
|
try_void(config_findValue(config_str, STR("local_address"), &tmp_str, true));
|
||||||
char* local_end_cstr = str_copy(tmp_str).data;
|
char* local_end_cstr = str_copy(tmp_str).data;
|
||||||
@ -133,7 +141,7 @@ Result(void) Server_run(Server* server){
|
|||||||
static void* handleConnection(void* _args){
|
static void* handleConnection(void* _args){
|
||||||
ConnectionHandlerArgs* args = (ConnectionHandlerArgs*)_args;
|
ConnectionHandlerArgs* args = (ConnectionHandlerArgs*)_args;
|
||||||
char log_ctx[64];
|
char log_ctx[64];
|
||||||
sprintf(log_ctx, "Session-" IFWIN("%llx", "%lx"), args->session_id);
|
sprintf(log_ctx, "Session-"FMT_x64, args->session_id);
|
||||||
|
|
||||||
ResultVar(void) r = try_handleConnection(args, log_ctx);
|
ResultVar(void) r = try_handleConnection(args, log_ctx);
|
||||||
if(r.error){
|
if(r.error){
|
||||||
@ -159,8 +167,8 @@ static Result(void) try_handleConnection(ConnectionHandlerArgs* args, cstr log_c
|
|||||||
logInfo(log_ctx, "session accepted");
|
logInfo(log_ctx, "session accepted");
|
||||||
|
|
||||||
// handle requests
|
// handle requests
|
||||||
PacketHeader req_head = {0};
|
PacketHeader req_head;
|
||||||
PacketHeader res_head = {0};
|
PacketHeader res_head;
|
||||||
while(true){
|
while(true){
|
||||||
sleepMsec(20);
|
sleepMsec(20);
|
||||||
//TODO: implement some additional check if socket is dead or not
|
//TODO: implement some additional check if socket is dead or not
|
||||||
@ -171,12 +179,9 @@ static Result(void) try_handleConnection(ConnectionHandlerArgs* args, cstr log_c
|
|||||||
switch(req_head.type){
|
switch(req_head.type){
|
||||||
// send error message and close connection
|
// send error message and close connection
|
||||||
default:
|
default:
|
||||||
try(char* err_msg, p,
|
try_void(sendErrorMessage_f(log_ctx, false, conn, &res_head,
|
||||||
sendErrorMessage(conn, &res_head,
|
"Received unexpected packet of type %u",
|
||||||
"Received unexpected packet of type %u",
|
req_head.type));
|
||||||
req_head.type));
|
|
||||||
logWarn(log_ctx, "%s", err_msg);
|
|
||||||
free(err_msg);
|
|
||||||
Return RESULT_VOID;
|
Return RESULT_VOID;
|
||||||
|
|
||||||
// unauthorized requests
|
// unauthorized requests
|
||||||
|
|||||||
@ -45,6 +45,7 @@ void ClientConnection_close(ClientConnection* conn);
|
|||||||
typedef struct Server {
|
typedef struct Server {
|
||||||
str name;
|
str name;
|
||||||
str description;
|
str description;
|
||||||
|
u64 landing_channel_id;
|
||||||
EndpointIPv4 local_end;
|
EndpointIPv4 local_end;
|
||||||
ServerCredentials cred;
|
ServerCredentials cred;
|
||||||
IncrementalDB* db;
|
IncrementalDB* db;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user