From 4dd9290648ccb0d5fa19df956f970dda9afd9db7 Mon Sep 17 00:00:00 2001 From: thing 1 Date: Tue, 10 Dec 2024 08:35:59 +0000 Subject: init commit of talk and talk server --- .gitignore | 5 ++ Makefile | 32 +++++++++++ passwd | 2 + talk.c | 142 +++++++++++++++++++++++++++++++++++++++++++++++ talk.h | 19 +++++++ talkserver.c | 177 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ util.c | 38 +++++++++++++ util.h | 4 ++ 8 files changed, 419 insertions(+) create mode 100644 .gitignore create mode 100644 Makefile create mode 100644 passwd create mode 100644 talk.c create mode 100644 talk.h create mode 100644 talkserver.c create mode 100644 util.c create mode 100644 util.h diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..bcd5c10 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +*.o +users/* +talk +talkserver + diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..4a42e1a --- /dev/null +++ b/Makefile @@ -0,0 +1,32 @@ +CC=cc +CFLAGS=-ggdb +SERVERLDFLAGS=`pkg-config --libs openssl` +LDFLAGS= + +SRC = talk.c talkserver.c util.c +OBJ = $(SRC:.c=.o) + +all: talk talkserver + +.c.o: + $(CC) -c $(CFLAGS) $< + +talk: talk.o util.o + $(CC) -o $@ talk.o util.o $(LDFLAGS) + +talkserver: talkserver.o util.o + $(CC) -o $@ talkserver.o util.o $(SERVERLDFLAGS) + +clean: + rm -f $(OBJ) talk talkserver + rm -rf users + +install: all + cp talk /usr/local/bin/talk + cp talkserver /usr/local/bin/talkserver + +uninstall: + rm /usr/local/bin/talkserver + rm /usr/local/bin/talk + +.PHONY: all clean dist install uninstall diff --git a/passwd b/passwd new file mode 100644 index 0000000..282720f --- /dev/null +++ b/passwd @@ -0,0 +1,2 @@ +thing1:n¢@×(¹»ñuz Jbêz? +thing2:n¢@×(¹»ñuz Jbêz? diff --git a/talk.c b/talk.c new file mode 100644 index 0000000..03b94dd --- /dev/null +++ b/talk.c @@ -0,0 +1,142 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "talk.h" +#include "util.h" + +char *hostip; +int port = 231; +char *username = "(null)"; +char *password = "(null)"; +char *recipient = "(null)"; +packettype mode = MSG; + +static int initsocket(struct sockaddr_in address, socklen_t len){ + int s; + if ((s = socket(AF_INET, SOCK_STREAM, 0)) == -1){ + perror("socket"); + return -1; + } + if ((connect(s, (struct sockaddr *)&address, len)) != 0) { + perror("connect"); + return -1; + } + + return s; +} + +static void processargs(int argc, char **argv){ + // -h specify the host of the server + // -P specify the port // default 231 + // -u specify the username + // -p specify the password + // -r specify the recipient + // -g get mode + // -R register mode + for (int i = 1; i < argc; i++){ + if (strcmp(argv[i], "-h") == 0){ + i++; + hostip = argv[i]; + } else if (strcmp(argv[i], "-P") == 0){ + i++; + port = atoi(argv[i]); + } else if (strcmp(argv[i], "-u") == 0){ + i++; + username = argv[i]; + } else if (strcmp(argv[i], "-p") == 0){ + i++; + password = argv[i]; + } else if (strcmp(argv[i], "-r") == 0){ + i++; + recipient = argv[i]; + } else if (strcmp(argv[i], "-g") == 0){ + mode = GET; + } else if (strcmp(argv[i], "-R") == 0){ + mode = NEWUSER; + } + else { + fprintf(stderr, "unknown option: %s\n", argv[i]); + exit(1); + } + } + if (hostip == NULL) { + fprintf(stderr, "no host given!\n"); + exit(1); + } + if (strcmp(username, "(null)") == 0){ + fprintf(stderr, "no username given!\n"); + exit(1); + } + if (strcmp(password, "(null)") == 0){ + fprintf(stderr, "no password given!\n"); + exit(1); + } + if (mode == GET && strcmp(recipient, "(null)") == 0){ + fprintf(stderr, "recipient is needed when requesting from an individual!\n"); + exit(1); + } + if (mode == MSG && strcmp(recipient, "(null)") == 0){ + fprintf(stderr, "recipient is needed when sending to an individual!\n"); + exit(1); + } +} + +int main(int argc, char **argv){ + processargs(argc, argv); + + struct sockaddr_in address; + address.sin_family = AF_INET; + inet_pton(AF_INET, hostip, &address.sin_addr); + address.sin_port = htons(port); + socklen_t len = sizeof(address); + + int s; + if ((s = initsocket(address, len)) < 0) return s; + + int size = sizeof(packet); + packet *buf = malloc(size); + strcpy(buf->username, username); + strcpy(buf->password, password); + strcpy(buf->recipient, recipient); + buf->type = mode; + + char *tmp; + if (buf->type == MSG){ + tmp = readupto(stdin, '\n'); + buf->msg = tmp; + buf->msglen=strlen(buf->msg); + send(s, buf, size, 0); + send(s, buf->msg, buf->msglen, 0); + free(tmp); + } else send(s, buf, size, 0); + + + + recv(s, buf, size, 0); + switch (buf->type){ + case USERMAKEERROR: fprintf(stderr, "failed to create new user on server!\n"); break; + case UNKNOWNCMD: fprintf(stderr, "unknown cmd!\n"); break; + case PASSAUTHFAIL: fprintf(stderr, "failed to authenticate password!\n"); break; + case NOSUCHUSER: fprintf(stderr, "user not found, either you tried to msg someone who doesn't exist or you don't exist!\n"); break; + case NEVERMSGED: fprintf(stderr, "you have never messaged that user, or have no new messages from them!\n"); break; + case GET: + tmp = calloc(1, buf->msglen); + recv(s, tmp, buf->msglen, 0); + printf("%s", tmp); + free(tmp); + break; + } + + + + close(s); + + + return 0; +} diff --git a/talk.h b/talk.h new file mode 100644 index 0000000..1f83fdc --- /dev/null +++ b/talk.h @@ -0,0 +1,19 @@ +typedef enum packettype { + MSG = 0, + GET = 1, + NEWUSER = 2, + USERMAKEERROR = 3, + UNKNOWNCMD = 4, + PASSAUTHFAIL = 5, + NOSUCHUSER = 6, + NEVERMSGED = 7, +} packettype; + +typedef struct packet { + packettype type; + char username[30]; + char password[30]; + char recipient[30]; + int msglen; + char *msg; +} packet; diff --git a/talkserver.c b/talkserver.c new file mode 100644 index 0000000..f96a8b7 --- /dev/null +++ b/talkserver.c @@ -0,0 +1,177 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "talk.h" +#include "util.h" + +#define PORT 231 + +#define USERSDIR "./users/" +#define PASSWORDFILE "./passwd" + +static int initsocket(struct sockaddr_in address, socklen_t len){ + int s; + if ((s = socket(AF_INET, SOCK_STREAM, 0)) == -1){ + perror("socket"); + return -1; + } + if ((bind(s, (struct sockaddr *)&address, len)) != 0) { + perror("bind"); + return -1; + } + + listen(s, 10); + return s; +} + +static bool checkpasswd(char *username, char *password) { + char *passwdline, *tok; + unsigned char hash[SHA_DIGEST_LENGTH]; + FILE *f = fopen(PASSWORDFILE, "r"); + + while ((passwdline = readupto(f, ':')) != NULL){ + tok = readnchars(f, 20); + if (strcmp(passwdline, username) == 0){ + SHA1((unsigned char *)password, 30, hash); + if (memcmp((char *)hash, tok, 20) == 0){ + free(tok); + free(passwdline); + return true; + } else { + free(tok); + free(passwdline); + return false; + } + } + free(tok); + free(passwdline); + } + return false; +} + +int main(){ + struct sockaddr_in address; + address.sin_family = AF_INET; + address.sin_addr.s_addr = INADDR_ANY; + address.sin_port = htons(PORT); + socklen_t len = sizeof(address); + + int s; + if ((s = initsocket(address, len)) < 0) return s; + + int client; + for (;;) { + if ((client = accept(s, (struct sockaddr *)&address, &len)) == -1){ + perror("accept"); + return 1; + } + + int size = sizeof(packet); + packet *buf = malloc(size); + recv(client, buf, size, 0); + + char *userdir, *tok, *passwdline, *msg; + unsigned char hash1[SHA_DIGEST_LENGTH], hash2[SHA_DIGEST_LENGTH]; + FILE *f, *fmsg; + int len; + + switch (buf->type){ + case MSG: + buf->msg = calloc(1, buf->msglen); + recv(client, buf->msg, buf->msglen, 0); + + if (checkpasswd(buf->username, buf->password) == true){ + if (buf->msg == NULL || strlen(buf->msg) == 0) { + buf->msg = "(null)"; + goto end; + } + userdir = malloc(80); + snprintf(userdir, 80, "%s%s/%s", USERSDIR, buf->recipient, buf->username); + fmsg = fopen(userdir, "a+"); + if (fmsg == NULL) goto nosuchuser; + fprintf(fmsg, "%s\n", buf->msg); + fclose(fmsg); + free(userdir); + goto end; + } else { + buf->type = PASSAUTHFAIL; + goto end; + } + +nosuchuser: + buf->type = NOSUCHUSER; +end: + send(client, buf, size, 0); + break; + case GET: + if (checkpasswd(buf->username, buf->password) == true){ + len = 128; + userdir = calloc(1, len); + snprintf(userdir, len, "%s%s/%s", USERSDIR, buf->username, buf->recipient); + + f = fopen(userdir, "r"); + if (f == NULL) { + buf->type = NEVERMSGED; + send(client, buf, size, 0); + break; + } + + msg = readupto(f, EOF); + buf->msg = msg; + buf->msglen = strlen(msg); + send(client, buf, size, 0); + send(client, buf->msg, buf->msglen, 0); + + remove(userdir); + + free(userdir); + userdir = NULL; + } else { + buf->type = PASSAUTHFAIL; + } + send(client, buf, size, 0); + + break; + case NEWUSER: + userdir = calloc(1, strlen(USERSDIR) + strlen(buf->username)); + strcat(userdir, USERSDIR); + strcat(userdir, buf->username); + + if (mkdir(userdir, 0777) == -1) { + buf->type = USERMAKEERROR; + } else { + buf->type = NEWUSER; + SHA1((unsigned char *)buf->password, 30, hash1); + f = fopen(PASSWORDFILE, "a+"); + if (f == NULL) exit(1); + fprintf(f, "%s:%s\n", buf->username, hash1); + fclose(f); + free(userdir); + userdir = NULL; + } + send(client, buf, size, 0); + break; + default: + buf->type = UNKNOWNCMD; + send(client, buf, size, 0); + break; + } + + free(buf->msg); + free(buf); + + close(client); + } + + + close(s); + + return 0; +} diff --git a/util.c b/util.c new file mode 100644 index 0000000..8073340 --- /dev/null +++ b/util.c @@ -0,0 +1,38 @@ +#include +#include +#include "talk.h" + +char *readupto(FILE *f, char end){ + char c; + char *out = malloc(128); + int counter = 0; + while ((c = fgetc(f)) != EOF){ + out[counter] = c; + if (c == end) break; + counter++; + if (counter > 128) out = realloc(out, counter + 128); + } + if (c == EOF && end != EOF) return NULL; + + out[counter] = 0; + out = realloc(out, counter); + + return out; +} + +char *readnchars(FILE *f, int n){ + char c; + char *out = malloc(128); + int counter = 0; + while ((c = fgetc(f)) != EOF && counter < n){ + out[counter] = c; + counter++; + if (counter > 128) out = realloc(out, counter + 128); + } + if (c == EOF) return NULL; + + out[counter] = 0; + out = realloc(out, counter); + + return out; +} diff --git a/util.h b/util.h new file mode 100644 index 0000000..e7685ff --- /dev/null +++ b/util.h @@ -0,0 +1,4 @@ +#include + +char *readupto(FILE *f, char end); +char *readnchars(FILE *f, int n); -- cgit v1.2.3