aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile5
-rw-r--r--src/cerberus.c85
-rw-r--r--src/cerberus.h2
3 files changed, 83 insertions, 9 deletions
diff --git a/Makefile b/Makefile
index 4e29083..6e73c52 100644
--- a/Makefile
+++ b/Makefile
@@ -16,7 +16,8 @@ _SS = $(SBIN)
TTY_GROUP = tty
DEFAULT_HOME = /
-DEFAULT_SHELL = $(BIN)/sh
+DEFAULT_SH = sh
+DEFAULT_SHELL = $(BIN)/$(DEFAULT_SH)
DEFAULT_TERM = dumb
VCS = $(DEV)/vcs
VCSA = $(DEV)/vcsa
@@ -28,7 +29,7 @@ VCS_LEN = $(shell vcs="$(VCS)" ; echo "$${$(H)vcs}")
VCSA_LEN = $(shell vcsa="$(VCSA)" ; echo "$${$(H)vcsa}")
VCS_VCSA_LEN = $(shell (echo $(VCS_LEN) ; echo $(VCSA_LEN)) | sort -n | tail -n 1)
-STR_DEFS = TTY_GROUP DEFAULT_HOME DEFAULT_SHELL DEFAULT_TERM PATH PATH_ROOT VCS VCSA
+STR_DEFS = TTY_GROUP DEFAULT_HOME DEFAULT_SH DEFAULT_SHELL DEFAULT_TERM PATH PATH_ROOT VCS VCSA
INT_DEFS = VCS_LEN VCSA_LEN VCS_VCSA_LEN
STR_CPPFLAGS = $(foreach D, $(STR_DEFS), -D'$(D)="$($(D))"')
diff --git a/src/cerberus.c b/src/cerberus.c
index f60f64c..3a5dd5d 100644
--- a/src/cerberus.c
+++ b/src/cerberus.c
@@ -36,7 +36,7 @@ int main(int argc, char** argv)
char preserve_env = 0;
char skip_auth = 0;
#ifdef USE_TTY_GROUP
- gid_t tty_group = 0;
+ static gid_t tty_group = 0;
struct group* group;
#endif
struct passwd* entry;
@@ -179,17 +179,88 @@ int main(int argc, char** argv)
reenable_echo();
- /* Login */
+ /* Partial login */
/* TODO verify that user is enabled */
- set_user(entry);
- /* TODO set supplemental groups */
+ chown_tty(entry->pw_uid, tty_group, 0);
chdir_home(entry);
ensure_shell(entry);
set_environ(entry, preserve_env);
-
- /* Reset terminal ownership and mode */
- chown_tty(0, tty_group, 0);
+ {
+ pid_t pid = fork();
+ /* vfork cannot be used as the child changes the user,
+ the parent would not be able to chown the TTY */
+
+ if (pid == -1)
+ {
+ perror("fork");
+ return 1;
+ }
+ else if (pid == 0)
+ {
+ int child_argc = 0;
+ char** child_argv = malloc(5 * sizeof(char*));
+ int n = 0;
+ char* sh = entry->pw_shell;
+ char* login_sh;
+
+ /* Partial login */
+ /* TODO set supplemental groups */
+ set_user(entry);
+
+ 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++) = DEFAULT_SHELL;
+ *(child_argv + child_argc++) = "-" DEFAULT_SH;
+ *(child_argv + child_argc++) = "-c";
+ *(child_argv + child_argc++) = login_sh - 5;
+ }
+ else
+ {
+ int i;
+ for (i = 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);
+ }
+ else
+ {
+ int _status;
+ waitpid(pid, &_status, 0);
+
+ /* Reset terminal ownership and mode */
+ chown_tty(0, tty_group, 0);
+ }
+ }
return 0;
}
diff --git a/src/cerberus.h b/src/cerberus.h
index a4ba19a..b5501a4 100644
--- a/src/cerberus.h
+++ b/src/cerberus.h
@@ -24,8 +24,10 @@
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
+#include <string.h>
#include <pwd.h>
#include <errno.h>
+#include <sys/wait.h>
#ifdef USE_TTY_GROUP
#include <grp.h>
#endif