summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/slogin/Makefile38
-rw-r--r--core/slogin/config.def.h2
-rw-r--r--core/slogin/config.mk12
-rw-r--r--core/slogin/slogin.c161
-rw-r--r--core/slogin/slogin.openrc9
5 files changed, 222 insertions, 0 deletions
diff --git a/core/slogin/Makefile b/core/slogin/Makefile
new file mode 100644
index 0000000..0f9b32a
--- /dev/null
+++ b/core/slogin/Makefile
@@ -0,0 +1,38 @@
+# slogin - simple login manager
+# See LICENSE file for license details.
+
+include config.mk
+
+SRC = slogin.c
+OBJ = ${SRC:.c=.o}
+RC = slogin.openrc
+
+all: slogin
+
+.c.o:
+ ${CC} -c ${CFLAGS} $<
+
+${OBJ}: config.h config.mk
+
+config.h:
+ cp config.def.h $@
+
+slogin: ${OBJ}
+ ${CC} -o $@ ${OBJ} ${LDFLAGS}
+
+clean:
+ rm -f slogin ${OBJ}
+
+install: all
+ mkdir -p ${DESTDIR}${PREFIX}/bin
+ cp -f slogin ${DESTDIR}${PREFIX}/bin
+ chmod 755 ${DESTDIR}${PREFIX}/bin/slogin
+ mkdir -p ${DESTDIR}/etc/init.d
+ cp -f ${RC} ${DESTDIR}/etc/init.d/slogin
+ chmod 755 ${DESTDIR}/etc/init.d/slogin
+
+uninstall:
+ rm -f ${DESTDIR}${PREFIX}/bin/slogin
+ rm -f ${DESTDIR}/etc/init.d/slogin
+
+.PHONY: all clean install uninstall
diff --git a/core/slogin/config.def.h b/core/slogin/config.def.h
new file mode 100644
index 0000000..6e58261
--- /dev/null
+++ b/core/slogin/config.def.h
@@ -0,0 +1,2 @@
+/* command to run after successful login */
+static const char *logincmd[] = { "startx", NULL };
diff --git a/core/slogin/config.mk b/core/slogin/config.mk
new file mode 100644
index 0000000..fcca349
--- /dev/null
+++ b/core/slogin/config.mk
@@ -0,0 +1,12 @@
+VERSION = 0.2
+
+PREFIX = /usr/local
+MANPREFIX = ${PREFIX}/share/man
+
+LIBS = -lcrypt
+
+CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -DVERSION=\"${VERSION}\" -DHAVE_SHADOW_H
+CFLAGS = -std=c99 -pedantic -Wall -Os ${CPPFLAGS}
+LDFLAGS = ${LIBS}
+
+CC = cc
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 <unistd.h>
+#include <pwd.h>
+#include <grp.h>
+#include <shadow.h>
+#include <crypt.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+#include <termios.h>
+#include <sys/wait.h>
+
+#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;
+}
diff --git a/core/slogin/slogin.openrc b/core/slogin/slogin.openrc
new file mode 100644
index 0000000..2b56a0a
--- /dev/null
+++ b/core/slogin/slogin.openrc
@@ -0,0 +1,9 @@
+#!/sbin/openrc-run
+command="/usr/local/bin/slogin"
+command_background="no"
+description="Minimal framebuffer login that launches X"
+
+depend() {
+ need localmount
+ after bootmisc
+}