#define _GNU_SOURCE #include "login.h" #include "data.h" #include "server.h" #include "util.h" #include #include #include #include #include #include void handle_player(int conn_fd) { debug("Let's make a new player object\n"); playerc_t plrc = {0}; plrc.state = LoggedOut; plrc.conn = conn_fd; player_t plr = {0}; plrc.plr = plr; debug("No sense in having a player if they can't log in!\n"); int err = step_login(&plrc, conn_fd); if (err) { err = send_to_fd(conn_fd, "Error in login process, exiting"); if (err) { error("Could not send error message"); } close(conn_fd); return; } close(conn_fd); } int step_login(playerc_t *player, int conn_fd) { int err = 0; for (;;) { switch (player->state) { case LoggedOut: ; /* the player has yet to log in, this is a fresh connection! */ debug("The player is logged out\n"); send_to_fd(player->conn, "Welcome! Please enter your **username** below\n"); char *buf = (char *)malloc(1 << 10); debug("Waiting to receive...\n"); recv(player->conn, buf, 1024, 0); debug("Received!\n"); char* playername = trimwhitespace(buf); err = try_load_plr(playername, player); debug("Finished trying to load the player\n"); if (err) { // File doesn't exist, let's create a player! player->plr.name = (char *)malloc(32); strcpy(player->plr.name, playername); send_to_fd(player->conn, "Howdy! Want to introduce yourself? [y|n]\n"); recv(player->conn, buf, sizeof(buf), 0); if (buf[0] == 'y') { player->state = WantMakeAccount; break; } else if (buf[0] == 'n') { send_to_fd(player->conn, "Awww :(. Oh well, hope to see you again soon!\n"); return 4; } break; } else { player->state = EnterPassword; break; } case EnterPassword: ; asprintf(&buf, "Welcome back %s! Please enter your password, so we can confirm it.\n", player->plr.name); send_to_fd(player->conn, buf); memset(buf, '\0', 1 << 9); recv(player->conn, buf, sizeof(buf), 0); char* pw = trimwhitespace(buf); int res = argon2i_verify(player->plr.pw_hash, pw, strlen(pw)); if (res == ARGON2_OK) { // The password is good! send_to_fd(player->conn, "That looks good to me! Let's get you loaded in\n"); player->state = Complete; } else { // Password is incorrect send_to_fd(player->conn, "Password incorrect, please try again\n"); break; } break; case WantMakeAccount: asprintf(&buf, "Welcome aboard %s! Why don't you start us off by giving me a password.\n", player->plr.name); send_to_fd(player->conn, buf); memset(buf, '\0', 1 << 9); recv(player->conn, buf, sizeof(buf), 0); if (strlen(buf) <= 5) { send_to_fd(player->conn, "We're sorry, but passwords need to be at least 5 characters"); } else { player->plr.pw_hash = (char *)malloc(512); char* pw = trimwhitespace(buf); err = argon2i_hash_encoded(32, 512, 1, pw, strlen(pw), "adSAaVWIueBwP2jHfAl7diRJ9ijC1Ysb9e920d6d9+I=", strlen("adSAaVWIueBwP2jHfAl7diRJ9ijC1Ysb9e920d6d9+I="), 32, player->plr.pw_hash, 512); if (err != ARGON2_OK) { send_to_fd(player->conn, "Uhhh, something happened. Try again."); player->state = LoggedOut; break; } else { send_to_fd(player->conn, "Sounds good! let's drop you into a world!"); player->state = Complete; player->plr.hp = player->plr.max_hp = 20; player->plr.level = 1; player->plr.xp = 0; player->plr.location_id = 0; debug("Trying to write player\n"); try_write_plr(&player->plr); debug("Done\n"); player->state = Complete; } } case Complete: ; return 0; } } return err; }