commit 0a3ed68d2500c2989545b3bf0af5ebc0b50bec7a
parent 5322e83da0f32f1d6805a2c3f492cfd3c178d489
Author: sin <sin@2f30.org>
Date: Mon, 2 Jun 2014 14:00:55 +0100
Add initial implementation of login(1)
No shadow support atm.
Diffstat:
M | Makefile | | | 1 | + |
A | login.c | | | 109 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
2 files changed, 110 insertions(+), 0 deletions(-)
diff --git a/Makefile b/Makefile
@@ -32,6 +32,7 @@ SRC = \
id.c \
insmod.c \
killall5.c \
+ login.c \
lsmod.c \
lsusb.c \
mknod.c \
diff --git a/login.c b/login.c
@@ -0,0 +1,109 @@
+/* See LICENSE file for copyright and license details. */
+#define _XOPEN_SOURCE
+#include <errno.h>
+#include <grp.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include "config.h"
+#include "util.h"
+
+static int dologin(struct passwd *, int);
+
+static void
+usage(void)
+{
+ eprintf("usage: %s [-p] username\n", argv0);
+}
+
+int
+main(int argc, char *argv[])
+{
+ struct passwd *pw;
+ uid_t uid;
+ gid_t gid;
+ char *pass, *cryptpass;
+ int pflag = 0;
+
+ ARGBEGIN {
+ case 'p':
+ pflag = 1;
+ break;
+ default:
+ usage();
+ } ARGEND;
+
+ if (argc < 1)
+ usage();
+
+ errno = 0;
+ pw = getpwnam(argv[0]);
+ if (errno)
+ eprintf("getpwnam: %s:", argv[0]);
+ else if (!pw)
+ eprintf("who are you?\n");
+
+ switch (pw->pw_passwd[0]) {
+ case '!':
+ case '*':
+ eprintf("Denied\n");
+ }
+
+ if (pw->pw_passwd[0] == 'x' && pw->pw_passwd[1] == '\0')
+ eprintf("no shadow support\n");
+
+ uid = pw->pw_uid;
+ gid = pw->pw_gid;
+
+ /* Empty password? Login now */
+ if (pw->pw_passwd[0] == '\0')
+ goto login;
+
+ /* Flush pending input */
+ ioctl(STDIN_FILENO, TCFLSH, (void *)0);
+
+ pass = getpass("Password: ");
+ if (!pass)
+ eprintf("getpass:");
+ putchar('\n');
+ cryptpass = crypt(pass, pw->pw_passwd);
+ explicit_bzero(pass, strlen(pass));
+ if (!cryptpass)
+ eprintf("crypt:");
+ if (strcmp(cryptpass, pw->pw_passwd) != 0)
+ eprintf("oops\n");
+
+login:
+ if (initgroups(argv[0], gid) < 0)
+ eprintf("initgroups:");
+ if (setgid(gid) < 0)
+ eprintf("setgid:");
+ if (setuid(uid) < 0)
+ eprintf("setuid:");
+
+ return dologin(pw, pflag);
+}
+
+static int
+dologin(struct passwd *pw, int preserve)
+{
+ char *shell[] = { pw->pw_shell, pw->pw_shell, "-l", NULL };
+
+ if (preserve == 0)
+ clearenv();
+ setenv("HOME", pw->pw_dir, 1);
+ setenv("SHELL", pw->pw_shell, 1);
+ setenv("USER", pw->pw_name, 1);
+ setenv("LOGNAME", pw->pw_name, 1);
+ setenv("PATH", strcmp(pw->pw_name, "root") == 0 ?
+ ENV_SUPATH : ENV_PATH, 1);
+ if (chdir(pw->pw_dir) < 0)
+ eprintf("chdir %s:", pw->pw_dir);
+ execvp(shell[0], shell + 1);
+ weprintf("execvp %s:", shell[0]);
+ return (errno == ENOENT) ? 127 : 126;
+}