aboutsummaryrefslogtreecommitdiffstats
path: root/src/cerberus.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cerberus.c')
-rw-r--r--src/cerberus.c317
1 files changed, 0 insertions, 317 deletions
diff --git a/src/cerberus.c b/src/cerberus.c
deleted file mode 100644
index c555a2b..0000000
--- a/src/cerberus.c
+++ /dev/null
@@ -1,317 +0,0 @@
-/**
- * cerberus – Minimal login program
- *
- * Copyright © 2013 Mattias Andrée (maandree@member.fsf.org)
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-#include "cerberus.h"
-
-/* TODO use log */
-
-
-#ifdef USE_TTY_GROUP
-/**
- * The group ID for the `tty` group
- */
-static gid_t tty_group = 0;
-#endif
-
-/**
- * The user's entry in the password file
- */
-static struct passwd* entry;
-
-/**
- * The process ID of the child process, 0 if none
- */
-pid_t child_pid = 0;
-
-/**
- * The passphrase
- */
-char* passphrase = NULL;
-
-
-/**
- * Mane method
- *
- * @param argc The number of command line arguments
- * @param argv The command line arguments
- * @return Return code
- */
-int main(int argc, char** argv)
-{
- char* tty_device = ttyname(STDIN_FILENO);
-
- do_login(argc, argv);
-
- /* Ignore signals */
- signal(SIGQUIT, SIG_IGN);
- signal(SIGINT, SIG_IGN);
-
- /* Wait for the login shell and all grandchildren to exit */
- while ((wait(NULL) == -1) && (errno == EINTR))
- ;
-
- /* Regain access to the terminal */
- if (tty_device)
- {
- int fd = open(tty_device, O_RDWR | O_NONBLOCK);
- if (fd)
- dup2(fd, 0);
- dup2(fd, 1);
- dup2(fd, 2);
- }
-
- /* Reset terminal ownership and mode */
- chown_tty(0, tty_group, 0);
-
- /* Close login session */
- close_login_session();
-
- return 0;
-}
-
-
-/**
- * Do everything before the fork and do everything the exec fork
- *
- * @param argc The number of command line arguments
- * @param argv The command line arguments
- */
-void do_login(int argc, char** argv)
-{
- char* username = NULL;
- char* hostname = NULL;
- char preserve_env = 0;
- char skip_auth = 0;
- int ret;
- #ifdef USE_TTY_GROUP
- struct group* group;
- #endif
-
-
- /* Disable echoing */
- disable_echo();
- /* This should be done as early and quickly as possible so as little
- as possible of the passphrase gets leaked to the output if the user
- begins entering the passphrase directly after the username. */
-
-
- /* Set process group ID */
- setpgrp();
-
-
- /* Parse command line arguments */
- {
- char double_dashed = 0;
- char hostname_on_next = 0;
- int i;
- for (i = 1; i < argc; i++)
- {
- char *arg = *(argv + i);
- char c;
-
- if (*arg == 0)
- ;
- else if ((*arg == '-') && (double_dashed == 0))
- while ((c = *(++arg)))
- if ((c == 'V') || (c == 'H'))
- ;
- else if (c == 'p')
- preserve_env = 1;
- else if (c == 'h')
- {
- if (*(arg + 1))
- hostname = arg + 1;
- else
- hostname_on_next = 1;
- break;
- }
- else if (c == 'f')
- {
- if (*(arg + 1))
- username = arg + 1;
- skip_auth = 1;
- break;
- }
- else if (c == '-')
- {
- double_dashed = 1;
- break;
- }
- else
- printf("%s: unrecognised options: -%c\n", *argv, c);
- else if (hostname_on_next)
- {
- hostname = arg;
- hostname_on_next = 0;
- }
- else
- username = arg;
- }
- }
-
-
- /* Change that a username has been specified */
- if (username == NULL)
- {
- printf("%s: no username specified\n", *argv);
- sleep(ERROR_SLEEP);
- _exit(2);
- }
-
-
- /* Only root may bypass authentication */
- if (skip_auth && getuid())
- {
- printf("%s: only root by use the -f option\n", *argv);
- sleep(ERROR_SLEEP);
- _exit(2);
- }
-
-
- /* Print ant we want a passphrase, if -f has not been used */
- if (skip_auth == 0)
- {
- printf("Passphrase: ");
- fflush(stdout);
- }
- /* Done early to make to program look like it is even faster than it is */
-
-
- /* Make sure nopony is spying */
- #ifdef USE_TTY_GROUP
- if ((group = getgrnam(TTY_GROUP)))
- tty_group = group->gr_gid;
- endgrent();
- #endif
- secure_tty(tty_group);
-
- /* Redisable echoing */
- disable_echo();
-
-
- /* Set up clean quiting and time out */
- signal(SIGALRM, timeout_quit);
- signal(SIGQUIT, user_quit);
- signal(SIGINT, user_quit);
- siginterrupt(SIGALRM, 1);
- siginterrupt(SIGQUIT, 1);
- siginterrupt(SIGINT, 1);
- alarm(TIMEOUT_SECONDS);
-
-
- /* Get user information */
- if ((entry = getpwnam(username)) == NULL)
- {
- if (errno)
- perror("getpwnam");
- else
- printf("User does not exist\n");
- sleep(ERROR_SLEEP);
- _exit(1);
- }
- endpwent();
- username = entry->pw_name;
-
-
- /* Verify passphrase or other token, if -f has not been used */
- initialise_login(hostname, username, read_passphrase);
- if ((skip_auth == 0) && authenticate_login())
- printf("(auto-authenticated)\n");
-
- /* Passphrase entered, turn off timeout */
- alarm(0);
-
- /* Wipe and free the passphrase from the memory */
- if (passphrase)
- {
- long i;
- for (i = 0; *(passphrase + i); i++)
- *(passphrase + i) = 0;
- free(passphrase);
- }
-
- /* Reset terminal settings */
- reenable_echo();
-
-
- /* Verify account, such as that it is enabled */
- verify_account();
-
-
- /* Partial login */
- chown_tty(entry->pw_uid, tty_group, 0);
- chdir_home(entry);
- ensure_shell(entry);
- set_environ(entry, preserve_env);
- open_login_session();
-
-
- /* Stop signal handling */
- signal(SIGALRM, SIG_DFL);
- signal(SIGQUIT, SIG_DFL);
- signal(SIGTSTP, SIG_IGN);
-
-
- child_pid = fork();
- /* vfork cannot be used as the child changes the user,
- the parent would not be able to chown the TTY */
-
- if (child_pid == -1)
- {
- perror("fork");
- close_login_session();
- sleep(ERROR_SLEEP);
- _exit(1);
- }
- else if (child_pid)
- return; /* Do not go beyond this in the parent */
-
- /* In case the shell does not do this */
- setsid();
-
- /* Set controlling terminal */
- if (ioctl(STDIN_FILENO, TIOCSCTTY, 1))
- perror("TIOCSCTTY");
- signal(SIGINT, SIG_DFL);
-
- /* Partial login */
- ret = entry->pw_uid
- ? initgroups(username, entry->pw_gid) /* supplemental groups for user, can require network */
- : setgroups(0, NULL); /* supplemental groups for root, does not require netork */
- if (ret == -1)
- {
- perror(entry->pw_uid ? "initgroups" : "setgroups");
- sleep(ERROR_SLEEP);
- _exit(1);
- }
- set_user(entry);
- exec_shell(entry);
-}
-
-
-/**
- * Read passphrase from the terminal
- *
- * @return The entered passphrase
- */
-char* read_passphrase(void)
-{
- passphrase = get_passphrase();
- return passphrase;
-}
-