From 004f09395ba5bc41a3ff59a7cce32538c211fadd Mon Sep 17 00:00:00 2001 From: Chris Date: Thu, 31 Mar 2016 17:18:44 +0100 Subject: [PATCH] Changed old 'cfg' directory references to 'conf'. Updated README with usage instructions when building from source. Server now sends shutdown message to client correctly when credential check fails as this was previously allowing users to stay logged on. Ref #26 - Replaced SSLv3 with TLS due to weak ciphers - https://www.openssl.org/news/changelog.html#x1. Fix #43 - Current user home now used when initialising client config. --- Makefile | 12 +++++------ README.md | 37 ++++++++++++++++++++++++++++++++ conf/key | 0 conf/users | 0 src/chatclient/client.c | 39 +++++++++++++++++++++++----------- src/lib/shhchat_cfg.h | 34 ++++++++++++++++++++++------- src/shhchatd/server.c | 47 +++++++++++++++++++++++------------------ 7 files changed, 122 insertions(+), 47 deletions(-) mode change 100755 => 100644 conf/key mode change 100755 => 100644 conf/users diff --git a/Makefile b/Makefile index 976b006..f0cc4ae 100644 --- a/Makefile +++ b/Makefile @@ -18,9 +18,9 @@ all: rm -f $(BIN)/shhchatd $(BIN)/shhclient $(CC) -o $(BIN)/shhchatd $(SRC)/shhchatd/server.c $(CFLAGS) -DVERSION='"_beta"' $(CC) -o $(BIN)/shhclient $(SRC)/chatclient/client.c $(CFLAGS) -DVERSION='"_beta"' - rm -rf $(BIN)/cfg - mkdir $(BIN)/cfg - cp $(CONF)/* -t $(BIN)/cfg + rm -rf $(BIN)/$(CONF) + mkdir $(BIN)/$(CONF) + cp $(CONF)/* -t $(BIN)/$(CONF) @echo Finished shhchat build clean: @@ -33,7 +33,7 @@ debug: rm -f $(BIN)/shhchatd $(BIN)/shhclient $(CC) -o $(BIN)/shhchatd $(SRC)/shhchatd/server.c $(CFLAGS) -DDEBUG -g $(CC) -o $(BIN)/shhclient $(SRC)/chatclient/client.c $(CFLAGS) -DDEBUG - rm -rf $(BIN)/cfg - mkdir $(BIN)/cfg - cp $(CONF)/* -t $(BIN)/cfg + rm -rf $(BIN)/$(CONF) + mkdir $(BIN)/$(CONF) + cp $(CONF)/* -t $(BIN)/$(CONF) @echo Finished shhchat debug build diff --git a/README.md b/README.md index 35e3d86..c43f2ca 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,44 @@ Next Milestone: 0.1 release * A simple key file will contain the encryption key used for messages. * A simple user/password file managed by the server. * SSL support. +* Example configuration files in conf.

Setting up SSL

shhchat supports SSL that requires a certificate and private key for both client and server. Have a look at http://dst.lbl.gov/~boverhof/openssl_certs.html for a simple guide. + +

How to use

+ +

Bare minimal setup without SSL

+
Server
+Create a directory in /etc named 'shhchat': + +
sudo mkdir /etc/shhchat
+ +Create a file called 'key' in this newly created directory: + +
echo 123456 | sudo tee /etc/shhchat/key
+ +Add a user: + +
echo user1: | sudo tee /etc/shhchat/users
+ +The server will also check for the user db file in the conf directory where it is running locally. + +Execute the server as root: + +
sudo shhchatd
+ +
Client
+Create a file called 'key' in your user home directory with the same key as the server + +
echo 123456 > ~/.key
+ +Connect to your server! + +
shhclient server_ip_address
+ +

Full setup with SSL

