summaryrefslogtreecommitdiff
path: root/talkserver.c
diff options
context:
space:
mode:
authorthing 1 <thing1@seacrossedlovers.xyz>2024-12-10 08:35:59 +0000
committerthing 1 <thing1@seacrossedlovers.xyz>2024-12-10 08:35:59 +0000
commit4dd9290648ccb0d5fa19df956f970dda9afd9db7 (patch)
tree6e3927fca87daaf925d4630d263442a1b4ea68ea /talkserver.c
init commit of talk and talk serverHEADmaster
Diffstat (limited to 'talkserver.c')
-rw-r--r--talkserver.c177
1 files changed, 177 insertions, 0 deletions
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 <unistd.h>
+#include <stdio.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <openssl/sha.h>
+
+#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;
+}