90 lines
2.7 KiB
C
90 lines
2.7 KiB
C
#include "server.h"
|
|
#include "network/tcp-chat-protocol/v1.h"
|
|
|
|
void ClientConnection_close(ClientConnection* conn){
|
|
if(conn == NULL)
|
|
return;
|
|
socket_close(conn->sock.sock);
|
|
free(conn->session_key.data);
|
|
free(conn);
|
|
}
|
|
|
|
Result(ClientConnection*) ClientConnection_accept(ServerCredentials* server_credentials,
|
|
Socket sock_tcp, EndpointIPv4 client_end, u64 session_id)
|
|
{
|
|
Deferral(32);
|
|
|
|
ClientConnection* conn = (ClientConnection*)malloc(sizeof(ClientConnection));
|
|
memset(conn, 0, sizeof(*conn));
|
|
bool success = false;
|
|
Defer(
|
|
if(!success)
|
|
ClientConnection_close(conn);
|
|
);
|
|
|
|
conn->client_end = client_end;
|
|
conn->session_id = session_id;
|
|
conn->session_key = Array_alloc_size(AES_SESSION_KEY_SIZE);
|
|
|
|
Array(u8) enc_buf = Array_alloc_size(8*1024);
|
|
Defer(free(enc_buf.data));
|
|
Array(u8) dec_buf = Array_alloc_size(8*1024);
|
|
Defer(free(dec_buf.data));
|
|
u32 enc_size = 0, dec_size = 0;
|
|
|
|
// TODO: set socket timeout to 5 seconds
|
|
|
|
// receive message encrypted by server public key
|
|
try(enc_size, u,
|
|
socket_recv(
|
|
sock_tcp,
|
|
Array_sliceBefore(enc_buf, server_credentials->rsa_pk.nlen),
|
|
SocketRecvFlag_WaitAll
|
|
)
|
|
);
|
|
|
|
// decrypt the message using server private key
|
|
RSADecryptor rsa_dec;
|
|
RSADecryptor_construct(&rsa_dec, &server_credentials->rsa_sk);
|
|
try(dec_size, u,
|
|
RSADecryptor_decrypt(
|
|
&rsa_dec,
|
|
Array_sliceBefore(enc_buf, enc_size),
|
|
dec_buf
|
|
)
|
|
);
|
|
|
|
// validate client handshake
|
|
if(dec_size != sizeof(ClientHandshake)){
|
|
Return RESULT_ERROR_FMT(
|
|
"decrypted message (size: %u) is not a ClientHandshake (size: %u)",
|
|
dec_size, (u32)sizeof(ClientHandshake)
|
|
);
|
|
}
|
|
ClientHandshake* client_handshake = dec_buf.data;
|
|
try_void(PacketHeader_validateMagic(&client_handshake->header));
|
|
if(client_handshake->header.type != PacketType_ClientHandshake){
|
|
Return RESULT_ERROR_FMT(
|
|
"received message of unexpected type: %u",
|
|
client_handshake->header.type
|
|
);
|
|
}
|
|
|
|
// use received session key
|
|
memcpy(conn->session_key.data, client_handshake->session_key, conn->session_key.size);
|
|
EncryptedSocketTCP_construct(&conn->sock, sock_tcp, conn->session_key);
|
|
|
|
// construct ServerHandshake in dec_buf
|
|
ServerHandshake_construct((ServerHandshake*)dec_buf.data, session_id);
|
|
// send ServerHandshake over encrypted TCP socket
|
|
try_void(
|
|
EncryptedSocketTCP_send(
|
|
&conn->sock,
|
|
Array_sliceBefore(dec_buf, sizeof(ServerHandshake)),
|
|
enc_buf
|
|
)
|
|
);
|
|
|
|
success = true;
|
|
Return RESULT_VALUE(p, conn);
|
|
} |