+As above however you will need a key/certificate pair for the client and server. + +The locations of these certificates can be set via the shhchat.conf file in /etc/shhchat/shhchat.conf. \ No newline at end of file diff --git a/conf/key b/conf/key old mode 100755 new mode 100644 diff --git a/conf/users b/conf/users old mode 100755 new mode 100644 diff --git a/src/chatclient/client.c b/src/chatclient/client.c index 555dcb4..34b3523 100644 --- a/src/chatclient/client.c +++ b/src/chatclient/client.c @@ -32,6 +32,12 @@ chat client #define VERSION "_beta" #endif +#ifdef DEBUG +#define debug 1 +#else +#define debug 0 +#endif + #define RED "\e[1;31m" #define GREEN "\e[1;32m" #define YELLOW "\e[1;33m" @@ -80,7 +86,15 @@ int main(int argc, char *argv[]) { int buf_size; struct parameters params; - init_parameters(¶ms); + if ((homeDir = getenv("HOME")) == NULL) { + homeDir = getpwuid(getuid())->pw_dir; + } + + if (debug == 1) { + debugsOn = true; + } + + init_parameters(¶ms, homeDir); parse_config(¶ms); if (argc < 2) { @@ -91,10 +105,6 @@ int main(int argc, char *argv[]) { if (argc == 3) { port = atoi(argv[2]); } - - if ((homeDir = getenv("HOME")) == NULL) { - homeDir = getpwuid(getuid())->pw_dir; - } printf("%sshhchat client v%s started\n%s", GREEN, VERSION, RESET_COLOR); printDebug("Searching for key file...\n"); @@ -103,15 +113,15 @@ int main(int argc, char *argv[]) { fp = fopen(params.client_simple_key, "r"); if (fp == NULL) { - printf("%sKey file not found in %s directory - Checking if you have a cfg folder in the current directory...\n%s", params.client_simple_key, GREEN, RESET_COLOR); - fp = fopen("cfg/key", "r"); + printf("Key file not found in '%s' - Checking in conf directory...\n", homeDir); + fp = fopen("conf/key", "r"); if (fp == NULL) { printf("%sKey file not found - This is the minimum encryption you can have...Exiting\n%s", RED, RESET_COLOR); exit(EXIT_FAILURE); } else { - printf("%sKey found in cfg directory.\n%s", GREEN, RESET_COLOR); + printf("%sKey found in conf directory.\n%s", GREEN, RESET_COLOR); } } @@ -134,7 +144,7 @@ int main(int argc, char *argv[]) { // Configure SSL initSSL(); - ssl_context = SSL_CTX_new(SSLv3_client_method()); + ssl_context = SSL_CTX_new(TLSv1_2_client_method()); if (!ssl_context) { fprintf (stderr, "SSL_CTX_new ERROR\n"); @@ -265,9 +275,14 @@ void *chat_read(int sockfd) { y = n; xor_encrypt(key, buffer, y); - if (strcmp(buffer, "!!shutdown") == 0) { - printf("%s\nConnection closed.\n%s", GREEN, RESET_COLOR); - exit(0); + if (strncmp(buffer, "!!shutdown", 10) == 0) { + if (strlen(buffer) > 10) { + printf("%s\n%s%s", GREEN, buffer + 10, RESET_COLOR); + exit(0); + } else { + printf("%s\nConnection closed.\n%s", GREEN, RESET_COLOR); + exit(0); + } } // Special server commands are preceded by '!!' diff --git a/src/lib/shhchat_cfg.h b/src/lib/shhchat_cfg.h index 4376b43..be2dd0a 100644 --- a/src/lib/shhchat_cfg.h +++ b/src/lib/shhchat_cfg.h @@ -23,17 +23,35 @@ struct parameters { char server_simple_key[MAXLEN]; char server_ssl_key[MAXLEN]; char server_ssl_cert[MAXLEN]; -} - -parameters; +} parameters; -void init_parameters(struct parameters *params); +void init_parameters(struct parameters *params, char *home); void parse_config(struct parameters *params); -void init_parameters(struct parameters *params) { - strncpy(params->client_simple_key, ".shhkey", MAXLEN); - strncpy(params->client_ssl_key, "/home/user/.shh_key", MAXLEN); - strncpy(params->client_ssl_cert, "/home/user/.shh_certificate", MAXLEN); +void init_parameters(struct parameters *params, char *home) { + char key[] = "/.key"; + char ssl_key[] = "/.shh_key"; + char ssl_cert[] = "/.shh_certificate"; + char tmp[50]; + memset(&tmp, 0, sizeof(tmp)); + + if (home != NULL) { + strncpy(tmp, home, strlen(home)); + strncat(tmp, key, sizeof(key)); + strncpy(params->client_simple_key, tmp, MAXLEN); + memset(&tmp, 0, sizeof(tmp)); + + strncpy(tmp, home, strlen(home)); + strncat(tmp, ssl_key, sizeof(ssl_key)); + strncpy(params->client_ssl_key, ssl_key, MAXLEN); + memset(&tmp, 0, sizeof(tmp)); + + strncpy(tmp, home, strlen(home)); + strncat(tmp, ssl_cert, sizeof(ssl_cert)); + strncpy(params->client_ssl_cert, ssl_cert, MAXLEN); + memset(&tmp, 0, sizeof(tmp)); + } + strncpy(params->server_simple_key, "/etc/shhchat/key", MAXLEN); strncpy(params->server_ssl_key, "/etc/shhchat/shh_key.pem", MAXLEN); strncpy(params->server_ssl_cert, "/etc/shhchat/shh_certificate.pem", MAXLEN); diff --git a/src/shhchatd/server.c b/src/shhchatd/server.c index 5685e98..1f06709 100644 --- a/src/shhchatd/server.c +++ b/src/shhchatd/server.c @@ -141,7 +141,7 @@ int main(int argc, char *argv[]) { bool have_key = false; struct parameters params; - init_parameters(¶ms); + init_parameters(¶ms, NULL); parse_config(¶ms); if (debug == 1) @@ -161,14 +161,14 @@ int main(int argc, char *argv[]) { printDebug("Reading contents of config file."); - // TODO #11 - Create cfg if it doesn't exist + // TODO #11 - Create conf if it doesn't exist // Try and open key file fp = fopen(params.server_simple_key, "r"); if (fp == NULL) { - syslog(LOG_INFO, "%s", "Failed to find key file in config defined location - Checking if you have a cfg folder in the current directory..."); - fp = fopen("cfg/key", "r"); + syslog(LOG_INFO, "%s", "Failed to find key file in config defined location - Checking if you have a conf folder in the current directory..."); + fp = fopen("conf/key", "r"); if (fp == NULL) { syslog(LOG_INFO, "%s", "Key file not found - This is the minimum encryption you can have...Exiting"); @@ -214,7 +214,7 @@ int main(int argc, char *argv[]) { // Setup SSL initSSL(); - ssl_context = SSL_CTX_new(SSLv3_server_method()); + ssl_context = SSL_CTX_new(TLSv1_2_server_method()); if (!ssl_context) { fprintf (stderr, "SSL_CTX_new ERROR\n"); @@ -318,7 +318,7 @@ int main(int argc, char *argv[]) { // Run checks on the credentials if (checkConnected(h, username) || !checkCredentials(username, password)) { - char upi[] = "Username / password incorrect or your user is already connected elsewhere.\n"; + char upi[] = "!!shutdownUsername / password incorrect or your user is already connected elsewhere.\n"; n = strlen(upi); xor_encrypt(key, upi, n); @@ -326,15 +326,6 @@ int main(int argc, char *argv[]) { SSL_write(ssl, upi, strlen(upi)); else send(new_fd, upi, strlen(upi), 0); - - char shutdown[] = "!!shutdown"; - n = strlen(shutdown); - xor_encrypt(key, shutdown, n); - - if (sslon) - SSL_write(ssl, shutdown, 10); - else - send(new_fd, shutdown, 10, 0); } if (pw_change) { @@ -790,8 +781,8 @@ bool checkCredentials(char *user, char *pass) { user[strlen(user) - 1] = '\0'; - fp = fopen("cfg/users", "r+"); - fp_o = fopen("cfg/pwds", "w+"); + fp = fopen("conf/users", "r+"); + fp_o = fopen("conf/pwds", "w+"); if (fp == NULL) { printDebug("Failed to find user file in local directory, checking in /etc/shhchat..."); @@ -800,12 +791,26 @@ bool checkCredentials(char *user, char *pass) { if (fp == NULL) { printDebug("Failed to find user file...Exiting"); free(md5string); - fclose(fp_o); + if (fp_o != NULL) { + fclose(fp_o); + } return false; } using_etc = true; } + if (fp_o == NULL) { + fp_o = fopen("/etc/shhchat/pwds", "w+"); + + if (fp_o == NULL) { + printDebug("Failed to find pwd file...Exiting"); + if (fp != NULL) { + fclose(fp); + } + return false; + } + } + // Read contents of user file while ((read = getline(&line, &len, fp)) != -1) { // line[strlen(line) - 1] = '\0'; @@ -852,9 +857,9 @@ bool checkCredentials(char *user, char *pass) { fclose(fp); if (using_etc) { - rename("cfg/pwds", "/etc/shhchat/users"); + rename("/etc/shhchat/pwds", "/etc/shhchat/users"); } else { - rename("cfg/pwds", "cfg/users"); + rename("conf/pwds", "conf/users"); } return true; } @@ -873,7 +878,7 @@ int populateDbUsers(char *msg) { size_t len = 0; ssize_t read; - fp = fopen("cfg/users", "r"); + fp = fopen("conf/users", "r"); if (fp == NULL) { printDebug("Failed to find user file in local directory, checking in /etc/shhchat...");