mirror of https://github.com/thearcanum/WIFSS
314 lines
7.8 KiB
C
Executable File
314 lines
7.8 KiB
C
Executable File
#include "client.h"
|
|
|
|
|
|
bool start_client(void)
|
|
{
|
|
clear_console();
|
|
|
|
printf("\n\033[32m[WIFSS] Starting Client...\033[0m\n\n");
|
|
|
|
init_global_variables();
|
|
|
|
char address[BUFFER];
|
|
char *args[BUFFER];
|
|
int16_t nbArgs = -1;
|
|
|
|
do
|
|
{
|
|
printf("-> Server IP: ");
|
|
prompt_keyboard(address);
|
|
free_args(args, &nbArgs);
|
|
parse_command(address, args, &nbArgs);
|
|
|
|
} while(nbArgs != 1);
|
|
|
|
int32_t port;
|
|
char portBuffer[BUFFER];
|
|
do
|
|
{
|
|
printf("-> Server Port: ");
|
|
prompt_keyboard(portBuffer);
|
|
free_args(args, &nbArgs);
|
|
parse_command(portBuffer, args, &nbArgs);
|
|
|
|
if(nbArgs == 1)
|
|
{
|
|
port = strtoul(args[0], NULL, 10);
|
|
}
|
|
|
|
else
|
|
{
|
|
port = -1;
|
|
}
|
|
|
|
} while(port < 0 || port > 65535);
|
|
|
|
struct addrinfo *servinfo;
|
|
|
|
struct addrinfo hints;
|
|
memset(&hints, 0, sizeof hints);
|
|
hints.ai_family = AF_UNSPEC;
|
|
hints.ai_socktype = SOCK_STREAM;
|
|
hints.ai_flags = AI_PASSIVE;
|
|
|
|
int16_t status = getaddrinfo(address, args[0], &hints, &servinfo);
|
|
if(status != 0)
|
|
{
|
|
fprintf(stderr, "\n\033[31m[WIFSS] An error occurred while trying to get some information about your host: %s.\033[0m\n\n", gai_strerror(status));
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
char buffer[BUFFER];
|
|
|
|
// Some stuff to set a timeout on `connect`
|
|
int16_t sock = -1;
|
|
int8_t error = 0;
|
|
socklen_t lenght = sizeof(error);
|
|
int16_t nbFds = -1;
|
|
fd_set readfds;
|
|
do
|
|
{
|
|
for(struct addrinfo *tmp = servinfo; tmp != NULL; tmp = tmp->ai_next)
|
|
{
|
|
/* Only for previous iterations */
|
|
if(sock != -1 && close(sock) == -1)
|
|
{
|
|
fprintf(stderr, "\n\033[31m[WIFSS] An error occurred while closing a socket: %s.\033[0m\n\n", strerror(errno));
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
/* ____________________________ */
|
|
|
|
sock = socket(tmp->ai_family, tmp->ai_socktype, tmp->ai_protocol);
|
|
if(sock == -1)
|
|
{
|
|
printf("\n\033[31m[WIFSS] Error while creating an endpoint for communication with server: %s.\033[0m\n\n", strerror(errno));
|
|
return false;
|
|
}
|
|
|
|
// Before the connection procedure, we'll set the socket as NON-BLOCKING
|
|
fcntl(sock, F_SETFL, fcntl(sock, F_GETFL, false) | O_NONBLOCK);
|
|
|
|
// Let's launch the connection procedure
|
|
connect(sock, tmp->ai_addr, tmp->ai_addrlen);
|
|
if(errno != EINPROGRESS)
|
|
{
|
|
fprintf(stderr, "\n\033[31m[WIFSS] An error occurred while running the connection procedure to: ");
|
|
print_endpoint(tmp);
|
|
printf(" (%s).\033[0m\n\n", strerror(errno));
|
|
continue;
|
|
}
|
|
|
|
// Let's now set a watch dog of 3 seconds on it
|
|
FD_ZERO(&readfds);
|
|
FD_SET(sock, &readfds);
|
|
nbFds = select(sock + 1, &readfds, NULL, NULL, &(struct timeval){3, 0});
|
|
if(nbFds == 0)
|
|
{
|
|
// The timeout has been elapsed...
|
|
printf("\n\033[31m[WIFSS] Error while connecting to ");
|
|
print_endpoint(tmp);
|
|
printf(": timeout reached.\033[0m\n");
|
|
continue;
|
|
}
|
|
|
|
else if(nbFds == -1)
|
|
{
|
|
// Again ? An error occurred...
|
|
fprintf(stderr, "\n\033[31m[WIFSS] An error occurred while waiting for the connection procedure ending: %s.\033[0m\n\n", strerror(errno));
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
else
|
|
{
|
|
// Fetch the buffered SYNC data [see @server/commands.c]
|
|
recv(sock, buffer, BUFFER, false);
|
|
|
|
if(strcmp(buffer, CLIENT_SERVER_SYNC))
|
|
{
|
|
printf("%s\n", buffer);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
}
|
|
|
|
// Two cases: The connection has been established OR a f*cking new error occurred (before the timeout !)...
|
|
if(getsockopt(sock, SOL_SOCKET, SO_ERROR, &error, &lenght) != 0)
|
|
{
|
|
fprintf(stderr, "\n\033[31m[WIFSS] An error occurred while retrieving some information about the socket: %s.\033[0m\n\n", gai_strerror(status));
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
if(error == 0)
|
|
{
|
|
// For the future, let's set again the socket as BLOCKING
|
|
fcntl(sock, F_SETFL, fcntl(sock, F_GETFL, false) ^ O_NONBLOCK);
|
|
|
|
// SSL stuffs
|
|
SSL *ssl = SSL_new(core_variables.ctx);
|
|
if(ssl == NULL)
|
|
{
|
|
fprintf(stderr, "\n\n\033[31mSSL Error: Couldn\'t enable the SSL layer on the socket.\n\n");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
if(SSL_set_cipher_list(ssl, (const char *const)"HIGH:!aNULL:!kRSA:!PSK:!SRP:!MD5:!RC4") != 1)
|
|
{
|
|
fprintf(stderr, "\n\n\033[31mSSL Error: Couldn\'t set the ciphers list.\n\n");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
SSL_set_fd(ssl, sock);
|
|
|
|
if(SSL_connect(ssl) <= 0)
|
|
{
|
|
printf("\n\n\033[31m[WIFSS] Couldn\'t create a TLS tunnel with the host...\033[0m\n\n");
|
|
ERR_print_errors_fp(stderr);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
// SSL Verification + Certificate information
|
|
if(SSL_get_verify_result(ssl) != X509_V_OK)
|
|
{
|
|
fprintf(stderr, "\n\n\033[31mSSL Error: The result got from SSL is not valid (is your certificate correct ?).\n\n");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
X509 *cert = SSL_get_peer_certificate(ssl);
|
|
if(cert == NULL)
|
|
{
|
|
fprintf(stderr, "\n\n\033[31mSSL Error: No certificate was sent by server.\n\n");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
printf("\n\033[34m\tTLS cipher used for this connection: %s\n", SSL_get_cipher(ssl));
|
|
|
|
char *str = NULL;
|
|
printf("\tServer certificate:\n");
|
|
str = X509_NAME_oneline(X509_get_subject_name(cert), 0, 0);
|
|
printf("\t\tSubject: %s\n", (str != NULL ? str : "None"));
|
|
OPENSSL_free(str);
|
|
str = X509_NAME_oneline(X509_get_issuer_name(cert), 0, 0);
|
|
printf("\t\tIssuer : %s\033[0m\n", (str != NULL ? str : "None"));
|
|
OPENSSL_free(str);
|
|
X509_free(cert);
|
|
// __________________________________________
|
|
|
|
core_variables.ssl = ssl;
|
|
|
|
printf("\n\033[32m[WIFSS] Connected to ");
|
|
print_endpoint(tmp);
|
|
printf(".\033[0m\n");
|
|
|
|
strncpy(buffer, "", BUFFER);
|
|
|
|
if(SSL_read(ssl, buffer, BUFFER) <= 0)
|
|
{
|
|
printf("\n\033[31m[WIFSS] Couldn\'t get your ID from server, exiting now.\033[0m\n\n");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
uint16_t idTemp = get_second_args_group_as_integer(buffer);
|
|
printf("\n\033[32m[WIFSS] Your ID on the server is %d.\033[0m\n\n", idTemp);
|
|
|
|
/* We save the ID of the client for the future */
|
|
core_variables.client_id = idTemp;
|
|
|
|
break;
|
|
}
|
|
|
|
else
|
|
{
|
|
printf("\n\033[31m[WIFSS] Error while connecting to ");
|
|
print_endpoint(tmp);
|
|
printf(": %s.\033[0m\n", strerror(errno));
|
|
}
|
|
}
|
|
|
|
if(core_variables.client_id != -1)
|
|
{
|
|
// Yeah... We've to `break` the loop a second time
|
|
break;
|
|
}
|
|
|
|
else
|
|
{
|
|
printf("\nWould you like to retry now ? (YES / no)\n\n");
|
|
if(!prompt_yes_no(buffer, args, &nbArgs))
|
|
{
|
|
printf("\n");
|
|
return false;
|
|
}
|
|
}
|
|
|
|
} while(true);
|
|
|
|
// We free here the previous linked list
|
|
freeaddrinfo(servinfo);
|
|
|
|
/* We save the socket value for the future */
|
|
core_variables.server_sock = sock;
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
void stop_client(void)
|
|
{
|
|
if(core_variables.ssl != NULL)
|
|
{
|
|
SSL_shutdown(core_variables.ssl);
|
|
SSL_free(core_variables.ssl);
|
|
}
|
|
|
|
if(core_variables.server_sock >= 0)
|
|
{
|
|
if(close(core_variables.server_sock) == -1)
|
|
{
|
|
printf("\n\033[35m[WIFSS] Socket couldn't be successfully closed.\033[0m\n\n");
|
|
}
|
|
else
|
|
{
|
|
printf("\n\n\033[32m[WIFSS] Socket successfully closed.\033[0m\n\n");
|
|
}
|
|
}
|
|
|
|
SSL_CTX_free(core_variables.ctx);
|
|
|
|
printf("\033[35m[WIFSS] Client is shutting down for now.\033[0m\n");
|
|
|
|
for(uint8_t i = 0; i < 64; i++)
|
|
{
|
|
printf("=");
|
|
}
|
|
|
|
printf("\n\n");
|
|
}
|
|
|
|
|
|
void init_global_variables(void)
|
|
{
|
|
core_variables.server_sock = -1;
|
|
core_variables.client_id = -1;
|
|
core_variables.ssl = NULL;
|
|
core_variables.ctx = NULL;
|
|
|
|
// SSL stuffs
|
|
OpenSSL_add_ssl_algorithms();
|
|
SSL_load_error_strings();
|
|
|
|
SSL_CTX *ctx = SSL_CTX_new(TLSv1_2_client_method());
|
|
if(ctx == NULL)
|
|
{
|
|
fprintf(stderr, "\n\033[31m\033[31mSSL Error: Couldn\'t create a SSL context.\033[0m\n\n");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_COMPRESSION);
|
|
|
|
if(SSL_CTX_load_verify_locations(ctx, "client.crt", NULL) != 1)
|
|
{
|
|
fprintf(stderr, "\n\033[31mSSL Error: Couldn\'t verify the location of, or load, the server\'s certificate.\033[0m\n\n");
|
|
}
|
|
|
|
core_variables.ctx = ctx;
|
|
}
|