From e4aefb7bc4f1dc9cb9235d13e4bf4000b9090d72 Mon Sep 17 00:00:00 2001 From: Mike Lowis Date: Thu, 28 Apr 2016 11:12:52 -0400 Subject: [PATCH] Finish initial implementation of login command --- Makefile | 4 +- include/util.h | 2 +- source/login.c | 254 ++++++++----------------------------------------- 3 files changed, 44 insertions(+), 216 deletions(-) diff --git a/Makefile b/Makefile index 54d57205..642dbf78 100644 --- a/Makefile +++ b/Makefile @@ -7,7 +7,7 @@ CC = cc # flags LIBS = INCS = -Iinclude -CPPFLAGS = $(INCS) +CPPFLAGS = $(INCS) -D_XOPEN_SOURCE CFLAGS = -O2 $(CPPFLAGS) LDFLAGS = $(LIBS) BUILD = $(CC) $(CFLAGS) -o $@ $< @@ -34,7 +34,7 @@ getty: source/getty.c $(BUILD) login: source/login.c - $(BUILD) + $(BUILD) -lcrypt clean: $(RM) $(BINS) diff --git a/include/util.h b/include/util.h index 5427c1ea..95b4afa3 100644 --- a/include/util.h +++ b/include/util.h @@ -164,7 +164,7 @@ static char* estrdup(const char *s) } /* Option Parsing - * + ****************************************************************************** * This following macros implement a simple POSIX-style option parsing strategy. * They are heavily influenced and inspired by the arg.h file from suckless.org * (http://git.suckless.org/libsl/tree/arg.h). That file is in turn inspired by diff --git a/source/login.c b/source/login.c index cce61fec..7c5f0b63 100644 --- a/source/login.c +++ b/source/login.c @@ -7,22 +7,9 @@ #include #include #include +#include -//#include -//#include -//#include -//#include -//#include -//#include -//#include -//#include -//#include -//#include -//#include - -//#include "config.h" -//#include "passwd.h" -//#include "util.h" +#define ENV_PATH "/bin" char* ARGV0; static char* Hostname = NULL; @@ -45,8 +32,8 @@ static char* get_user(void) { if (Username == NULL) { printf("login: "); fflush(stdout); - fgets(username, sizeof(username)-1, stdin); - username[strlen(username)-1] = '\0'; + if (fgets(username, sizeof(username)-1, stdin)) + username[strlen(username)-1] = '\0'; return username; } else { return Username; @@ -54,25 +41,28 @@ static char* get_user(void) { } static char* get_pass(void) { + /* flush input buffer */ + ioctl(0, TCFLSH, (void *)0); return getpass("password: "); } -static bool check_pass(const char* user, char* pass) { +static struct passwd* check_pass(const char* user, char* pass) { struct spwd* spw; + /* get the passwd entry */ struct passwd* pwentry = getpwnam(user); if (!pwentry || errno) die("Could not find entry for user: %s", user); /* Handle disabled accounts */ if (pwentry->pw_passwd[0] == '!' || pwentry->pw_passwd[0] == '*') { warn("access denied"); - return false; + return NULL; } /* Handle blank pass or blank pass entry */ if ((pwentry->pw_passwd[0] == '\0') || (pass[0] == '\0')) { warn("incorrect password\n"); - return false; + return NULL; } - /* Handle shadow passwd entries */ + /* Get the shadow entry */ if (pwentry->pw_passwd[0] == 'x' && pwentry->pw_passwd[1] == '\0') { errno = 0; spw = getspnam(pwentry->pw_name); @@ -81,63 +71,16 @@ static bool check_pass(const char* user, char* pass) { if (spw->sp_pwdp[0] == '!' || spw->sp_pwdp[0] == '*') { warn("access denied\n"); - return false; + return NULL; } } /* Check the password */ char* cryptpass = crypt(pass, spw->sp_pwdp); if (strcmp(cryptpass, spw->sp_pwdp) != 0) { warn("incorrect password"); - return false; - } - return true; -} - -int pw_check(const struct passwd *pw, const char *pass) -{ - char *cryptpass, *p; - struct spwd *spw; - - p = pw->pw_passwd; - if (p[0] == '!' || p[0] == '*') { - weprintf("denied\n"); - return -1; - } - - if (pw->pw_passwd[0] == '\0') { - if (pass[0] == '\0') - return 1; - weprintf("incorrect password\n"); - return 0; - } - - if (pw->pw_passwd[0] == 'x' && pw->pw_passwd[1] == '\0') { - errno = 0; - spw = getspnam(pw->pw_name); - if (!spw) { - if (errno) - weprintf("getspnam: %s:", pw->pw_name); - else - weprintf("who are you?\n"); - return -1; - } - p = spw->sp_pwdp; - if (p[0] == '!' || p[0] == '*') { - weprintf("denied\n"); - return -1; - } - } - - cryptpass = crypt(pass, p); - if (!cryptpass) { - weprintf("crypt:"); - return -1; - } - if (strcmp(cryptpass, p) != 0) { - weprintf("incorrect password\n"); - return 0; + return NULL; } - return 1; + return pwentry; } int main(int argc, char** argv) { @@ -153,150 +96,35 @@ int main(int argc, char** argv) { Username = EOPTARG(die("no username provided")); break; default: - die("Usage: %s [-p] [-h host] [-u user]", ARGV0); + fprintf(stderr,"Usage: %s [-p] [-h host] [-u user]", ARGV0); + exit(EXIT_FAILURE); } OPTEND; - /* */ + /* Print the hostname to the tty */ if (isatty(0) == 0 || isatty(1) == 0 || isatty(2) == 0) die("no tty"); - printf("%s\n", get_host()); - - char* user = get_user(); - char* pass = get_pass(); - if (check_pass(user, pass)) { - - } else { - return EXIT_FAILURE; + printf("This is %s\n\n", get_host()); + /* Get the credentials and authenticate */ + char* user = get_user(); + char* pass = get_pass(); + struct passwd* pwentry = check_pass(user, pass); + while (*pass) { *(pass++) = '\0'; } + if (pwentry != NULL) { + initgroups(user, pwentry->pw_gid); + check(setgid(pwentry->pw_gid), "setgid failed"); + check(setuid(pwentry->pw_uid), "setuid failed"); + char *shell = (pwentry->pw_shell[0] ? pwentry->pw_shell : "/bin/sh"); + if (!PreserveEnv) + clearenv(); + setenv("HOME", pwentry->pw_dir, 1); + setenv("SHELL", shell, 1); + setenv("USER", pwentry->pw_name, 1); + setenv("LOGNAME", pwentry->pw_name, 1); + setenv("PATH", ENV_PATH, 1); + check(chdir(pwentry->pw_dir), "chdir failed"); + execlp(shell, shell, "-l", NULL); } - return EXIT_SUCCESS; -} -//* See LICENSE file for copyright and license details. */ -//#include -//#include -// -//#include -//#include -//#include -//#include -//#include -//#include -//#include -//#include -//#include -// -//#include "config.h" -//#include "passwd.h" -//#include "util.h" -// -///* Write utmp entry */ -//static void -//writeutmp(const char *user, const char *tty) -//{ -// struct utmp usr; -// FILE *fp; -// -// memset(&usr, 0, sizeof(usr)); -// -// usr.ut_type = USER_PROCESS; -// usr.ut_pid = getpid(); -// strlcpy(usr.ut_user, user, sizeof(usr.ut_user)); -// strlcpy(usr.ut_line, tty, sizeof(usr.ut_line)); -// usr.ut_tv.tv_sec = time(NULL); -// -// fp = fopen(UTMP_PATH, "a"); -// if (fp) { -// if (fwrite(&usr, sizeof(usr), 1, fp) != 1) -// if (ferror(fp)) -// weprintf("%s: write error:", UTMP_PATH); -// fclose(fp); -// } else { -// weprintf("fopen %s:", UTMP_PATH); -// } -//} -// -//static int -//dologin(struct passwd *pw, int preserve) -//{ -// char *shell = pw->pw_shell[0] == '\0' ? "/bin/sh" : pw->pw_shell; -// -// if (preserve == 0) -// clearenv(); -// setenv("HOME", pw->pw_dir, 1); -// setenv("SHELL", shell, 1); -// setenv("USER", pw->pw_name, 1); -// setenv("LOGNAME", pw->pw_name, 1); -// setenv("PATH", ENV_PATH, 1); -// if (chdir(pw->pw_dir) < 0) -// eprintf("chdir %s:", pw->pw_dir); -// execlp(shell, shell, "-l", NULL); -// weprintf("execlp %s:", shell); -// return (errno == ENOENT) ? 127 : 126; -//} -// -//static void -//usage(void) -//{ -// eprintf("usage: %s [-p] username\n", argv0); -//} -// -//int -//main(int argc, char *argv[]) -//{ -// struct passwd *pw; -// char *pass, *user; -// char *tty; -// uid_t uid; -// gid_t gid; -// int pflag = 0; -// -// ARGBEGIN { -// case 'p': -// pflag = 1; -// break; -// default: -// usage(); -// } ARGEND; -// -// if (argc < 1) -// usage(); -// -// if (isatty(0) == 0 || isatty(1) == 0 || isatty(2) == 0) -// eprintf("no tty"); -// -// user = argv[0]; -// errno = 0; -// pw = getpwnam(user); -// if (!pw) { -// if (errno) -// eprintf("getpwnam %s:", user); -// else -// eprintf("who are you?\n"); -// } -// -// uid = pw->pw_uid; -// gid = pw->pw_gid; -// -// /* Flush pending input */ -// ioctl(0, TCFLSH, (void *)0); -// -// pass = getpass("Password: "); -// if (!pass) -// eprintf("getpass:"); -// if (pw_check(pw, pass) <= 0) -// exit(1); -// -// tty = ttyname(0); -// if (!tty) -// eprintf("ttyname:"); -// -// writeutmp(user, tty); -// -// if (initgroups(user, gid) < 0) -// eprintf("initgroups:"); -// if (setgid(gid) < 0) -// eprintf("setgid:"); -// if (setuid(uid) < 0) -// eprintf("setuid:"); -// -// return dologin(pw, pflag); -//} + /* Handle any unexpected errors that occurred */ +error: + return (errno == ENOENT) ? 127 : 126; +} -- 2.49.0