From 3681f2276a60de0d3b53940d67c10d707e47d34e Mon Sep 17 00:00:00 2001 From: chris laptop Date: Fri, 26 Dec 2014 10:04:05 +0000 Subject: [PATCH] Added colours to distinguish general messages and other client messages. Removed duplicate config files fixing #31. Messages received in the client from other clients will no longer output additional lines which fixes #32. Added chat logging command on client, debugs no longer use a log file. Improved client and server key file handling fixes #36. Tidied up shutdown command routines. Added git issues refs to 'todo' actions. Fixed code warnings found with oclint. Commented out websocket features for now ref #29. --- Makefile | 5 +- build/cfg/key | 1 - build/cfg/users | 3 - src/chatclient/client.c | 145 ++++++++++++++++++++++++----------- src/shhchatd/server.c | 163 +++++++++++++++++++++++----------------- 5 files changed, 197 insertions(+), 120 deletions(-) delete mode 100755 build/cfg/key delete mode 100755 build/cfg/users diff --git a/Makefile b/Makefile index 397ab99..993188e 100755 --- a/Makefile +++ b/Makefile @@ -3,6 +3,7 @@ CFLAGS=-lpthread --std=gnu99 SRC=src BIN=build CONF=conf +WS=-lwebsockets # Check for Linux environment ENV:=$(shell uname -s | cut -d _ -f1) @@ -14,7 +15,7 @@ endef all: $(os_check) rm -f $(BIN)/shhchatd $(BIN)/shhclient - $(CC) -o $(BIN)/shhchatd $(SRC)/shhchatd/server.c $(CFLAGS) -DVERSION='"_beta"' -lwebsockets + $(CC) -o $(BIN)/shhchatd $(SRC)/shhchatd/server.c $(CFLAGS) -DVERSION='"_beta"' $(CC) -o $(BIN)/shhclient $(SRC)/chatclient/client.c $(CFLAGS) -DVERSION='"_beta"' cp $(CONF)/* -t $(BIN)/cfg @echo Finished shhchat build @@ -26,7 +27,7 @@ clean: debug: $(os_check) rm -f $(BIN)/shhchatd $(BIN)/shhclient - $(CC) -o $(BIN)/shhchatd $(SRC)/shhchatd/server.c $(CFLAGS) -DDEBUG -lwebsockets -g + $(CC) -o $(BIN)/shhchatd $(SRC)/shhchatd/server.c $(CFLAGS) -DDEBUG -g $(CC) -o $(BIN)/shhclient $(SRC)/chatclient/client.c $(CFLAGS) -DDEBUG cp $(CONF)/* -t $(BIN)/cfg @echo Finished shhchat debug build diff --git a/build/cfg/key b/build/cfg/key deleted file mode 100755 index 9f358a4..0000000 --- a/build/cfg/key +++ /dev/null @@ -1 +0,0 @@ -123456 diff --git a/build/cfg/users b/build/cfg/users deleted file mode 100755 index 30672be..0000000 --- a/build/cfg/users +++ /dev/null @@ -1,3 +0,0 @@ -user1 -user2 -user3 diff --git a/src/chatclient/client.c b/src/chatclient/client.c index f135735..a1811a1 100755 --- a/src/chatclient/client.c +++ b/src/chatclient/client.c @@ -1,6 +1,5 @@ /* shhchat client -alpha */ #include @@ -21,22 +20,28 @@ alpha #define BUFFER_MAX 1024 #ifndef VERSION -#define VERSION "_debug" +#define VERSION "_beta" #endif -// Colours -#define RED "\033[22;31m" -#define RESET_COLOR "\e[m" +#define RED "\e[1;31m" +#define GREEN "\e[1;32m" +#define YELLOW "\e[1;33m" +#define BLUE "\e[1;34m" +#define RESET_COLOR "\e[0m" int sockfd, n, x, y, count; struct sockaddr_in serv_addr; char buffer[BUFFER_MAX]; char buf[10]; +char plain[] = ""; +char key[] = "123456"; +char serverKey[BUFFER_MAX]; void *interrupt_Handler(); void *chat_write(int); void *chat_read(int); void *zzz(); void printDebug(char *string); +void printLog(char *string); void writeLog(FILE *fp, char *str); void addYou(); void *xor_encrypt(char *key, char *string, int n); @@ -44,10 +49,9 @@ void initLog(char logname[]); int createPaths(char log_name_default[], char log_name_new[]); void exitLogError(); bool debugsOn = false; -char plain[] = ""; -char key[] = "123456"; +bool logsOn = false; +bool addedYou = false; FILE *fp_l; -char serverKey[BUFFER_MAX]; int main(int argc, char *argv[]) { pthread_t thr1, thr2; @@ -57,6 +61,7 @@ int main(int argc, char *argv[]) { size_t len = 0; ssize_t read; bool haveKey = false; + int buf_size; if (argc < 2) { printf("Usage: ./shhclient \n"); @@ -67,25 +72,37 @@ int main(int argc, char *argv[]) { port = atoi(argv[2]); } - printf("\e[1;34mshhchat client v%s started\n\e[0m", VERSION); - initLog ("shh_log"); - printDebug("Reading contents of config file\n"); - - // TODO Create the key file if it doesn't exist + printf("%sshhchat client v%s started\n%s", GREEN, VERSION, RESET_COLOR); + printDebug("Searching for key file...\n"); - // Try and open key file - fp = fopen("cfg/key", "r"); + // Find key file for use in current session + fp = fopen(".sshkey", "r"); if (fp == NULL) { - printDebug("Failed to read key file\n"); - exit(EXIT_FAILURE); + printf("%sKey file not found in current dir - Searching in standard build filepath...\n%s", GREEN, RESET_COLOR); + fp = fopen("cfg/key", "r"); + + if (fp == NULL) { + printf("%sKey file not found in current standard build dir - Searching in /etc/shhchat...\n%s", RED, RESET_COLOR); + fp = fopen("/etc/shhchat/key", "r"); + + if (fp == NULL) { + printf("%sKey file not found...Exiting\n%s", RED, RESET_COLOR); + exit(EXIT_FAILURE); + } + else { + printf("%sKey found in /etc/shhchat dir.\n%s", GREEN, RESET_COLOR); + } + } + else { + printf("%sKey found in cfg dir.\n%s", GREEN, RESET_COLOR); + } } // Read contents of key file while ((read = getline(&line, &len, fp)) != -1) { - // printf("Key found %zu :\n", read); - printDebug("Key found\n"); - strncpy(key, line, sizeof(line)); + buf_size = sizeof(line); + strncpy(key, line, buf_size); // Don't print key out! // printf("%s", key); haveKey = true; @@ -103,9 +120,7 @@ int main(int argc, char *argv[]) { sockfd = socket(AF_INET, SOCK_STREAM, 0); if (sockfd == -1) - printf ("Failed to open socket - Is the port already in use?\n"); - else - printf("\e[1;34mSocket opened.\n\e[0m"); + printf ("%sFailed to open socket - Is the port already in use?\n%s", RED, RESET_COLOR); bzero((char *) &serv_addr, sizeof(serv_addr)); serv_addr.sin_family = AF_INET; @@ -113,17 +128,16 @@ int main(int argc, char *argv[]) { serv_addr.sin_addr.s_addr = inet_addr(argv[1]); bzero(buf, 10); - printf("\e[1;34mChoose username for this chat session: \e[0m"); + printf("Choose username for this chat session: "); fgets(buf, 10, stdin); __fpurge(stdin); buf[strlen(buf)-1] = ':'; if (connect(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) == -1) { - printf("Failed to connect - Is the server running?\n"); + printf("%sFailed to connect - Is the server running?\n%s", RED, RESET_COLOR); exit(0); - } - else - printf("%s connected.\n",buf); + } else + printf("%s%s connected.\n%s", GREEN, buf, RESET_COLOR); addYou(); @@ -149,7 +163,7 @@ void *chat_read(int sockfd) { n = recv(sockfd, buffer, sizeof(buffer), 0); if (n == 0) { - printf("Lost connection to the server.\n\n"); + printf("%sLost connection to the server.\n\n%s", RED, RESET_COLOR); exit(0); } @@ -158,9 +172,8 @@ void *chat_read(int sockfd) { y = n; xor_encrypt(key, buffer, y); - // TODO Add '!!' - if (strncmp(buffer, "shutdown", 8) == 0) { - printf("\n"); + if (strncmp(buffer, "!!shutdown", 10) == 0) { + printf("%s\nServer has shutdown.\n%s", GREEN, RESET_COLOR); exit(0); } @@ -170,11 +183,19 @@ void *chat_read(int sockfd) { continue; } - printf("\n%s", buffer); + if (addedYou) { + printLog(buffer); + printf("\r%s%s%s", BLUE, buffer, RESET_COLOR); + } else { + printf("\n%s%s%s", BLUE, buffer, RESET_COLOR); + addedYou = false; + } + fflush(stdout); addYou(); } } + return 0; } void *chat_write(int sockfd) { @@ -184,24 +205,28 @@ void *chat_write(int sockfd) { // Continuously read from stdin clear = true; bzero(buffer, BUFFER_MAX); + fflush(stdout); __fpurge(stdin); fgets(buffer, sizeof(buffer), stdin); if (strlen(buffer)-1 > sizeof(buffer)) { - printf("\e[1;34mBuffer full, reduce size of message.\n\e[0m"); + printf("%sBuffer full, reduce size of message.%s\n", GREEN, RESET_COLOR); bzero(buffer, BUFFER_MAX); __fpurge(stdin); } if (strlen(buffer) > 1) { + // ======================== + // Server Side Requests + if (strncmp(buffer, "??who", 5) == 0) { - printf("\e[1;34mUser's currently connected:\e[0m"); + printf("%sUser's currently connected:%s\n", GREEN, RESET_COLOR); clear = false; } if (strncmp(buffer, "??list", 6) == 0) { - printf("\e[1;34mUser's in db:\e[0m"); + printf("%sUser's in db:%s\n", GREEN, RESET_COLOR); clear = false; } @@ -209,6 +234,29 @@ void *chat_write(int sockfd) { exit(0); } + // End Server Side Requests + // ======================== + + + // ================== + // Local Requests + + if (strncmp(buffer, "??logon", 7) == 0) { + logsOn = true; + initLog ("shh_log"); + continue; + } + + if (strncmp(buffer, "??logoff", 8) == 0) { + logsOn = false; + continue; + } + + // End Local Requests + // ================== + + printLog(buffer); + char *tmp = strdup(buffer); strncpy(buffer, serverKey, sizeof(serverKey)); strcat(buffer, tmp); @@ -218,8 +266,7 @@ void *chat_write(int sockfd) { y = strlen(buffer); xor_encrypt(key, buffer, y); n = send(sockfd, buffer, y, 0); - } - else + } else __fpurge(stdin); bzero(buffer, BUFFER_MAX); @@ -227,20 +274,25 @@ void *chat_write(int sockfd) { if (clear) addYou(); } + return 0; } void *interrupt_Handler() { - printf("\rType '??quit' to exit.\n"); + printf("\r%sType '??quit' to exit.\n%s", YELLOW, RESET_COLOR); + return 0; } void *zzz() { - printf("\rType '??quit' to exit.\n"); + printf("\r%sType '??quit' to exit.\n%s", YELLOW, RESET_COLOR); + return 0; } void printDebug(char *string) { - // If debugs not on, write to log file if (debugsOn) - printf(string); - else + printf("%s", string); +} + +void printLog(char *string) { + if (logsOn) writeLog(fp_l, string); } @@ -249,7 +301,7 @@ void initLog(char logname[]) { char log_name_default[1024] = "/"; char log_name_new[1024] = "/"; - // TODO Check if there are over 5 logfiles and if so remove the oldest before adding a new one + // TODO #34 - Check if there are over 5 log files and if so remove the oldest before adding a new one strncat(log_name_default, logname, strlen(logname)); strncat(log_name_new, logname, strlen(logname)); @@ -258,6 +310,7 @@ void initLog(char logname[]) { if (createPaths(log_name_default, log_name_new) == 0) exitLogError(); + // TODO #35 - Handle error while copying result = rename(log_name_default, log_name_new); // Open log file @@ -289,7 +342,7 @@ int createPaths(char log_name_default[], char log_name_new[]) { } void exitLogError() { - printf("Log file error, shutting down.\n"); + printf("%sLog file error, shutting down.\n%s", RED, RESET_COLOR); exit(0); } @@ -298,6 +351,7 @@ void writeLog(FILE *fp, char *str) { } void addYou() { + addedYou = true; printf("You: "); } @@ -309,5 +363,6 @@ void *xor_encrypt(char *key, char *string, int n) { for (i = 0;i < n;i++) { string[i] = string[i]^key[i%keyLength]; } + return 0; } diff --git a/src/shhchatd/server.c b/src/shhchatd/server.c index 04873af..cd4dd1f 100755 --- a/src/shhchatd/server.c +++ b/src/shhchatd/server.c @@ -1,6 +1,5 @@ /* shhchat server -alpha */ #include @@ -17,8 +16,8 @@ alpha #include #include #include -#include -#include "shhchat_ws.h" +//#include +//#include "shhchat_ws.h" #define BACKLOG 100 #define BUFFER_MAX 1024 @@ -37,8 +36,21 @@ struct client { char username[10]; unsigned int sessionId; struct client *next; + char su; }; +/* +TODO #37 - Superuser actions +su privs: +=================================================== +level name prefix actions +=================================================== + 0 (none) n/a n/a + 1 (mod) + kick users + 2 (admin) @ change user db +=================================================== +*/ + typedef struct client *ptrtoclient; typedef ptrtoclient clients; typedef ptrtoclient addr; @@ -95,12 +107,13 @@ static void start_daemon() { for (x = sysconf(_SC_OPEN_MAX); x>0; x--) { close(x); } + openlog("shhchatd", 0, LOG_USER); syslog(LOG_INFO, "%s", "Server daemon started."); } int main(int argc, char *argv[]) { - int socket_fd, new_fd, portnum, cli_size, z; + int socket_fd, new_fd, portnum, cli_size, buf_size; struct sockaddr_in server_addr; struct sockaddr_in client_addr; pthread_t thr; @@ -129,20 +142,26 @@ int main(int argc, char *argv[]) { printDebug("Reading contents of config file."); - // TODO Create cfg if it doesn't exist + // TODO #11 - Create cfg if it doesn't exist // Try and open key file fp = fopen("cfg/key", "r"); if (fp == NULL) { - printDebug("Failed to read key file."); - exit(EXIT_FAILURE); + printDebug("Failed to read key file in standard build dir, checking in /etc/shhchat..."); + fp = fopen("/etc/shhchat/key", "r"); + + if (fp == NULL) { + printDebug("Failed to read key file...Exiting"); + exit(EXIT_FAILURE); + } } // Read contents of key file while ((read = getline(&line, &len, fp)) != -1) { printDebug("Key found."); - strncpy(key, line, sizeof(line)); + buf_size = sizeof(line); + strncpy(key, line, buf_size); if (debugsOn) printf("%s", key); @@ -200,13 +219,12 @@ int main(int argc, char *argv[]) { if (bind(socket_fd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) == -1) { syslog(LOG_INFO, "%s", "Failed to bind."); exit(1); - } - else + } else syslog(LOG_INFO, "%s", "Port binded."); listen(socket_fd, BACKLOG); - // Create a WebSocket thread + // TODO #29 - Create a WebSocket thread // pthread_create(&thr, NULL, webInit, portnum); // pthread_detach(thr); @@ -214,51 +232,52 @@ int main(int argc, char *argv[]) { if (signal(SIGTSTP, showConnected) == 0) while (1) { cli_size = sizeof(struct sockaddr_in); - new_fd = accept(socket_fd, (struct sockaddr *)&client_addr, &cli_size); + new_fd = accept(socket_fd, (struct sockaddr *)&client_addr, (socklen_t*)&cli_size); a = h; bzero(username, 10); bzero(buffer, BUFFER_MAX); - if (recv(new_fd, username, sizeof(username), 0) > 0); - n = strlen(username); - xor_encrypt(key, username, n); + if (recv(new_fd, username, sizeof(username), 0) > 0) { + n = strlen(username); + xor_encrypt(key, username, n); - username[strlen(username)-1] = ':'; - sprintf(buffer, "%s logged in\n", username); + username[strlen(username)-1] = ':'; + sprintf(buffer, "%s logged in\n", username); - // Check user hasn't already logged in - if (checkConnected(h, username)) { - char shutdown[] = "shutdown"; - n = strlen(shutdown); - xor_encrypt(key, shutdown, n); - send(new_fd, shutdown, 13, 0); - } - - addClient(new_fd, username, h, a); - - a = a->next; - unsigned int tmp = a->sessionId; - a = h; - - do { - a = a->next; - sf2 = a->port; - if (sf2 != new_fd) { - n = strlen(buffer); - xor_encrypt(key, buffer, n); - send(sf2, buffer, n, 0); + // Check user hasn't already logged in + if (checkConnected(h, username)) { + char shutdown[] = "!!shutdown"; + n = strlen(shutdown); + xor_encrypt(key, shutdown, n); + send(new_fd, shutdown, 10, 0); } - } while (a->next != NULL); - if (debugsOn) - printf("Connection made from %s\n\n", inet_ntoa(client_addr.sin_addr)); + addClient(new_fd, username, h, a); - struct client args; - args.port = new_fd; - args.sessionId = tmp; - strncpy(args.username, username, sizeof(username)); - pthread_create(&thr, NULL, server, (void*)&args); - pthread_detach(thr); + a = a->next; + unsigned int tmp = a->sessionId; + a = h; + + do { + a = a->next; + sf2 = a->port; + if (sf2 != new_fd) { + n = strlen(buffer); + xor_encrypt(key, buffer, n); + send(sf2, buffer, n, 0); + } + } while (a->next != NULL); + + if (debugsOn) + printf("Connection made from %s\n\n", inet_ntoa(client_addr.sin_addr)); + + struct client args; + args.port = new_fd; + args.sessionId = tmp; + strncpy(args.username, username, sizeof(username)); + pthread_create(&thr, NULL, server, (void*)&args); + pthread_detach(thr); + } } removeAllClients(h); close(socket_fd); @@ -268,26 +287,25 @@ int main(int argc, char *argv[]) { // Server side handling for each connected client void *server(void * arguments) { struct client *args = arguments; - char buffer[BUFFER_MAX], ubuf[BUFFER_MAX], uname[10], keybuf[BUFFER_MAX]; + char buffer[BUFFER_MAX], uname[10], keybuf[BUFFER_MAX]; char *strp; char *msg = (char *) malloc(BUFFER_MAX); char keystr[] = "!!key"; - int ts_fd, x, y, sfd, msglen; + int ts_fd, x, y, sfd, msglen, buf_size; unsigned int sessionId; ts_fd = args->port; strncpy(uname, args->username, sizeof(args->username)); addr a; a = h; sessionId = args->sessionId; + /* Server Control Commands:- * ??quit - disconnects from chat session * ??who - query who is connected * ??list - list all users in db - * ??logon - enable current session logging TODO - * ??logoff - disable current session logging TODO - * ??sup - gain superuser rights TODO - * ?!kick - kick user (requires ??sup) TODO + * ??sup - gain superuser rights TODO #37 + * ?!kick - kick user (requires ??sup) TODO #37 */ if (!checkUser(uname)) { @@ -312,6 +330,7 @@ void *server(void * arguments) { uname[strlen(uname)] = ' '; /* + ubuf[BUFFER_MAX] bzero(ubuf,BUFFER_MAX); do { a = a->next; @@ -353,6 +372,7 @@ void *server(void * arguments) { if (strncmp(buffer, "??who", 5) == 0) { addr a = h; bzero(msg, BUFFER_MAX); + do { a = a->next; sfd = a->port; @@ -423,7 +443,8 @@ void *server(void * arguments) { x = strlen(msg); strp = msg; strp += x; - strncat(strp, buffer, sizeof(buffer)); + buf_size = sizeof(buffer); + strncat(strp, buffer, buf_size); msglen = strlen(msg); addr a = h; @@ -479,19 +500,22 @@ void removeAllClients(clients h) { } void addClient(int port, char *username, clients h, addr a) { - addr TmpCell; - TmpCell = malloc(sizeof(struct client)); + addr tmpcell; + tmpcell = malloc(sizeof(struct client)); unsigned int rangen = (unsigned int)time(NULL); + int buf_size; srand(rangen); - if (TmpCell == NULL) + if (tmpcell == NULL) syslog(LOG_INFO, "%s", "Max connections reached."); - TmpCell->port = port; - TmpCell->sessionId = rand(); - strncpy(TmpCell->username, username, sizeof(username)); - TmpCell->next = a->next; - a->next = TmpCell; + tmpcell->su = 0; + tmpcell->port = port; + tmpcell->sessionId = rand(); + buf_size = sizeof(username); + strncpy(tmpcell->username, username, buf_size); + tmpcell->next = a->next; + a->next = tmpcell; } void displayConnected(const clients h) { @@ -561,10 +585,10 @@ void disconnectAllClients() { i++; a = a->next; sfd = a->port; - char shutdown[] = "shutdown"; + char shutdown[] = "!!shutdown"; n = strlen(shutdown); xor_encrypt(key, shutdown, n); - send(sfd, shutdown, 13, 0); + send(sfd, shutdown, 10, 0); } while (a->next != NULL); printf("%d clients closed.\n\n", i); @@ -593,6 +617,7 @@ bool checkUser(char *user) { ssize_t read; char *tmp = NULL; char *tempUser = NULL; + int buf_size; tempUser = user; tempUser[strlen(tempUser) - 1] = '\0'; @@ -607,8 +632,9 @@ bool checkUser(char *user) { // Read contents of user file while ((read = getline(&line, &len, fp)) != -1) { line[strlen(line) - 1] = '\0'; + buf_size = sizeof(tempUser); - if (strncmp(line, tempUser, sizeof(tempUser)) == 0) { + if (strncmp(line, tempUser, buf_size) == 0) { // printf("Found user %s.", tempUser); fclose(fp); return true; @@ -642,9 +668,7 @@ int populateDbUsers(char *msg) { return 1; } -// TODO chat logging routine - -// WebSocket Init +/* TODO #29 - WebSocket support void *webInit(void * arguments) { int port = atoi(arguments); struct lws_context_creation_info info; @@ -688,4 +712,5 @@ void *webInit(void * arguments) { libwebsocket_context_destroy(context); exit(1); -} \ No newline at end of file +} +*/ \ No newline at end of file