From d9ee2c56f2a26c4d26bfea48099ae1e04c3f6317 Mon Sep 17 00:00:00 2001 From: Lorenzo Torres Date: Thu, 8 Jan 2026 12:40:03 +0100 Subject: [PATCH] project skeleton --- .gitignore | 3 ++ Makefile | 55 ++++++++++++++++++++++++++++++++++++ client.h | 16 +++++++++++ config.def.h | 4 +++ config.mk | 26 +++++++++++++++++ main.c | 80 ++++++++++++++++++++++++++++++++++++++++++++++++++++ password.c | 43 ++++++++++++++++++++++++++++ password.h | 10 +++++++ 8 files changed, 237 insertions(+) create mode 100644 .gitignore create mode 100644 Makefile create mode 100644 client.h create mode 100644 config.def.h create mode 100644 config.mk create mode 100644 main.c create mode 100644 password.c create mode 100644 password.h diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c75cf2e --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +**/*.o +asfur +config.h diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..d3cdbef --- /dev/null +++ b/Makefile @@ -0,0 +1,55 @@ +# See LICENSE file for copyright and license details. + +include config.mk + +SRC = main.c\ + password.c +HDR = config.def.h client.h +OBJ = ${SRC:.c=.o} + +all: options asfur + +options: + @echo asfur build options: + @echo "CFLAGS = ${CFLAGS}" + @echo "LDFLAGS = ${LDFLAGS}" + @echo "CC = ${CC}" + +.c.o: + ${CC} -c ${CFLAGS} $< + +${OBJ}: config.h client.h + +config.h: + cp config.def.h $@ + +users.h: + cp users.def.h $@ + +asfur: ${OBJ} + ${CC} -o $@ ${OBJ} ${LDFLAGS} + +clean: + rm -f asfur ${OBJ} asfur-${VERSION}.tar.gz + +dist: clean + mkdir -p asfur-${VERSION} + cp -R LICENSE Makefile README config.mk\ + asfur.1 ${HDR} ${SRC} asfur-${VERSION} + tar -cf asfur-${VERSION}.tar asfur-${VERSION} + gzip asfur-${VERSION}.tar + rm -rf asfur-${VERSION} + +install: all + mkdir -p ${DESTDIR}${PREFIX}/bin + cp -f asfur ${DESTDIR}${PREFIX}/bin + chmod 755 ${DESTDIR}${PREFIX}/bin/asfur + mkdir -p ${DESTDIR}${MANPREFIX}/man1 + sed "s/VERSION/${VERSION}/g" < asfur.1 > ${DESTDIR}${MANPREFIX}/man1/asfur.1 + chmod 644 ${DESTDIR}${MANPREFIX}/man1/asfur.1 + +uninstall: + rm -f ${DESTDIR}${PREFIX}/bin/asfur\ + ${DESTDIR}${MANPREFIX}/man1/asfur.1 + +.PHONY: all options clean dist install uninstall diff --git a/client.h b/client.h new file mode 100644 index 0000000..ef2f89a --- /dev/null +++ b/client.h @@ -0,0 +1,16 @@ +#ifndef CLIENT_H +#define CLIENT_H + +#include +#include +#include + +struct client { + uv_tcp_t handle; + uint32_t user_id; + uint32_t current_room_id; + bool is_authenticated; + char username[32]; +}; + +#endif diff --git a/config.def.h b/config.def.h new file mode 100644 index 0000000..6359ca9 --- /dev/null +++ b/config.def.h @@ -0,0 +1,4 @@ +/* See LICENSE file for copyright and license details. */ + +#define CONFIG_ALLOW_REGISTER true + diff --git a/config.mk b/config.mk new file mode 100644 index 0000000..0215fc5 --- /dev/null +++ b/config.mk @@ -0,0 +1,26 @@ +# asfur version +VERSION = 0.1 + +# Customize below to fit your system + +# paths +PREFIX = /usr +MANPREFIX = ${PREFIX}/share/man + +# OpenBSD (uncomment) +#MANPREFIX = ${PREFIX}/man + +# includes and libs +INCS = -I. +LIBS = -lssl -lcrypto -lcrypt -luv +# flags +CFLAGS := -std=c11 -pedantic -Wall -O0 ${INCS} -DVERSION=\"${VERSION}\" +CFLAGS := ${CFLAGS} -g +LDFLAGS = ${LIBS} + +# Solaris +#CFLAGS = -fast ${INCS} -DVERSION=\"${VERSION}\" +#LDFLAGS = ${LIBS} + +# compiler and linker +CC = cc diff --git a/main.c b/main.c new file mode 100644 index 0000000..089a738 --- /dev/null +++ b/main.c @@ -0,0 +1,80 @@ +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include "client.h" + +uv_loop_t *loop; + +void alloc_buffer(uv_handle_t *handle, size_t suggested_size, uv_buf_t *buf) +{ + (void)handle; + buf->base = (char*) malloc(suggested_size); + buf->len = suggested_size; +} + +void echo_write(uv_write_t *req, int status) +{ + if (status) { + fprintf(stderr, "Write error %s\n", uv_strerror(status)); + } + free(req); +} + +void on_close(uv_handle_t *handle) +{ + free(handle); +} + +void on_read(uv_stream_t *client, ssize_t nread, const uv_buf_t *buf) +{ + if (nread > 0) { + uv_write_t *req = (uv_write_t *) malloc(sizeof(uv_write_t)); + uv_buf_t wrbuf = uv_buf_init(buf->base, nread); + uv_write(req, client, &wrbuf, 1, echo_write); + } + if (nread < 0) { + if (nread != UV_EOF) + fprintf(stderr, "Read error %s\n", uv_err_name(nread)); + uv_close((uv_handle_t*) client, on_close); + } + free(buf->base); +} + +void on_new_connection(uv_stream_t *server, int status) +{ + if (status < 0) { + fprintf(stderr, "New connection error %s\n", uv_strerror(status)); + return; + } + + struct client *client = malloc(sizeof(struct client)); + uv_tcp_init(loop, &client->handle); + if (uv_accept(server, (uv_stream_t*) &client->handle) == 0) { + uv_read_start((uv_stream_t*) &client->handle, alloc_buffer, on_read); + } else { + uv_close((uv_handle_t*) &client->handle, on_close); + } +} + +int main() +{ + loop = uv_default_loop(); + + uv_tcp_t server; + uv_tcp_init(loop, &server); + + struct sockaddr_in addr; + uv_ip4_addr("0.0.0.0", 7000, &addr); + + uv_tcp_bind(&server, (const struct sockaddr*)&addr, 0); + int r = uv_listen((uv_stream_t*) &server, 128, on_new_connection); + + if (r) { + fprintf(stderr, "Listen error %s\n", uv_strerror(r)); + return 1; + } + return uv_run(loop, UV_RUN_DEFAULT); +} diff --git a/password.c b/password.c new file mode 100644 index 0000000..7d5ed04 --- /dev/null +++ b/password.c @@ -0,0 +1,43 @@ +#define _GNU_SOURCE +#include +#include +#include +#include +#include + +void generate_salt(char *salt_buffer) +{ + const char *charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789./"; + salt_buffer[0] = '$'; + salt_buffer[1] = '6'; // SHA-512 + salt_buffer[2] = '$'; + + srand(time(NULL)); + for (int i = 3; i < 19; i++) { + salt_buffer[i] = charset[rand() % 64]; + } + salt_buffer[19] = '$'; + salt_buffer[20] = '\0'; +} + +char* hash_password(const char *password) +{ + struct crypt_data data; + data.initialized = 0; + + char salt[21]; + generate_salt(salt); + + char *hash = crypt_r(password, salt, &data); + return hash ? strdup(hash) : NULL; +} + +int verify_password(const char *password, const char *stored_hash) +{ + struct crypt_data data; + data.initialized = 0; + + char *calculated = crypt_r(password, stored_hash, &data); + + return (calculated && strcmp(calculated, stored_hash) == 0); +} diff --git a/password.h b/password.h new file mode 100644 index 0000000..29e8155 --- /dev/null +++ b/password.h @@ -0,0 +1,10 @@ +#ifndef PASSWORD_H +#define PASSWORD_H + +void generate_salt(char *salt_buffer); +/* Returns a malloc'd string containing the full hash (including salt) */ +char* hash_password(const char *password); +/* Returns 1 if match, 0 if fail */ +int verify_password(const char *password, const char *stored_hash); + +#endif