summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNalin Dahyabhai <nalin.dahyabhai@pobox.com>2008-03-20 11:58:00 -0400
committerNalin Dahyabhai <nalin.dahyabhai@pobox.com>2008-03-20 11:58:00 -0400
commit48037909a5a5c8e0640c33352de6aa942f532d8c (patch)
tree6123e59209f23cf9f35314729ed0aed0adc04ebc
downloadautologin-48037909a5a5c8e0640c33352de6aa942f532d8c.tar.gz
autologin-48037909a5a5c8e0640c33352de6aa942f532d8c.tar.xz
autologin-48037909a5a5c8e0640c33352de6aa942f532d8c.zip
- stable version
-rw-r--r--Makefile15
-rw-r--r--README20
-rw-r--r--TODO0
-rw-r--r--autologin.829
-rw-r--r--autologin.c330
-rw-r--r--autologin.pamd3
-rw-r--r--autologin.spec43
7 files changed, 440 insertions, 0 deletions
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..13ff2fe
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,15 @@
+CFLAGS=-Wall -Wextra
+LDFLAGS=-lpam -lutempter -ldl
+
+all: autologin
+
+clean:
+ $(RM) autologin
+
+install: $(DESTDIR)/sbin/autologin $(DESTDIR)/usr/man/man8/autologin.8.gz
+
+$(DESTDIR)/sbin/autologin: autologin
+ install -m 711 $^ $@
+
+$(DESTDIR)/usr/man/man8/autologin.8.gz: autologin.8
+ cat autologin.8 | gzip > $(DESTDIR)/usr/man/man8/autologin.8.gz
diff --git a/README b/README
new file mode 100644
index 0000000..a4ecba6
--- /dev/null
+++ b/README
@@ -0,0 +1,20 @@
+This is a program you can use to automatically log in on a workstation when
+it boots. Look for a line in /etc/inittab that looks like this:
+
+1:2345:respawn:/sbin/mingetty tty1
+
+Replace it with this:
+
+1:2345:respawn:/sbin/autlogin tty1 joeuser
+
+And joeuser will be logged in automatically when the system boots. To have
+some command other than a shell started, supply it as a third argument:
+
+1:2345:respawn:/sbin/autlogin tty1 joeuser startx
+
+Note that this is a potential security risk that's big enough to drive a truck
+through, and it's only guaranteed to work with pam_unix and possibly pam_pwdb.
+
+Consider yourself warned.
+
+Nalin Dahyabhai <nalin@redhat.com>
diff --git a/TODO b/TODO
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/TODO
diff --git a/autologin.8 b/autologin.8
new file mode 100644
index 0000000..8ff7ac3
--- /dev/null
+++ b/autologin.8
@@ -0,0 +1,29 @@
+.TH AUTOLOGIN 8 "Red Hat, Inc." "Red Hat Linux" \" -*- nroff -*-
+.SH NAME
+autologin \- run a program without having to log in first
+.SH SYNOPSIS
+.B autologin
+\fItty\fP \fIuser\fP [command]
+.SH DESCRIPTION
+.B autologin
+opens a specified terminal, becomes the specified user, and will either
+start an interactive shell or run a specified command. This is intended
+for use in your \fB/etc/inittab\fP file, but can be used elsewhere.
+
+.SH OPTIONS
+.TP
+.I tty
+The name of the TTY device to use. Most of the time this will be one of
+the virtual consoles, numbered from \fBtty1\fP to \fBtty12\fP. The \fB/dev\fP
+prefix can be omitted.
+.TP
+.I user
+The name of the user to become. Autologin will drop privileges to those of this
+user before doing anything else.
+.TP
+.I command
+An optional command to run. It must be a binary, either in the default PATH, or
+given as a full pathname. If no command is specified, the user's shell will be
+started interactively.
+.SH AUTHOR
+Nalin Dahyabhai <nalin@redhat.com>
diff --git a/autologin.c b/autologin.c
new file mode 100644
index 0000000..31eb1f8
--- /dev/null
+++ b/autologin.c
@@ -0,0 +1,330 @@
+/*
+ * Autologin - sort of automatic execution on a terminal.
+ * Author: Nalin Dahyabhai <nalin@redhat.com>
+ * Copyright (c) 2000,2005 Red Hat, Inc.
+ *
+ * This program is licensed under the terms of the GPL.
+ */
+
+#ident "$Id: autologin.c,v 1.3 1999/12/19 22:37:45 nalin Exp $"
+
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <grp.h>
+#include <limits.h>
+#include <pwd.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <security/pam_appl.h>
+#include <utempter.h>
+
+#define SLEEPYTIME 5
+
+static int
+converse(int num_msg, const struct pam_message **msg,
+ struct pam_response **resp, void *appdata_ptr)
+{
+ int i;
+
+ resp = malloc(sizeof(struct pam_response*) * (num_msg + 1));
+ if (resp == NULL) {
+ fprintf(stderr, "out of memory!\n");
+ sleep(SLEEPYTIME);
+ _exit(1);
+ }
+ memset(resp, 0, sizeof(struct pam_response*) * (num_msg + 1));
+
+ for (i = 0; i < num_msg; i++) {
+ resp[i] = malloc(sizeof(struct pam_response));
+ memset(resp[i], 0, sizeof(struct pam_response));
+ resp[i]->resp_retcode = PAM_SUCCESS;
+
+ switch (msg[i]->msg_style) {
+ case PAM_PROMPT_ECHO_OFF:
+ case PAM_PROMPT_ECHO_ON:
+ resp[i]->resp = strdup(appdata_ptr ?
+ appdata_ptr : "");
+ /* fall through */
+ case PAM_ERROR_MSG:
+ case PAM_TEXT_INFO:
+ if ((msg[i]->msg != NULL) &&
+ (strlen(msg[i]->msg) > 0)) {
+ fprintf(stderr, "%s", msg[i]->msg);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ return PAM_SUCCESS;
+}
+
+static void
+init_environment(pam_handle_t *pamh, struct passwd *pwd)
+{
+ char *tmp, **envlist;
+ const char *path;
+ int i;
+
+ /* Set the same variables that login(1) would. */
+ tmp = malloc(5 + strlen(pwd->pw_dir) + 1);
+ if (tmp == NULL) {
+ fprintf(stderr, "out of memory!\n");
+ sleep(SLEEPYTIME);
+ _exit(1);
+ }
+ sprintf(tmp, "HOME=%s", pwd->pw_dir);
+ putenv(tmp);
+
+ tmp = malloc(6 + strlen(pwd->pw_shell) + 1);
+ if (tmp == NULL) {
+ fprintf(stderr, "out of memory!\n");
+ sleep(SLEEPYTIME);
+ _exit(1);
+ }
+ sprintf(tmp, "SHELL=%s", pwd->pw_shell);
+ putenv(tmp);
+
+ tmp = malloc(8 + strlen(pwd->pw_name) + 1);
+ if (tmp == NULL) {
+ fprintf(stderr, "out of memory!\n");
+ sleep(SLEEPYTIME);
+ _exit(1);
+ }
+ sprintf(tmp, "LOGNAME=%s", pwd->pw_name);
+ putenv(tmp);
+
+ tmp = malloc(5 + strlen(pwd->pw_name) + 1);
+ if (tmp == NULL) {
+ fprintf(stderr, "out of memory!\n");
+ sleep(SLEEPYTIME);
+ _exit(1);
+ }
+ sprintf(tmp, "USER=%s", pwd->pw_name);
+ putenv(tmp);
+
+ if (pwd->pw_uid == 0) {
+ path = "/sbin:/bin:/usr/sbin:/usr/bin:/usr/X11R6/bin";
+ } else {
+ path = "/usr/local/bin:"
+ "/bin:/usr/bin:/usr/X11R6/bin:/sbin:/usr/sbin";
+ }
+
+ asprintf(&tmp, "PATH=%s", path);
+ if (tmp == NULL) {
+ fprintf(stderr, "out of memory!\n");
+ sleep(SLEEPYTIME);
+ _exit(1);
+ }
+ putenv(tmp);
+
+ /* Set any environment variables which PAM would like for us to set. */
+ envlist = pam_getenvlist(pamh);
+ for (i = 0; (envlist != NULL) && (envlist[i] != NULL); i++) {
+ putenv(envlist[i]);
+ }
+}
+
+int
+main(int argc, char **argv)
+{
+ int ret = 0;
+ int fd = 0;
+ pid_t child;
+ pam_handle_t *pamh = NULL;
+ char tty[PATH_MAX];
+ char shell[PATH_MAX];
+ struct passwd *pwd;
+ struct group *ttygrp;
+ struct stat st;
+ struct pam_conv conversation = {
+ converse,
+ "",
+ };
+
+ /* Verify that we were invoked correctly. */
+ if ((argc < 3) || (argc > 4)) {
+ fprintf(stderr, "Incorrect invocation -- should be \"%s tty "
+ "user [command]\"\n", argv[0]);
+ sleep(SLEEPYTIME);
+ exit(1);
+ }
+
+ /* Verify that the user exists. */
+ pwd = getpwnam(argv[2]);
+ if (pwd == NULL) {
+ fprintf(stderr, "Unknown user \"%s\"!\n", argv[2]);
+ sleep(SLEEPYTIME);
+ exit(1);
+ }
+ ttygrp = getgrnam("tty");
+
+ /* Verify that the specified tty exists. */
+ strncpy(tty, argv[1], sizeof(tty));
+ if (stat(tty, &st) != 0) {
+ strncpy(tty, "/dev/", sizeof(tty));
+ strncat(tty, argv[1], sizeof(tty));
+ if (stat(tty, &st) != 0) {
+ fprintf(stderr, "Unknown tty \"%s\"!\n", argv[1]);
+ sleep(SLEEPYTIME);
+ exit(1);
+ }
+ }
+
+ /* Make the tty our controlling terminal. */
+ close(STDIN_FILENO);
+ close(STDOUT_FILENO);
+ close(STDERR_FILENO);
+ fd = open(tty, O_RDWR);
+ if (fd == -1) {
+ fprintf(stderr, "Error opening %s: %s.\n", tty,
+ strerror(errno));
+ sleep(SLEEPYTIME);
+ exit(1);
+ }
+ if (dup2(fd, STDIN_FILENO) != STDIN_FILENO) {
+ fprintf(stderr, "Error dup2()ing to stdin: %s.\n",
+ strerror(errno));
+ sleep(SLEEPYTIME);
+ exit(1);
+ }
+ if (dup2(fd, STDOUT_FILENO) != STDOUT_FILENO) {
+ fprintf(stderr, "Error dup2()ing to stdout: %s.\n",
+ strerror(errno));
+ sleep(SLEEPYTIME);
+ exit(1);
+ }
+ if (dup2(fd, STDERR_FILENO) != STDERR_FILENO) {
+ fprintf(stderr, "Error dup2()ing to stderr: %s.\n",
+ strerror(errno));
+ sleep(SLEEPYTIME);
+ exit(1);
+ }
+ if (dup2(fd, 3) != 3) {
+ fprintf(stderr, "Error dup2()ing to FD3: %s.\n",
+ strerror(errno));
+ sleep(SLEEPYTIME);
+ exit(1);
+ }
+ if (fcntl(3, F_SETFD, FD_CLOEXEC) != 0) {
+ fprintf(stderr, "Error setting close-on-exec flag: %s.\n",
+ strerror(errno));
+ sleep(SLEEPYTIME);
+ exit(1);
+ }
+
+ /* Start PAM up, skip authentication, and open a session. */
+ ret = pam_start("login", argv[2], &conversation, &pamh);
+ if (ret != PAM_SUCCESS) {
+ fprintf(stderr, "Error initializing libpam: %s\n",
+ pam_strerror(pamh, ret));
+ sleep(SLEEPYTIME);
+ exit(1);
+ }
+
+ pam_set_item(pamh, PAM_USER, argv[2]);
+ pam_set_item(pamh, PAM_TTY, argv[1]);
+
+ pam_set_item(pamh, PAM_RHOST, NULL);
+ pam_set_item(pamh, PAM_RUSER, argv[2]);
+
+ ret = pam_setcred(pamh, PAM_ESTABLISH_CRED);
+ if (ret != PAM_SUCCESS) {
+ fprintf(stderr, "Error establishing credentials: %s\n",
+ pam_strerror(pamh, ret));
+ sleep(SLEEPYTIME);
+ exit(1);
+ }
+
+ ret = pam_open_session(pamh, 0);
+ if (ret != PAM_SUCCESS) {
+ fprintf(stderr, "Error initializing session: %s\n",
+ pam_strerror(pamh, ret));
+ sleep(SLEEPYTIME);
+ exit(1);
+ }
+
+ /* Prepare argv[0] for the user's shell. */
+ memset(shell, 0, sizeof(shell));
+ if (rindex(pwd->pw_shell, '/') != NULL) {
+ strncpy(shell, rindex(pwd->pw_shell, '/'), sizeof(shell));
+ } else {
+ strncpy(shell + 1, pwd->pw_shell, sizeof(shell));
+ }
+ shell[0] = '-';
+
+ /* Set permissions on the device. */
+ chown(tty, pwd->pw_uid, ttygrp ? ttygrp->gr_gid : 0);
+ chmod(tty, 0620);
+
+ /* Log the login. */
+ addToUtmp(tty, NULL, STDERR_FILENO);
+
+ /* Fork. The child will exec the shell. */
+ child = fork();
+ if (child < 0) {
+ fprintf(stderr, "Error fork()ing: %s\n", strerror(errno));
+ /* Don't leave an erroneous login behind. */
+ removeFromUtmp();
+ sleep(SLEEPYTIME);
+ exit(1);
+ }
+
+ if (child == 0) {
+ /* We're in the child. */
+ fprintf(stderr, "");
+ initgroups(pwd->pw_name, pwd->pw_gid);
+ if (setuid(pwd->pw_uid) == 0) {
+ init_environment(pamh, pwd);
+ chdir(pwd->pw_dir);
+ /* If we have an argv[3], execute it instead. */
+ if (argc >= 4) {
+ execlp(argv[3], argv[3], NULL);
+ } else {
+ execlp(pwd->pw_shell, shell, NULL);
+ }
+ } else {
+ fprintf(stderr, "Error becoming %s.\n", pwd->pw_name);
+ }
+ return 1;
+ }
+ if (child > 0) {
+ /* We're in the parent. */
+ waitpid(child, NULL, 0);
+ kill(child, SIGHUP);
+ }
+
+ /* Log the logout. */
+ removeFromUtmp();
+
+ /* Reset permissions on the device. */
+ chown(tty, st.st_uid, st.st_gid);
+ chmod(tty, st.st_mode);
+
+ /* Clean up. */
+ ret = pam_close_session(pamh, 0);
+ if (ret != PAM_SUCCESS) {
+ fprintf(stderr, "Error terminating session: %s\n",
+ pam_strerror(pamh, ret));
+ sleep(SLEEPYTIME);
+ exit(1);
+ }
+
+ ret = pam_setcred(pamh, PAM_DELETE_CRED);
+ if (ret != PAM_SUCCESS) {
+ fprintf(stderr, "Error deleting credentials: %s\n",
+ pam_strerror(pamh, ret));
+ sleep(SLEEPYTIME);
+ exit(1);
+ }
+
+ pam_end(pamh, PAM_SUCCESS);
+
+ return 0;
+}
diff --git a/autologin.pamd b/autologin.pamd
new file mode 100644
index 0000000..5d4b71a
--- /dev/null
+++ b/autologin.pamd
@@ -0,0 +1,3 @@
+auth include login
+account include login
+session include login
diff --git a/autologin.spec b/autologin.spec
new file mode 100644
index 0000000..d770d73
--- /dev/null
+++ b/autologin.spec
@@ -0,0 +1,43 @@
+%define name autologin
+%define version 0.02
+%define release 1
+
+Summary: Auto Login Utility
+Name: %{name}
+Version: %{version}
+Release: %{release}
+License: GPLv2
+Group: Security Violations
+Source: autologin.tar.gz
+BuildRoot: %{_tmppath}/%{name}-%{version}-root
+
+%description
+This is a program you can use to automatically log in on a workstation when
+it boots. This program is normally run from /etc/inittab replacing one of
+your mingetty lines. This program is a huge security hole.
+
+%prep
+%setup -n %{name}
+
+%build
+make
+
+%install
+
+mkdir -p $RPM_BUILD_ROOT/sbin/
+mkdir -p $RPM_BUILD_ROOT/usr/man/man8/
+install autologin $RPM_BUILD_ROOT/sbin/
+cat autologin.8 | gzip > $RPM_BUILD_ROOT/usr/man/man8/autologin.8.gz
+
+%clean
+rm -rf $RPM_BUILD_ROOT
+
+%files
+%defattr(-,root,root)
+%doc README TODO
+%attr(711,root,root) /sbin/autologin
+/usr/man/man8/autologin.8.gz
+
+%changelog
+* Thu Mar 16 2000 Dale Lovelace <dale@redhat.com>
+- First RPM build