From 4a0c806d83311e991b321642e180e66dc21b6e25 Mon Sep 17 00:00:00 2001 From: auric <104602845+ihateamongus@users.noreply.github.com> Date: Mon, 8 Sep 2025 23:41:35 -0500 Subject: Refactor slogin for framebuffer and OpenRC --- core/slogin/slogin.c | 161 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 161 insertions(+) create mode 100644 core/slogin/slogin.c (limited to 'core/slogin/slogin.c') diff --git a/core/slogin/slogin.c b/core/slogin/slogin.c new file mode 100644 index 0000000..1978d71 --- /dev/null +++ b/core/slogin/slogin.c @@ -0,0 +1,161 @@ +/* See LICENSE file for license details. */ +#define _XOPEN_SOURCE 700 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../accent.h" +#include "config.h" + +static ColorShm *accentshm; +static char accentcol[8] = "#005577"; + +static void +die(const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); + exit(1); +} + +static void +updateaccent(void) +{ + if (!readaccent(&accentshm, accentcol)) + memcpy(accentcol, "#005577", 8); +} + +static void +parseaccent(int *r, int *g, int *b) +{ + unsigned int ri, gi, bi; + if (sscanf(accentcol + 1, "%02x%02x%02x", &ri, &gi, &bi) == 3) { + *r = ri; + *g = gi; + *b = bi; + } else { + *r = 0x00; + *g = 0x55; + *b = 0x77; + } +} + +static void +colored(const char *msg) +{ + int r, g, b; + parseaccent(&r, &g, &b); + printf("\033[38;2;%d;%d;%dm%s\033[0m", r, g, b, msg); +} + +static const char * +gethash(const char *user) +{ + struct passwd *pw; + const char *hash; + if (!(pw = getpwnam(user))) + return NULL; + hash = pw->pw_passwd; +#if HAVE_SHADOW_H + if (!strcmp(hash, "x")) { + struct spwd *sp; + if (!(sp = getspnam(user))) + return NULL; + hash = sp->sp_pwdp; + } +#endif + return hash; +} + +static int +auth(const char *user, const char *pass) +{ + const char *hash = gethash(user); + char *cryptpw; + if (!hash) + return 0; + if (!(cryptpw = crypt(pass, hash))) + return 0; + return !strcmp(cryptpw, hash); +} + +static void +readinput(char *buf, size_t len) +{ + if (!fgets(buf, len, stdin)) + buf[0] = '\0'; + buf[strcspn(buf, "\n")] = '\0'; +} + +static void +readpass(char *buf, size_t len) +{ + struct termios old, new; + tcgetattr(STDIN_FILENO, &old); + new = old; + new.c_lflag &= ~(ECHO); + tcsetattr(STDIN_FILENO, TCSAFLUSH, &new); + readinput(buf, len); + tcsetattr(STDIN_FILENO, TCSAFLUSH, &old); +} + +static void +runsession(const char *user) +{ + struct passwd *pw; + pid_t pid; + if (!(pw = getpwnam(user))) + return; + if ((pid = fork()) == 0) { + if (initgroups(user, pw->pw_gid) < 0) + die("slogin: initgroups failed\n"); + if (setgid(pw->pw_gid) < 0) + die("slogin: setgid failed\n"); + if (setuid(pw->pw_uid) < 0) + die("slogin: setuid failed\n"); + setenv("HOME", pw->pw_dir, 1); + if (chdir(pw->pw_dir) < 0) + die("slogin: chdir failed\n"); + execvp(logincmd[0], (char *const *)logincmd); + _exit(1); + } + waitpid(pid, NULL, 0); +} + +int +main(void) +{ + char user[64]; + char pass[64]; + + for (;;) { + updateaccent(); + printf("\033[2J\033[H"); + colored("login: "); + fflush(stdout); + readinput(user, sizeof user); + colored("password: "); + fflush(stdout); + readpass(pass, sizeof pass); + printf("\n"); + if (auth(user, pass)) { + memset(pass, 0, sizeof pass); + runsession(user); + } else { + colored("Login incorrect\n"); + memset(pass, 0, sizeof pass); + sleep(2); + } + } + return 0; +} -- cgit v1.2.3