aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMattias Andrée <m@maandree.se>2026-02-22 13:49:08 +0100
committerMattias Andrée <m@maandree.se>2026-02-22 13:49:08 +0100
commit86138fc92d6e5f92d9d3fcceb32b849e8504f619 (patch)
treef361b9cea99dbe4d77d0dd8f9cbc00f67c105d6b /src
parentUdpdate for new version of glibc (diff)
downloadcerberus-86138fc92d6e5f92d9d3fcceb32b849e8504f619.tar.gz
cerberus-86138fc92d6e5f92d9d3fcceb32b849e8504f619.tar.bz2
cerberus-86138fc92d6e5f92d9d3fcceb32b849e8504f619.tar.xz
m fixesHEADmaster
Signed-off-by: Mattias Andrée <m@maandree.se>
Diffstat (limited to '')
-rw-r--r--src/auth.h43
-rw-r--r--src/auth/crypt.c101
-rw-r--r--src/auth/crypt.h7
-rw-r--r--src/auth/pam.c248
-rw-r--r--src/auth/pam.h7
-rw-r--r--src/cerberus.c694
-rw-r--r--src/cerberus.h29
-rw-r--r--src/config.h3
-rw-r--r--src/login.c229
-rw-r--r--src/login.h13
-rw-r--r--src/quit.c35
-rw-r--r--src/quit.h3
-rw-r--r--src/security.c187
-rw-r--r--src/security.h3
14 files changed, 778 insertions, 824 deletions
diff --git a/src/auth.h b/src/auth.h
index edca0b8..be517da 100644
--- a/src/auth.h
+++ b/src/auth.h
@@ -1,7 +1,7 @@
/**
* cerberus – Minimal login program
*
- * Copyright © 2013, 2014, 2015, 2016, 2020 Mattias Andrée (maandree@kth.se)
+ * Copyright © 2013, 2014, 2015, 2016, 2020 Mattias Andrée (m@maandree.se)
*
* 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
@@ -22,33 +22,26 @@
#if AUTH == 0
-
-#define close_login_session(...) /* do nothing */
-#define initialise_login(...) (void) hostname
-#define authenticate_login(...) 1
-#define verify_account(...) /* do nothing */
-#define open_login_session(...) /* do nothing */
-
+# define close_login_session(...) /* do nothing */
+# define initialise_login(...) (void) hostname
+# define authenticate_login(...) 1
+# define verify_account(...) /* do nothing */
+# define open_login_session(...) /* do nothing */
#elif AUTH == 1
-
-#include "auth/crypt.h"
-#define close_login_session(...) /* do nothing */
-#define initialise_login initialise_crypt
-#define authenticate_login authenticate_crypt
-#define verify_account(...) /* do nothing */
-#define open_login_session(...) /* do nothing */
-
+# include "auth/crypt.h"
+# define close_login_session(...) /* do nothing */
+# define initialise_login initialise_crypt
+# define authenticate_login authenticate_crypt
+# define verify_account(...) /* do nothing */
+# define open_login_session(...) /* do nothing */
#elif AUTH == 2
-
-#include "auth/pam.h"
-#define close_login_session close_session_pam
-#define initialise_login initialise_pam
-#define authenticate_login authenticate_pam
-#define verify_account verify_account_pam
-#define open_login_session open_session_pam
-
+# include "auth/pam.h"
+# define close_login_session close_session_pam
+# define initialise_login initialise_pam
+# define authenticate_login authenticate_pam
+# define verify_account verify_account_pam
+# define open_login_session open_session_pam
#endif
#endif
-
diff --git a/src/auth/crypt.c b/src/auth/crypt.c
index 4573c5a..5012580 100644
--- a/src/auth/crypt.c
+++ b/src/auth/crypt.c
@@ -1,7 +1,7 @@
/**
* cerberus – Minimal login program
*
- * Copyright © 2013, 2014, 2015, 2016, 2020 Mattias Andrée (maandree@kth.se)
+ * Copyright © 2013, 2014, 2015, 2016, 2020 Mattias Andrée (m@maandree.se)
*
* 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
@@ -46,12 +46,12 @@
/**
* Function that can be used to read a passphrase from the terminal
*/
-static char* (*passphrase_reader)(void) = NULL;
+static char *(*passphrase_reader)(void) = NULL;
/**
* The username of the user to log in to
*/
-static char* login_username;
+static char *login_username;
@@ -62,12 +62,13 @@ static char* login_username;
* @param username The username of the user to log in to
* @param reader Function that can be used to read a passphrase from the terminal
*/
-void initialise_crypt(char* remote, char* username, char* (*reader)(void))
+void
+initialise_crypt(char *remote, char *username, char *(*reader)(void))
{
- (void) remote;
-
- login_username = username;
- passphrase_reader = reader;
+ (void) remote;
+
+ login_username = username;
+ passphrase_reader = reader;
}
@@ -76,54 +77,52 @@ void initialise_crypt(char* remote, char* username, char* (*reader)(void))
*
* @return 0: failed, 1: success, 2: auto-authenticated
*/
-char authenticate_crypt(void)
+char
+authenticate_crypt(void)
{
#ifdef HAVE_SHADOW
- struct spwd* shadow_entry = NULL;
+ struct spwd *shadow_entry = NULL;
#endif
- struct passwd* passwd_entry = NULL;
- char* crypted;
- char* entered;
- struct termios stty;
-
+ struct passwd *passwd_entry = NULL;
+ char *crypted;
+ char *entered;
+ struct termios stty;
+
#ifdef HAVE_SHADOW
- shadow_entry = getspnam(login_username);
- endspent();
-
- if (shadow_entry)
- crypted = shadow_entry->sp_pwdp;
- else
- {
+ shadow_entry = getspnam(login_username);
+ endspent();
+
+ if (shadow_entry) {
+ crypted = shadow_entry->sp_pwdp;
+ } else {
#endif
- passwd_entry = getpwnam(login_username);
- if (passwd_entry)
- crypted = passwd_entry->pw_passwd;
- else
- {
- perror("getpwnam");
- endpwent();
- sleep(ERROR_SLEEP);
- _exit(1);
- }
- endpwent();
+ passwd_entry = getpwnam(login_username);
+ if (passwd_entry) {
+ crypted = passwd_entry->pw_passwd;
+ } else {
+ perror("getpwnam");
+ endpwent();
+ sleep(ERROR_SLEEP);
+ _exit(1);
+ }
+ endpwent();
#ifdef HAVE_SHADOW
- }
+ }
#endif
-
- if (!(crypted && *crypted)) /* empty means that no passphrase is required (not even Enter) */
- return 2;
-
- entered = crypt(passphrase_reader(), crypted /* salt argument stops parsing when encrypted begins */);
- if (entered && !strcmp(entered, crypted))
- return 1;
-
- /* Clear ISIG (and everything else) to prevent the user
- * from skipping the brute force protection sleep. */
- tcgetattr(STDIN_FILENO, &stty);
- stty.c_lflag = 0;
- tcsetattr(STDIN_FILENO, TCSAFLUSH, &stty);
-
- printf("\nPassphrase incorrect.\nOnly perfect spellers may\nenter this system.\n");
- return 0;
-}
+ if (!(crypted && *crypted)) /* empty means that no passphrase is required (not even Enter) */
+ return 2;
+
+ entered = crypt(passphrase_reader(), crypted /* salt argument stops parsing when encrypted begins */);
+ if (entered && !strcmp(entered, crypted))
+ return 1;
+
+ /* Clear ISIG (and everything else) to prevent the user
+ * from skipping the brute force protection sleep. */
+ tcgetattr(STDIN_FILENO, &stty);
+ stty.c_lflag = 0;
+ tcsetattr(STDIN_FILENO, TCSAFLUSH, &stty);
+
+ printf("\nPassphrase incorrect.\nOnly perfect spellers may\nenter this system.\n");
+ return 0;
+}
diff --git a/src/auth/crypt.h b/src/auth/crypt.h
index 4478929..cfcfc4f 100644
--- a/src/auth/crypt.h
+++ b/src/auth/crypt.h
@@ -1,7 +1,7 @@
/**
* cerberus – Minimal login program
*
- * Copyright © 2013, 2014, 2015, 2016, 2020 Mattias Andrée (maandree@kth.se)
+ * Copyright © 2013, 2014, 2015, 2016, 2020 Mattias Andrée (m@maandree.se)
*
* 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
@@ -23,11 +23,11 @@
/**
* Initialise crypt authentication module
*
- * @param remote The remote computer, {@code NULL} for local login
+ * @param remote The remote computer, `NULL` for local login
* @param username The username of the user to log in to
* @param reader Function that can be used to read a passphrase from the terminal
*/
-void initialise_crypt(char* remote, char* username, char* (*reader)(void));
+void initialise_crypt(char *remote, char *username, char *(*reader)(void));
/**
* Perform token authentication
@@ -38,4 +38,3 @@ char authenticate_crypt(void);
#endif
-
diff --git a/src/auth/pam.c b/src/auth/pam.c
index 106462a..7ddc874 100644
--- a/src/auth/pam.c
+++ b/src/auth/pam.c
@@ -1,7 +1,7 @@
/**
* cerberus – Minimal login program
*
- * Copyright © 2013, 2014, 2015, 2016, 2020 Mattias Andrée (maandree@kth.se)
+ * Copyright © 2013, 2014, 2015, 2016, 2020 Mattias Andrée (m@maandree.se)
*
* 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
@@ -37,7 +37,7 @@ __attribute__((noreturn))
#endif
static void quit_pam(int sig);
-static int conv_pam(int num_msg, const struct pam_message** msg, struct pam_response** resp, void* appdata_ptr);
+static int conv_pam(int num_msg, const struct pam_message **msg, struct pam_response **resp, void *appdata_ptr);
/**
@@ -73,7 +73,7 @@ static char auto_authenticated = 1;
/**
* Function that can be used to read a passphrase from the terminal
*/
-static char* (*passphrase_reader)(void) = NULL;
+static char *(*passphrase_reader)(void) = NULL;
#ifdef __GNUC__
@@ -85,17 +85,17 @@ static char* (*passphrase_reader)(void) = NULL;
*
* @param rc What the PAM instruction return
*/
-static void do_pam(int rc)
+static void
+do_pam(int rc)
{
- if (__failed(rc))
- {
- const char* msg = pam_strerror(handle, rc);
- if (msg)
- fprintf(stderr, "%s\n", msg);
- pam_end(handle, rc);
- sleep(ERROR_SLEEP);
- _exit(1);
- }
+ if (__failed(rc)) {
+ const char *msg = pam_strerror(handle, rc);
+ if (msg)
+ fprintf(stderr, "%s\n", msg);
+ pam_end(handle, rc);
+ sleep(ERROR_SLEEP);
+ _exit(1);
+ }
}
#ifdef __GNUC__
# pragma GCC diagnostic pop
@@ -109,91 +109,92 @@ static void do_pam(int rc)
* @param username The username of the user to log in to
* @param reader Function that can be used to read a passphrase from the terminal
*/
-void initialise_pam(char* remote, char* username, char* (*reader)(void))
+void
+initialise_pam(char *remote, char *username, char *(*reader)(void))
{
- passphrase_reader = reader;
-
- if (pam_start(remote ? "remote" : "local", username, &conv, &handle) != PAM_SUCCESS)
- {
- fprintf(stderr, "Cannot initialise PAM\n");
- sleep(ERROR_SLEEP);
- _exit(1);
- }
-
- do_pam(pam_set_item(handle, PAM_RHOST, remote ?: "localhost"));
- do_pam(pam_set_item(handle, PAM_TTY, ttyname(STDIN_FILENO) ?: "(none)"));
- do_pam(pam_set_item(handle, PAM_USER_PROMPT, "Username: "));
+ passphrase_reader = reader;
+
+ if (pam_start(remote ? "remote" : "local", username, &conv, &handle) != PAM_SUCCESS) {
+ fprintf(stderr, "Cannot initialise PAM\n");
+ sleep(ERROR_SLEEP);
+ _exit(1);
+ }
+
+ do_pam(pam_set_item(handle, PAM_RHOST, remote ?: "localhost"));
+ do_pam(pam_set_item(handle, PAM_TTY, ttyname(STDIN_FILENO) ?: "(none)"));
+ do_pam(pam_set_item(handle, PAM_USER_PROMPT, "Username: "));
}
/**
* Verify that the account may be used
*/
-void verify_account_pam(void)
+void
+verify_account_pam(void)
{
- /* FIXME pam_acct_mgmt exits the program, but freezes if PAM_USER_PROMPT has not been set. */
- /* however, if -f is used there is no problem. */
- /*
- int rc = pam_acct_mgmt(handle, 0);
- if (rc == PAM_NEW_AUTHTOK_REQD)
- rc = pam_chauthtok(handle, PAM_CHANGE_EXPIRED_AUTHTOK);
- do_pam(rc);
- */
+ /* FIXME pam_acct_mgmt exits the program, but freezes if PAM_USER_PROMPT has not been set. */
+ /* however, if -f is used there is no problem. */
+ /*
+ int rc = pam_acct_mgmt(handle, 0);
+ if (rc == PAM_NEW_AUTHTOK_REQD)
+ rc = pam_chauthtok(handle, PAM_CHANGE_EXPIRED_AUTHTOK);
+ do_pam(rc);
+ */
}
/**
* Open PAM session
*/
-void open_session_pam(void)
+void
+open_session_pam(void)
{
- int rc;
- char** env;
- struct sigaction signal_action;
-
- do_pam(pam_setcred(handle, PAM_ESTABLISH_CRED));
-
- if (__failed(rc = pam_open_session(handle, 0)))
- {
- pam_setcred(handle, PAM_DELETE_CRED);
- do_pam(rc);
- }
-
- if (__failed(rc = pam_setcred(handle, PAM_REINITIALIZE_CRED)))
- {
- pam_close_session(handle, 0);
- do_pam(rc);
- }
-
- memset(&signal_action, 0, sizeof(signal_action));
- signal_action.sa_handler = SIG_IGN;
- sigaction(SIGINT, &signal_action, NULL);
- sigaction(SIGHUP, &signal_action, &signal_action_hup);
- signal_action.sa_handler = quit_pam;
- sigaction(SIGHUP, &signal_action, NULL);
- sigaction(SIGTERM, &signal_action, &signal_action_term);
-
- for (env = pam_getenvlist(handle); env && *env; env++)
- if (putenv(*env))
- {
- pam_setcred(handle, PAM_DELETE_CRED);
- pam_end(handle, pam_close_session(handle, 0));
- sleep(ERROR_SLEEP);
- _exit(1);
- }
+ int rc;
+ char **env;
+ struct sigaction signal_action;
+
+ do_pam(pam_setcred(handle, PAM_ESTABLISH_CRED));
+
+ if (__failed(rc = pam_open_session(handle, 0))) {
+ pam_setcred(handle, PAM_DELETE_CRED);
+ do_pam(rc);
+ }
+
+ if (__failed(rc = pam_setcred(handle, PAM_REINITIALIZE_CRED))) {
+ pam_close_session(handle, 0);
+ do_pam(rc);
+ }
+
+ memset(&signal_action, 0, sizeof(signal_action));
+ signal_action.sa_handler = SIG_IGN;
+ sigaction(SIGINT, &signal_action, NULL);
+ sigaction(SIGHUP, &signal_action, &signal_action_hup);
+ signal_action.sa_handler = quit_pam;
+ sigaction(SIGHUP, &signal_action, NULL);
+ sigaction(SIGTERM, &signal_action, &signal_action_term);
+
+ for (env = pam_getenvlist(handle); env && *env; env++) {
+ if (putenv(*env)) {
+ pam_setcred(handle, PAM_DELETE_CRED);
+ pam_end(handle, pam_close_session(handle, 0));
+ sleep(ERROR_SLEEP);
+ _exit(1);
+ }
+ }
}
/**
* Close PAM session
*/
-void close_session_pam(void)
+void
+close_session_pam(void)
{
- sigaction(SIGHUP, &signal_action_hup, NULL);
- sigaction(SIGTERM, &signal_action_term, NULL);
-
- pam_setcred(handle, PAM_DELETE_CRED);
- pam_end(handle, pam_close_session(handle, 0));
+ sigaction(SIGHUP, &signal_action_hup, NULL);
+ sigaction(SIGTERM, &signal_action_term, NULL);
+
+ pam_setcred(handle, PAM_DELETE_CRED);
+ pam_end(handle, pam_close_session(handle, 0));
}
@@ -202,17 +203,18 @@ void close_session_pam(void)
*
* @param sig The received signal
*/
-void quit_pam(int sig)
+void
+quit_pam(int sig)
{
- if (child_pid)
- kill(-child_pid, sig);
- if (sig == SIGTERM)
- kill(-child_pid, SIGHUP);
-
- pam_setcred(handle, PAM_DELETE_CRED);
- pam_end(handle, pam_close_session(handle, 0));
-
- _exit(sig);
+ if (child_pid)
+ kill(-child_pid, sig);
+ if (sig == SIGTERM)
+ kill(-child_pid, SIGHUP);
+
+ pam_setcred(handle, PAM_DELETE_CRED);
+ pam_end(handle, pam_close_session(handle, 0));
+
+ _exit(sig);
}
@@ -221,25 +223,25 @@ void quit_pam(int sig)
*
* @return 0: failed, 1: success, 2: auto-authenticated
*/
-char authenticate_pam(void)
+char
+authenticate_pam(void)
{
- int rc;
-
- if (__failed(rc = pam_authenticate(handle, 0)))
- {
- /* Clear ISIG (and everything else) to prevent the user
- * from skipping the brute force protection sleep. */
- struct termios stty;
- tcgetattr(STDIN_FILENO, &stty);
- stty.c_lflag = 0;
- tcsetattr(STDIN_FILENO, TCSAFLUSH, &stty);
-
- printf("\nPassphrase incorrect.\nOnly perfect spellers may\nenter this system.\n");
- pam_end(handle, rc);
- return 0;
- }
-
- return auto_authenticated ? 2 : 1;
+ int rc;
+
+ if (__failed(rc = pam_authenticate(handle, 0))) {
+ /* Clear ISIG (and everything else) to prevent the user
+ * from skipping the brute force protection sleep. */
+ struct termios stty;
+ tcgetattr(STDIN_FILENO, &stty);
+ stty.c_lflag = 0;
+ tcsetattr(STDIN_FILENO, TCSAFLUSH, &stty);
+
+ printf("\nPassphrase incorrect.\nOnly perfect spellers may\nenter this system.\n");
+ pam_end(handle, rc);
+ return 0;
+ }
+
+ return auto_authenticated ? 2 : 1;
}
@@ -252,26 +254,24 @@ char authenticate_pam(void)
* @param appdata_ptr (Not used)
* @return `PAM_SUCCESS`, `PAM_CONV_ERR` or `PAM_BUF_ERR`
*/
-int conv_pam(int num_msg, const struct pam_message** msg, struct pam_response** resp, void* appdata_ptr)
+int
+conv_pam(int num_msg, const struct pam_message **msg, struct pam_response **resp, void *appdata_ptr)
{
- int i;
-
- (void) appdata_ptr;
-
- *resp = calloc((size_t)num_msg, sizeof(struct pam_response));
-
- for (i = 0; i < num_msg; i++)
- {
- ((*resp) + i)->resp = NULL;
- ((*resp) + i)->resp_retcode = 0;
-
- if ((**(msg + i)).msg_style == PAM_PROMPT_ECHO_OFF)
- {
- (*resp + i)->resp = passphrase_reader();
- auto_authenticated = 0;
+ int i;
+
+ (void) appdata_ptr;
+
+ *resp = calloc((size_t)num_msg, sizeof(struct pam_response));
+
+ for (i = 0; i < num_msg; i++) {
+ (*resp)[i].resp = NULL;
+ (*resp)[i].resp_retcode = 0;
+
+ if ((**msg[i]).msg_style == PAM_PROMPT_ECHO_OFF) {
+ (*resp)[i].resp = passphrase_reader();
+ auto_authenticated = 0;
+ }
}
- }
-
- return PAM_SUCCESS;
-}
+ return PAM_SUCCESS;
+}
diff --git a/src/auth/pam.h b/src/auth/pam.h
index ecfe03a..0b85631 100644
--- a/src/auth/pam.h
+++ b/src/auth/pam.h
@@ -1,7 +1,7 @@
/**
* cerberus – Minimal login program
*
- * Copyright © 2013, 2014, 2015, 2016, 2020 Mattias Andrée (maandree@kth.se)
+ * Copyright © 2013, 2014, 2015, 2016, 2020 Mattias Andrée (m@maandree.se)
*
* 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
@@ -23,11 +23,11 @@
/**
* Initialise PAM
*
- * @param remote The remote computer, {@code NULL} for local login
+ * @param remote The remote computer, `NULL` for local login
* @param username The username of the user to log in to
* @param reader Function that can be used to read a passphrase from the terminal
*/
-void initialise_pam(char* remote, char* username, char* (*reader)(void));
+void initialise_pam(char *remote, char *username, char *(*reader)(void));
/**
* Verify that the account may be used
@@ -53,4 +53,3 @@ char authenticate_pam(void);
#endif
-
diff --git a/src/cerberus.c b/src/cerberus.c
index 0cd06b4..9fccbf9 100644
--- a/src/cerberus.c
+++ b/src/cerberus.c
@@ -1,7 +1,7 @@
/**
* cerberus – Minimal login program
*
- * Copyright © 2013, 2014, 2015, 2016, 2020 Mattias Andrée (maandree@kth.se)
+ * Copyright © 2013, 2014, 2015, 2016, 2020 Mattias Andrée (m@maandree.se)
*
* 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
@@ -72,7 +72,7 @@ static char skip_auth = 0;
/**
* The passphrase
*/
-char* passphrase = NULL;
+char *passphrase = NULL;
#endif
@@ -81,59 +81,59 @@ char* passphrase = NULL;
*
* @param s The number of seconds to sleep
*/
-static void xsleep(unsigned int s)
+static void
+xsleep(unsigned int s)
{
- sigset_t sigset;
- sigset_t old_sigset;
-
- sigfillset(&sigset);
- sigprocmask(SIG_BLOCK, &sigset, &old_sigset);
-
- while ((s = sleep(s)));
-
- sigprocmask(SIG_SETMASK, &old_sigset, NULL);
+ sigset_t sigset;
+ sigset_t old_sigset;
+
+ sigfillset(&sigset);
+ sigprocmask(SIG_BLOCK, &sigset, &old_sigset);
+
+ while ((s = sleep(s)));
+
+ sigprocmask(SIG_SETMASK, &old_sigset, NULL);
}
/**
- * Mane method
+ * Main method
*
* @param argc The number of command line arguments
* @param argv The command line arguments
* @return Return code
*/
-int main(int argc, char** argv)
+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 != 0) dup2(fd, 0);
- if (fd != 1) dup2(fd, 1);
- if (fd != 2) dup2(fd, 2);
- }
-
- /* Reset terminal ownership and mode */
- chown_tty(0, tty_group, 0);
-
- /* Close login session */
- close_login_session();
-
- /* Run logout hook */
- exec_hook(HOOK_LOGOUT, argc, argv);
- return 0;
+ 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 != 0) dup2(fd, 0);
+ if (fd != 1) dup2(fd, 1);
+ if (fd != 2) dup2(fd, 2);
+ }
+
+ /* Reset terminal ownership and mode */
+ chown_tty(0, tty_group, 0);
+
+ /* Close login session */
+ close_login_session();
+
+ /* Run logout hook */
+ exec_hook(HOOK_LOGOUT, argc, argv);
+ return 0;
}
@@ -144,33 +144,32 @@ int main(int argc, char** argv)
* @param argc The number of command line arguments
* @param argv The command line arguments
*/
-void exec_hook(int hook, int argc, char** argv)
+void
+exec_hook(int hook, int argc, char **argv)
{
- static char cerberusrc[] = CERBERUSRC;
- static char hooks[][7] =
- {
- [HOOK_LOGIN] = "login",
- [HOOK_LOGOUT] = "logout",
- [HOOK_DENIED] = "denied",
- [HOOK_VERIFY] = "verify",
- };
- char** args;
- int i;
-
- args = malloc((size_t)(argc + 2) * sizeof(char*));
- if (args == NULL)
- {
- perror("malloc");
- return;
- }
-
- args[0] = cerberusrc;
- args[1] = hooks[hook];
- for (i = 1; i < argc; i++)
- args[i + 1] = argv[i];
- args[argc + 1] = NULL;
-
- execv(CERBERUSRC, args);
+ static char cerberusrc[] = CERBERUSRC;
+ static char hooks[][7] = {
+ [HOOK_LOGIN] = "login",
+ [HOOK_LOGOUT] = "logout",
+ [HOOK_DENIED] = "denied",
+ [HOOK_VERIFY] = "verify",
+ };
+ char **args;
+ int i;
+
+ args = malloc((size_t)(argc + 2) * sizeof(char*));
+ if (!args) {
+ perror("malloc");
+ return;
+ }
+
+ args[0] = cerberusrc;
+ args[1] = hooks[hook];
+ for (i = 1; i < argc; i++)
+ args[i + 1] = argv[i];
+ args[argc + 1] = NULL;
+
+ execv(CERBERUSRC, args);
}
@@ -182,30 +181,28 @@ void exec_hook(int hook, int argc, char** argv)
* @param argv The command line arguments
* @return The exit value of the hook
*/
-int fork_exec_wait_hook(int hook, int argc, char** argv)
+int
+fork_exec_wait_hook(int hook, int argc, char **argv)
{
- pid_t pid, reaped;
- int status;
- pid = fork();
- if (pid == -1)
- return -1;
- if (pid == 0)
- {
- close(STDIN_FILENO);
- exec_hook(hook, argc, argv);
- _exit(138);
- }
- for (;;)
- {
- reaped = wait(&status);
- if (reaped == -1)
- {
- perror("wait");
- return -1;
+ pid_t pid, reaped;
+ int status;
+ pid = fork();
+ if (pid == -1)
+ return -1;
+ if (pid == 0) {
+ close(STDIN_FILENO);
+ exec_hook(hook, argc, argv);
+ _exit(138);
+ }
+ for (;;) {
+ reaped = wait(&status);
+ if (reaped == -1) {
+ perror("wait");
+ return -1;
+ }
+ if (reaped == pid)
+ return status == 138 ? -1 : status;
}
- if (reaped == pid)
- return status == 138 ? -1 : status;
- }
}
@@ -215,246 +212,229 @@ int fork_exec_wait_hook(int hook, int argc, char** argv)
* @param argc The number of command line arguments
* @param argv The command line arguments
*/
-void do_login(int argc, char** argv)
+void
+do_login(int argc, char **argv)
{
- char* username = NULL;
- char* hostname = NULL;
- char preserve_env = 0;
- int ret;
- #ifdef USE_TTY_GROUP
- struct group* group;
- #endif
-
-
- #if AUTH > 0
- /* Disable echoing */
- passphrase_disable_echo1(STDIN_FILENO /* Will be the terminal. */);
- /* 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. */
- #endif
-
-
- /* 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 == 'H')
- ;
- else if (c == 'V')
- _exit(2);
- 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);
- }
-
-
- /* Verify that the user may login */
- ret = fork_exec_wait_hook(HOOK_VERIFY, argc, argv);
- if ((ret >= 0) && WIFEXITED(ret) && (WEXITSTATUS(ret) == 1))
- {
- sleep(ERROR_SLEEP);
- _exit(2);
- }
-
-
- if (skip_auth)
- {
- /* Reset terminal settings */
- passphrase_reenable_echo1(STDIN_FILENO);
-
- /* Only root may bypass authentication */
- if (getuid())
+ char *username = NULL;
+ char *hostname = NULL;
+ char preserve_env = 0;
+ int ret;
+#ifdef USE_TTY_GROUP
+ struct group *group;
+#endif
+
+
+#if AUTH > 0
+ /* Disable echoing */
+ passphrase_disable_echo1(STDIN_FILENO /* Will be the terminal. */);
+ /* 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. */
+#endif
+
+
+ /* Set process group ID */
+ setpgrp();
+
+
+ /* Parse command line arguments */
{
- printf("%s: only root by use the -f option\n", *argv);
- sleep(ERROR_SLEEP);
- _exit(2);
+ 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) {
+ continue;
+ } else if (*arg == '-' && !double_dashed) {
+ while ((c = *++arg))
+ if (c == 'H') {
+ continue;
+ } else if (c == 'V') {
+ _exit(2);
+ } 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) {
+ printf("%s: no username specified\n", *argv);
+ sleep(ERROR_SLEEP);
+ _exit(2);
+ }
+
+
+ /* Verify that the user may login */
+ ret = fork_exec_wait_hook(HOOK_VERIFY, argc, argv);
+ if (ret >= 0 && WIFEXITED(ret) && WEXITSTATUS(ret) == 1) {
+ sleep(ERROR_SLEEP);
+ _exit(2);
+ }
+
+
+ if (skip_auth) {
+ /* Reset terminal settings */
+ passphrase_reenable_echo1(STDIN_FILENO);
+
+ /* Only root may bypass authentication */
+ if (getuid()) {
+ printf("%s: only root by use the -f option\n", *argv);
+ sleep(ERROR_SLEEP);
+ _exit(2);
+ }
+ } else {
+ /* Print ant we want a passphrase, if -f has not been used */
+ printf("Passphrase: ");
+ fflush(stdout);
}
- }
- /* Print ant we want a passphrase, if -f has not been used */
- else
- {
- 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);
-
- #if AUTH > 0
- if (skip_auth == 0)
- {
- /* Redisable echoing */
- passphrase_disable_echo1(STDIN_FILENO);
- }
- #endif
-
-
- /* 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);
- #if AUTH > 0
- alarm(TIMEOUT_SECONDS);
- #endif
-
-
- /* Get user information */
- if ((entry = getpwnam(username)) == NULL)
- {
- if (errno == EIO /* seriously...? */ || !errno)
- printf("User does not exist\n");
- else if (errno)
- perror("getpwnam");
- sleep(ERROR_SLEEP);
- _exit(1);
- }
- endpwent();
- username = entry->pw_name;
-
-
- /* Verify passphrase or other token, if -f has not been used */
- ret = 2;
- #if AUTH == 0
- (void) hostname;
- #else
- initialise_login(hostname, username, read_passphrase);
- if (skip_auth == 0)
- ret = authenticate_login();
- /* Passphrase entered, turn off timeout */
- alarm(0);
- #endif
- if (ret == 2)
- printf("(auto-authenticated)\n");
- if (ret == 0)
- {
- preexit();
- fork_exec_wait_hook(HOOK_DENIED, argc, argv);
- xsleep(FAILURE_SLEEP);
- _exit(1);
- }
-
- preexit();
-
-
- /* Verify account, such as that it is enabled */
- verify_account();
-
-
- /* Run login hook */
- fork_exec_wait_hook(HOOK_LOGIN, argc, argv);
-
-
- /* 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);
+ /* Done early to make to program look like it is even faster than it is */
+
+
+ /* Make sure nobody is spying */
+#ifdef USE_TTY_GROUP
+ if ((group = getgrnam(TTY_GROUP)))
+ tty_group = group->gr_gid;
+ endgrent();
+#endif
+ secure_tty(tty_group);
+
+#if AUTH > 0
+ if (!skip_auth) {
+ /* Redisable echoing */
+ passphrase_disable_echo1(STDIN_FILENO);
+ }
+#endif
+
+
+ /* 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);
+#if AUTH > 0
+ alarm(TIMEOUT_SECONDS);
+#endif
+
+
+ /* Get user information */
+ if (!(entry = getpwnam(username))) {
+ if (errno == EIO /* seriously...? */ || !errno)
+ printf("User does not exist\n");
+ else if (errno)
+ perror("getpwnam");
+ sleep(ERROR_SLEEP);
+ _exit(1);
+ }
+ endpwent();
+ username = entry->pw_name;
+
+
+ /* Verify passphrase or other token, if -f has not been used */
+ ret = 2;
+#if AUTH == 0
+ (void) hostname;
+#else
+ initialise_login(hostname, username, read_passphrase);
+ if (skip_auth == 0)
+ ret = authenticate_login();
+ /* Passphrase entered, turn off timeout */
+ alarm(0);
+#endif
+ if (ret == 2)
+ printf("(auto-authenticated)\n");
+ if (ret == 0) {
+ preexit();
+ fork_exec_wait_hook(HOOK_DENIED, argc, argv);
+ xsleep(FAILURE_SLEEP);
+ _exit(1);
+ }
+
+ preexit();
+
+
+ /* Verify account, such as that it is enabled */
+ verify_account();
+
+
+ /* Run login hook */
+ fork_exec_wait_hook(HOOK_LOGIN, argc, argv);
+
+
+ /* 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);
}
@@ -463,16 +443,16 @@ void do_login(int argc, char** argv)
/**
* Called before the process exits, to do cleanup
*/
-void preexit(void)
+void
+preexit(void)
{
- if (skip_auth == 0)
- {
- /* Wipe and free the passphrase from the memory */
- destroy_passphrase();
-
- /* Reset terminal settings */
- passphrase_reenable_echo1(STDIN_FILENO);
- }
+ if (!skip_auth) {
+ /* Wipe and free the passphrase from the memory */
+ destroy_passphrase();
+
+ /* Reset terminal settings */
+ passphrase_reenable_echo1(STDIN_FILENO);
+ }
}
@@ -481,16 +461,16 @@ void preexit(void)
*
* @return The entered passphrase
*/
-char* read_passphrase(void)
+char *
+read_passphrase(void)
{
- passphrase = passphrase_read2(STDIN_FILENO, PASSPHRASE_READ_EXISTING);
- if (passphrase == NULL)
- {
- perror("passphrase_read");
- sleep(ERROR_SLEEP);
- _exit(1);
- }
- return passphrase;
+ passphrase = passphrase_read2(STDIN_FILENO, PASSPHRASE_READ_EXISTING);
+ if (!passphrase) {
+ perror("passphrase_read");
+ sleep(ERROR_SLEEP);
+ _exit(1);
+ }
+ return passphrase;
}
#endif
@@ -503,14 +483,14 @@ char* read_passphrase(void)
/**
* Wipe and free the passphrase if it is allocated
*/
-void destroy_passphrase(void)
+void
+destroy_passphrase(void)
{
- if (passphrase)
- {
- passphrase_wipe(passphrase, strlen(passphrase));
- free(passphrase);
- passphrase = NULL;
- }
+ if (passphrase) {
+ passphrase_wipe(passphrase, strlen(passphrase));
+ free(passphrase);
+ passphrase = NULL;
+ }
}
@@ -520,8 +500,8 @@ void destroy_passphrase(void)
#ifdef __GNUC__
__attribute__((destructor))
#endif
-static void passphrase_destructor(void)
+static void
+passphrase_destructor(void)
{
- destroy_passphrase();
+ destroy_passphrase();
}
-
diff --git a/src/cerberus.h b/src/cerberus.h
index a81b8a0..038ce2a 100644
--- a/src/cerberus.h
+++ b/src/cerberus.h
@@ -1,7 +1,7 @@
/**
* cerberus – Minimal login program
*
- * Copyright © 2013, 2014, 2015, 2016, 2020 Mattias Andrée (maandree@kth.se)
+ * Copyright © 2013, 2014, 2015, 2016, 2020 Mattias Andrée (m@maandree.se)
*
* 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
@@ -20,18 +20,18 @@
#define CERBERUS_CERBERUS_H
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <signal.h>
-#include <pwd.h>
-#include <errno.h>
-#include <termios.h>
-#include <fcntl.h>
-#include <sys/wait.h>
#include <sys/ioctl.h>
#include <sys/types.h>
+#include <sys/wait.h>
+#include <errno.h>
+#include <fcntl.h>
#include <grp.h>
+#include <pwd.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <termios.h>
+#include <unistd.h>
#if AUTH > 0
#include <passphrase.h>
@@ -50,13 +50,13 @@
#endif
-int fork_exec_wait_hook(int hook, int argc, char** argv);
-void exec_hook(int hook, int argc, char** argv);
-void do_login(int argc, char** argv);
+int fork_exec_wait_hook(int hook, int argc, char **argv);
+void exec_hook(int hook, int argc, char **argv);
+void do_login(int argc, char **argv);
#if AUTH > 0
void preexit(void);
-char* read_passphrase(void);
+char *read_passphrase(void);
#else
#define preexit() /* do nothing */
#define read_passphrase() NULL
@@ -69,4 +69,3 @@ void destroy_passphrase(void);
#endif
-
diff --git a/src/config.h b/src/config.h
index aa144b2..761be58 100644
--- a/src/config.h
+++ b/src/config.h
@@ -1,7 +1,7 @@
/**
* cerberus – Minimal login program
*
- * Copyright © 2013, 2014, 2015, 2016, 2020 Mattias Andrée (maandree@kth.se)
+ * Copyright © 2013, 2014, 2015, 2016, 2020 Mattias Andrée (m@maandree.se)
*
* 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
@@ -58,4 +58,3 @@
#endif
-
diff --git a/src/login.c b/src/login.c
index e99b77f..3cb0877 100644
--- a/src/login.c
+++ b/src/login.c
@@ -1,7 +1,7 @@
/**
* cerberus – Minimal login program
*
- * Copyright © 2013, 2014, 2015, 2016, 2020 Mattias Andrée (maandree@kth.se)
+ * Copyright © 2013, 2014, 2015, 2016, 2020 Mattias Andrée (m@maandree.se)
*
* 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
@@ -30,7 +30,7 @@
/**
* The environment variables
*/
-extern char** environ;
+extern char **environ;
/**
@@ -38,19 +38,18 @@ extern char** environ;
*
* @param entry The user entry in the password file
*/
-void set_user(struct passwd* entry)
+void
+set_user(struct passwd *entry)
{
- if (setgid(entry->pw_gid) && entry->pw_gid)
- {
- perror("setgid");
- _exit(1);
- }
-
- if (setuid(entry->pw_uid) && entry->pw_uid)
- {
- perror("setuid");
- _exit(1);
- }
+ if (setgid(entry->pw_gid) && entry->pw_gid) {
+ perror("setgid");
+ _exit(1);
+ }
+
+ if (setuid(entry->pw_uid) && entry->pw_uid) {
+ perror("setuid");
+ _exit(1);
+ }
}
@@ -59,19 +58,18 @@ void set_user(struct passwd* entry)
*
* @param entry The user entry in the password file
*/
-void chdir_home(struct passwd* entry)
+void
+chdir_home(struct passwd *entry)
{
- if (chdir(entry->pw_dir))
- {
- perror("chdir");
- if (chdir(DEFAULT_HOME))
- {
- perror("chdir");
- sleep(ERROR_SLEEP);
- _exit(1);
+ if (chdir(entry->pw_dir)) {
+ perror("chdir");
+ if (chdir(DEFAULT_HOME)) {
+ perror("chdir");
+ sleep(ERROR_SLEEP);
+ _exit(1);
+ }
+ entry->pw_dir = strdup(DEFAULT_HOME);
}
- entry->pw_dir = strdup(DEFAULT_HOME);
- }
}
@@ -80,10 +78,11 @@ void chdir_home(struct passwd* entry)
*
* @param entry The user entry in the password file
*/
-void ensure_shell(struct passwd* entry)
+void
+ensure_shell(struct passwd *entry)
{
- if ((entry->pw_shell && *(entry->pw_shell)) == 0)
- entry->pw_shell = strdup(DEFAULT_SHELL);
+ if (!entry->pw_shell || !*entry->pw_shell)
+ entry->pw_shell = strdup(DEFAULT_SHELL);
}
@@ -93,47 +92,43 @@ void ensure_shell(struct passwd* entry)
* @param entry The user entry in the password file
* @param preserve_env Whether to preserve the environment
*/
-void set_environ(struct passwd* entry, char preserve_env)
+void
+set_environ(struct passwd *entry, char preserve_env)
{
- char* _term = getenv("TERM");
- char* term = NULL;
- if (_term)
- {
- size_t n = 0, i;
- while (*(_term + n++))
- ;
- term = malloc(n * sizeof(char));
- if (term == NULL)
- {
- perror("malloc");
- sleep(ERROR_SLEEP);
- _exit(1);
+ char *_term = getenv("TERM");
+ char *term = NULL;
+ if (_term) {
+ size_t n = 0, i;
+ while (_term[n++]) ;
+ term = malloc(n * sizeof(char));
+ if (!term) {
+ perror("malloc");
+ sleep(ERROR_SLEEP);
+ _exit(1);
+ }
+ for (i = 0; i < n; i++)
+ *(term + i) = *(_term + i);
}
- for (i = 0; i < n; i++)
- *(term + i) = *(_term + i);
- }
-
- if (preserve_env == 0)
- {
- environ = malloc(sizeof(char*));
- if (environ == NULL)
- {
- perror("malloc");
- sleep(ERROR_SLEEP);
- _exit(1);
+
+ if (!preserve_env) {
+ environ = malloc(sizeof(char*));
+ if (!environ) {
+ perror("malloc");
+ sleep(ERROR_SLEEP);
+ _exit(1);
+ }
+ *environ = NULL;
}
- *environ = NULL;
- }
-
- setenv("HOME", entry->pw_dir, 1);
- setenv("USER", entry->pw_name, 1);
- setenv("LOGUSER", entry->pw_name, 1);
- setenv("SHELL", entry->pw_shell, 1);
- setenv("TERM", term ?: DEFAULT_TERM, 1);
- setenv("PATH", entry->pw_uid ? PATH : PATH_ROOT, 1);
-
- if (term)
- free(term);
+
+ setenv("HOME", entry->pw_dir, 1);
+ setenv("USER", entry->pw_name, 1);
+ setenv("LOGUSER", entry->pw_name, 1);
+ setenv("SHELL", entry->pw_shell, 1);
+ setenv("TERM", term ?: DEFAULT_TERM, 1);
+ setenv("PATH", entry->pw_uid ? PATH : PATH_ROOT, 1);
+
+ if (term)
+ free(term);
}
@@ -142,59 +137,53 @@ void set_environ(struct passwd* entry, char preserve_env)
*
* @param entry The user entry in the password file
*/
-void exec_shell(struct passwd* entry)
+void
+exec_shell(struct passwd *entry)
{
- int child_argc = 0;
- char** child_argv = malloc(5 * sizeof(char*));
- size_t n = 0;
- char* sh = entry->pw_shell;
- char* login_sh;
-
- while (*(sh + n++))
- ;
-
- login_sh = malloc((n + (strchr(sh, ' ') ? 5 : 1)) * sizeof(char));
- if (login_sh == NULL)
- {
- perror("malloc");
- sleep(ERROR_SLEEP);
- _exit(1);
- }
-
- if (strchr(sh, ' '))
- {
- login_sh += 5;
- strcpy(login_sh, "exec ");
- *(login_sh + n) = 0;
-
- *(child_argv + child_argc++) = strdup(DEFAULT_SHELL);
- *(child_argv + child_argc++) = strdup("-" DEFAULT_SH);
- *(child_argv + child_argc++) = strdup("-c");
- *(child_argv + child_argc++) = login_sh - 5;
- }
- else
- {
- ssize_t i;
- for (i = (ssize_t)n - 1; i >= 0; i--)
- if (*(sh + i) == '/')
- {
- i++;
- break;
- }
-
- login_sh = malloc((n + 1) * sizeof(char));
- *login_sh++ = '-';
- strcpy(login_sh, sh + i);
- *(login_sh + n) = 0;
-
- *(child_argv + child_argc++) = sh;
- *(child_argv + child_argc++) = login_sh - 1;
- }
-
- *(child_argv + child_argc) = NULL;
- execvp(*child_argv, child_argv + 1);
- perror("execvp");
- sleep(ERROR_SLEEP);
- _exit(1);
-}
+ int child_argc = 0;
+ char **child_argv = malloc(5 * sizeof(char *));
+ size_t n = 0;
+ char *sh = entry->pw_shell;
+ char *login_sh;
+
+ while (sh[n++]) ;
+ login_sh = malloc((n + (strchr(sh, ' ') ? 5 : 1)) * sizeof(char));
+ if (!login_sh) {
+ perror("malloc");
+ sleep(ERROR_SLEEP);
+ _exit(1);
+ }
+
+ if (strchr(sh, ' ')) {
+ login_sh += 5;
+ strcpy(login_sh, "exec ");
+ login_sh[n] = 0;
+
+ child_argv[child_argc++] = strdup(DEFAULT_SHELL);
+ child_argv[child_argc++] = strdup("-" DEFAULT_SH);
+ child_argv[child_argc++] = strdup("-c");
+ child_argv[child_argc++] = login_sh - 5;
+ } else {
+ ssize_t i;
+ for (i = (ssize_t)n - 1; i >= 0; i--)
+ if (sh[i] == '/') {
+ i++;
+ break;
+ }
+
+ login_sh = malloc((n + 1U) * sizeof(char));
+ *login_sh++ = '-';
+ strcpy(login_sh, &sh[i]);
+ login_sh[n] = 0;
+
+ child_argv[child_argc++] = sh;
+ child_argv[child_argc++] = &login_sh[-1];
+ }
+
+ child_argv[child_argc] = NULL;
+ execvp(child_argv[0], &child_argv[1]);
+ perror("execvp");
+ sleep(ERROR_SLEEP);
+ _exit(1);
+}
diff --git a/src/login.h b/src/login.h
index a672434..ecf4107 100644
--- a/src/login.h
+++ b/src/login.h
@@ -1,7 +1,7 @@
/**
* cerberus – Minimal login program
*
- * Copyright © 2013, 2014, 2015, 2016, 2020 Mattias Andrée (maandree@kth.se)
+ * Copyright © 2013, 2014, 2015, 2016, 2020 Mattias Andrée (m@maandree.se)
*
* 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
@@ -27,21 +27,21 @@
*
* @param entry The user entry in the password file
*/
-void set_user(struct passwd* entry);
+void set_user(struct passwd *entry);
/**
* Change directory to the user's home directory
*
* @param entry The user entry in the password file
*/
-void chdir_home(struct passwd* entry);
+void chdir_home(struct passwd *entry);
/**
* Make sure the shell to use is definied
*
* @param entry The user entry in the password file
*/
-void ensure_shell(struct passwd* entry);
+void ensure_shell(struct passwd *entry);
/**
* Set environment variables
@@ -49,7 +49,7 @@ void ensure_shell(struct passwd* entry);
* @param entry The user entry in the password file
* @param preserve_env Whether to preserve the environment
*/
-void set_environ(struct passwd* entry, char preserve_env);
+void set_environ(struct passwd *entry, char preserve_env);
/**
* Replace the current image with the user's login shell
@@ -59,8 +59,7 @@ void set_environ(struct passwd* entry, char preserve_env);
#ifdef __GNUC__
__attribute__((noreturn))
#endif
-void exec_shell(struct passwd* entry);
+void exec_shell(struct passwd *entry);
#endif
-
diff --git a/src/quit.c b/src/quit.c
index e26fca1..2a8bbf3 100644
--- a/src/quit.c
+++ b/src/quit.c
@@ -1,7 +1,7 @@
/**
* cerberus – Minimal login program
*
- * Copyright © 2013, 2014, 2015, 2016, 2020 Mattias Andrée (maandree@kth.se)
+ * Copyright © 2013, 2014, 2015, 2016, 2020 Mattias Andrée (m@maandree.se)
*
* 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
@@ -31,15 +31,16 @@
*
* @param signal The signal the program received
*/
-void timeout_quit(int signal)
+void
+timeout_quit(int signal)
{
- (void) signal;
- printf("\nTimed out.\n");
- #if AUTH != 0
- passphrase_reenable_echo1(STDIN_FILENO);
- #endif
- sleep(ERROR_SLEEP);
- _exit(10);
+ (void) signal;
+ printf("\nTimed out.\n");
+#if AUTH != 0
+ passphrase_reenable_echo1(STDIN_FILENO);
+#endif
+ sleep(ERROR_SLEEP);
+ _exit(10);
}
@@ -48,13 +49,13 @@ void timeout_quit(int signal)
*
* @param signal The signal the program received
*/
-void user_quit(int signal)
+void
+user_quit(int signal)
{
- (void) signal;
- printf("\n");
- #if AUTH != 0
- passphrase_reenable_echo1(STDIN_FILENO);
- #endif
- _exit(130);
+ (void) signal;
+ printf("\n");
+#if AUTH != 0
+ passphrase_reenable_echo1(STDIN_FILENO);
+#endif
+ _exit(130);
}
-
diff --git a/src/quit.h b/src/quit.h
index f5e8c74..012f265 100644
--- a/src/quit.h
+++ b/src/quit.h
@@ -1,7 +1,7 @@
/**
* cerberus – Minimal login program
*
- * Copyright © 2013, 2014, 2015, 2016, 2020 Mattias Andrée (maandree@kth.se)
+ * Copyright © 2013, 2014, 2015, 2016, 2020 Mattias Andrée (m@maandree.se)
*
* 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
@@ -42,4 +42,3 @@ void user_quit(int signal);
#endif
-
diff --git a/src/security.c b/src/security.c
index 9a1faf3..54ab501 100644
--- a/src/security.c
+++ b/src/security.c
@@ -1,7 +1,7 @@
/**
* cerberus – Minimal login program
*
- * Copyright © 2013, 2014, 2015, 2016, 2020 Mattias Andrée (maandree@kth.se)
+ * Copyright © 2013, 2014, 2015, 2016, 2020 Mattias Andrée (m@maandree.se)
*
* 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
@@ -39,11 +39,12 @@
*
* @param str The function that failed.
*/
-static void fail(const char* str)
+static
+void fail(const char *str)
{
- perror(str);
- sleep(ERROR_SLEEP);
- _exit(1);
+ perror(str);
+ sleep(ERROR_SLEEP);
+ _exit(1);
}
@@ -52,44 +53,45 @@ static void fail(const char* str)
*
* @param group The group, -1 for unchanged
*/
-void secure_tty(gid_t group)
+void
+secure_tty(gid_t group)
{
- struct termios tty;
- struct termios saved_tty;
- char* tty_device;
- int fd, i;
-
- /* Set ownership of this TTY to root:root */
- chown_tty(0, group, 1);
-
- /* Get TTY name for last part of this functions */
- tty_device = ttyname(STDIN_FILENO);
-
- /* Kill other processes on this TTY */
- tcgetattr(STDIN_FILENO, &tty);
- saved_tty = tty;
- tty.c_cflag &= (tcflag_t)~HUPCL;
- tcsetattr(0, TCSANOW, &tty);
- close(STDIN_FILENO);
- close(STDOUT_FILENO);
- close(STDERR_FILENO);
- signal(SIGHUP, SIG_IGN);
- vhangup();
- signal(SIGHUP, SIG_DFL);
-
- /* Restore terminal and TTY modes */
- fd = open(tty_device, O_RDWR | O_NONBLOCK);
- if (fd == -1)
- fail("open");
- fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) & ~O_NONBLOCK);
- for (i = 0; i < fd; i++)
- close(i);
- for (i = 0; i < 3; i++)
- if (i != fd)
- dup2(fd, i);
- if (fd > 2)
- close(fd);
- tcgetattr(STDIN_FILENO, &saved_tty);
+ struct termios tty;
+ struct termios saved_tty;
+ char *tty_device;
+ int fd, i;
+
+ /* Set ownership of this TTY to root:root */
+ chown_tty(0, group, 1);
+
+ /* Get TTY name for last part of this functions */
+ tty_device = ttyname(STDIN_FILENO);
+
+ /* Kill other processes on this TTY */
+ tcgetattr(STDIN_FILENO, &tty);
+ saved_tty = tty;
+ tty.c_cflag &= (tcflag_t)~HUPCL;
+ tcsetattr(0, TCSANOW, &tty);
+ close(STDIN_FILENO);
+ close(STDOUT_FILENO);
+ close(STDERR_FILENO);
+ signal(SIGHUP, SIG_IGN);
+ vhangup();
+ signal(SIGHUP, SIG_DFL);
+
+ /* Restore terminal and TTY modes */
+ fd = open(tty_device, O_RDWR | O_NONBLOCK);
+ if (fd == -1)
+ fail("open");
+ fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) & ~O_NONBLOCK);
+ for (i = 0; i < fd; i++)
+ close(i);
+ for (i = 0; i < 3; i++)
+ if (i != fd)
+ dup2(fd, i);
+ if (fd > 2)
+ close(fd);
+ tcgetattr(STDIN_FILENO, &saved_tty);
}
@@ -100,57 +102,54 @@ void secure_tty(gid_t group)
* @param group The group, -1 for unchanged
* @param with_fail Abort on failure
*/
-void chown_tty(uid_t owner, gid_t group, char with_fail)
+void
+chown_tty(uid_t owner, gid_t group, char with_fail)
{
- #if defined(OWN_VCSA) || defined(OWN_VCS)
- struct vt_stat vtstat;
- #endif
-
- /* Set ownership of this TTY */
- if (fchown(STDIN_FILENO, owner, group) && with_fail)
- fail("fchown");
-
- /* Restrict others from using this TTY */
- if (fchmod(STDIN_FILENO, TTY_PERM) && with_fail)
- fail("fchmod");
-
- /* Also do the above for /dev/vcs[a][0-9]+ */
- #if defined(OWN_VCSA) || defined(OWN_VCS)
- if (ioctl(STDIN_FILENO, VT_GETSTATE, &vtstat) == 0)
- {
- int n = vtstat.v_active;
- char _vcs[VCS_LEN + 6];
- char _vcsa[VCSA_LEN + 6];
-
- char* vcs = _vcs;
- char* vcsa = _vcsa;
- vcs += VCS_LEN + 6;
- vcsa += VCSA_LEN + 6;
-
- if (n)
- {
- *--vcs = *--vcsa = 0;
- while (n)
- {
- *--vcs = *--vcsa = (char)((n % 10) + '0');
- n /= 10;
- }
-
- vcs -= VCS_LEN;
- vcsa -= VCSA_LEN;
- strncpy(vcs, VCS, VCS_LEN);
- strncpy(vcsa, VCSA, VCSA_LEN);
-
- #ifdef OWN_VCS
- if (chown(vcs, owner, group) && with_fail) fail("chown");
- if (chmod(vcs, TTY_PERM) && with_fail) fail("chmod");
- #endif
- #ifdef OWN_VCSA
- if (chown(vcsa, owner, group) && with_fail) fail("chown");
- if (chmod(vcsa, TTY_PERM) && with_fail) fail("chmod");
- #endif
- }
- }
- #endif
-}
+#if defined(OWN_VCSA) || defined(OWN_VCS)
+ struct vt_stat vtstat;
+#endif
+
+ /* Set ownership of this TTY */
+ if (fchown(STDIN_FILENO, owner, group) && with_fail)
+ fail("fchown");
+
+ /* Restrict others from using this TTY */
+ if (fchmod(STDIN_FILENO, TTY_PERM) && with_fail)
+ fail("fchmod");
+ /* Also do the above for /dev/vcs[a][0-9]+ */
+#if defined(OWN_VCSA) || defined(OWN_VCS)
+ if (!ioctl(STDIN_FILENO, VT_GETSTATE, &vtstat)) {
+ int n = vtstat.v_active;
+ char _vcs[VCS_LEN + 6];
+ char _vcsa[VCSA_LEN + 6];
+
+ char *vcs = _vcs;
+ char *vcsa = _vcsa;
+ vcs += VCS_LEN + 6;
+ vcsa += VCSA_LEN + 6;
+
+ if (n) {
+ *--vcs = *--vcsa = 0;
+ while (n) {
+ *--vcs = *--vcsa = (char)((n % 10) + '0');
+ n /= 10;
+ }
+
+ vcs -= VCS_LEN;
+ vcsa -= VCSA_LEN;
+ strncpy(vcs, VCS, VCS_LEN);
+ strncpy(vcsa, VCSA, VCSA_LEN);
+
+#ifdef OWN_VCS
+ if (chown(vcs, owner, group) && with_fail) fail("chown");
+ if (chmod(vcs, TTY_PERM) && with_fail) fail("chmod");
+#endif
+#ifdef OWN_VCSA
+ if (chown(vcsa, owner, group) && with_fail) fail("chown");
+ if (chmod(vcsa, TTY_PERM) && with_fail) fail("chmod");
+#endif
+ }
+ }
+#endif
+}
diff --git a/src/security.h b/src/security.h
index d367dc7..3744c9c 100644
--- a/src/security.h
+++ b/src/security.h
@@ -1,7 +1,7 @@
/**
* cerberus – Minimal login program
*
- * Copyright © 2013, 2014, 2015, 2016, 2020 Mattias Andrée (maandree@kth.se)
+ * Copyright © 2013, 2014, 2015, 2016, 2020 Mattias Andrée (m@maandree.se)
*
* 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
@@ -40,4 +40,3 @@ void chown_tty(uid_t owner, gid_t group, char with_fail);
#endif
-