tcp-chat/src/main.c

179 lines
6.0 KiB
C
Executable File

#include "network/network.h"
#include "client/client.h"
#include "server/server.h"
#define _DEFAULT_CONFIG_PATH_CLIENT "tcp-chat-client.config"
#define _DEFAULT_CONFIG_PATH_SERVER "tcp-chat-server.config"
typedef enum ProgramMode {
Client,
Server,
RsaGenStdin,
RsaGenRandom,
} ProgramMode;
#define arg_is(LITERAL) str_equals(arg_str, STR(LITERAL))
int main(const int argc, cstr const* argv){
Deferral(32);
if(br_prng_seeder_system(NULL) == NULL){
printfe("Can't get system random seeder. Bearssl is compiled incorrectly.");
return 1;
}
ProgramMode mode = Client;
cstr server_endpoint_cstr = NULL;
cstr config_path = NULL;
u32 key_size = 0;
for(int argi = 1; argi < argc; argi++){
str arg_str = str_from_cstr(argv[argi]);
if(arg_is("-h") || arg_is("--help")){
printf(
"USAGE:\n"
"no arguments Interactive client mode.\n"
"-h, --help Show this message.\n"
"-l, --listen [addr:port] Start server.\n"
"--config [path] Load config from specified path.\n"
" Default path for config is '" _DEFAULT_CONFIG_PATH_CLIENT "' or '" _DEFAULT_CONFIG_PATH_SERVER "'\n"
"--rsa-gen-stdin [size] Generate RSA private and public keys based on stdin data (64Kb max).\n"
" size: 2048 / 3072 (default) / 4096\n"
" Usage: `cat somefile | tcp-chat --gen-rsa-stdin`\n"
"--rsa-gen-random [size] Generate random RSA private and public keys.\n"
" size: 2048 / 3072 (default) / 4096\n"
);
Return 0;
}
if(arg_is("-l") || arg_is("--listen")){
if(mode != Client){
printf("program mode is set already\n");
Return 1;
}
mode = Server;
if(++argi >= argc){
printfe("ERROR: no endpoint specified\n");
Return 1;
}
server_endpoint_cstr = argv[argi];
}
else if(arg_is("--config")){
if(++argi >= argc){
printfe("ERROR: no config path specified\n");
Return 1;
}
config_path = argv[argi];
}
else if(arg_is("--rsa-gen-stdin")){
if(mode != Client){
printf("program mode is set already\n");
Return 1;
}
mode = RsaGenStdin;
if(++argi >= argc){
key_size = RSA_DEFAULT_KEY_SIZE;
}
else if(sscanf(argv[argi], "%u", &key_size) != 1){
printfe("ERROR: no key size specified\n");
}
}
else if(arg_is("--rsa-gen-random")){
if(mode != Client){
printf("program mode is set already\n");
Return 1;
}
mode = RsaGenRandom;
if(++argi >= argc){
key_size = RSA_DEFAULT_KEY_SIZE;
}
else if(sscanf(argv[argi], "%u", &key_size) != 1){
printfe("ERROR: no key size specified\n");
}
}
else {
printfe("ERROR: unknown argument '%s'\n"
"Use '-h' to see list of avaliable arguments\n",
argv[argi]);
Return 1;
}
}
try_fatal_void(network_init());
Defer(network_deinit());
switch(mode){
case Client: {
if(config_path == NULL)
config_path = _DEFAULT_CONFIG_PATH_CLIENT;
try_fatal_void(client_run());
break;
}
case Server: {
if(config_path == NULL)
config_path = _DEFAULT_CONFIG_PATH_SERVER;
try_fatal_void(server_run(server_endpoint_cstr, config_path));
break;
}
case RsaGenStdin: {
size_t input_max_size = 64*1024;
char* input_buf = malloc(input_max_size);
Defer(free(input_buf));
size_t read_n = fread(input_buf, 1, input_max_size, stdin);
if(read_n == 0){
printfe("ERROR: no input\n");
Return 1;
}
str input_str = str_construct(input_buf, read_n, false);
printfe("generating RSA key pair based on stdin...\n");
br_rsa_private_key sk;
br_rsa_public_key pk;
try_fatal_void(RSA_generateKeyPairFromPassword(key_size, &sk, &pk, input_str));
Defer(
RSA_destroyPrivateKey(&sk);
RSA_destroyPublicKey(&pk);
);
str sk_str = RSA_serializePrivateKey_base64(&sk);
printf("rsa_private_key = %s\n", sk_str.data);
free(sk_str.data);
str pk_str = RSA_serializePublicKey_base64(&pk);
printf("\nrsa_public_key = %s\n", pk_str.data);
free(pk_str.data);
}
break;
case RsaGenRandom: {
printfe("generating random RSA key pair...\n");
br_rsa_private_key sk;
br_rsa_public_key pk;
try_fatal_void(RSA_generateKeyPairFromSystemRandom(key_size, &sk, &pk));
Defer(
RSA_destroyPrivateKey(&sk);
RSA_destroyPublicKey(&pk);
);
str sk_str = RSA_serializePrivateKey_base64(&sk);
printf("rsa_private_key = %s\n", sk_str.data);
free(sk_str.data);
str pk_str = RSA_serializePublicKey_base64(&pk);
printf("\nrsa_public_key = %s\n", pk_str.data);
free(pk_str.data);
}
break;
default:
printfe("ERROR: invalid program mode %i\n", mode);
Return 1;
}
Return 0;
}