/* 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; }