int main (int argc, char **argv) { pam_handle_t *pamh = NULL; struct passwd *pw; const char *auth; int status; int flags; int res; if (isatty (0)) errx (2, "this command is not meant to be run from the console"); if (argc != 3) errx (2, "invalid arguments to cockpit-session"); /* When setuid root, make sure our group is also root */ if (geteuid () == 0) { /* Never trust the environment when running setuid() */ if (getuid() != 0) { if (clearenv () != 0) err (1, "couldn't clear environment"); /* set a minimal environment */ setenv ("PATH", "/usr/sbin:/usr/bin:/sbin:/bin", 1); } if (setgid (0) != 0 || setuid (0) != 0) err (1, "couldn't switch permissions correctly"); } /* We should never leak our auth fd to other processes */ flags = fcntl (AUTH_FD, F_GETFD); if (flags < 0 || fcntl (AUTH_FD, F_SETFD, flags | FD_CLOEXEC)) err (1, "couldn't set auth fd flags"); auth = argv[1]; rhost = argv[2]; signal (SIGALRM, SIG_DFL); signal (SIGQUIT, SIG_DFL); signal (SIGTSTP, SIG_IGN); signal (SIGHUP, SIG_IGN); signal (SIGPIPE, SIG_IGN); snprintf (line, UT_LINESIZE, "cockpit-%d", getpid ()); line[UT_LINESIZE] = '\0'; if (strcmp (auth, "basic") == 0) pamh = perform_basic (); else if (strcmp (auth, "negotiate") == 0) pamh = perform_gssapi (); else errx (2, "unrecognized authentication method: %s", auth); if (want_session) { /* Let the G_MESSAGES_DEBUG leak through from parent as a default */ transfer_pam_env (pamh, "G_DEBUG", "G_MESSAGES_DEBUG", NULL); env = pam_getenvlist (pamh); if (env == NULL) errx (EX, "get pam environment failed"); pw = getpwnam (user); if (pw == NULL) errx (EX, "%s: invalid user", user); if (initgroups (user, pw->pw_gid) < 0) err (EX, "%s: can't init groups", user); signal (SIGTERM, pass_to_child); signal (SIGINT, pass_to_child); signal (SIGQUIT, pass_to_child); utmp_log (1); status = fork_session (pw, session); utmp_log (0); signal (SIGTERM, SIG_DFL); signal (SIGINT, SIG_DFL); signal (SIGQUIT, SIG_DFL); res = pam_setcred (pamh, PAM_DELETE_CRED); if (res != PAM_SUCCESS) err (EX, "%s: couldn't delete creds: %s", user, pam_strerror (pamh, res)); res = pam_close_session (pamh, 0); if (res != PAM_SUCCESS) err (EX, "%s: couldn't close session: %s", user, pam_strerror (pamh, res)); } else { status = session (); } pam_end (pamh, PAM_SUCCESS); if (WIFEXITED(status)) exit (WEXITSTATUS(status)); else if (WIFSIGNALED(status)) raise (WTERMSIG(status)); else exit (127); }
int main (int argc, char **argv) { pam_handle_t *pamh = NULL; const char *auth; char **env; int status; int flags; int res; int i; if (isatty (0)) errx (2, "this command is not meant to be run from the console"); if (argc != 3) errx (2, "invalid arguments to cockpit-session"); save_environment (); /* When setuid root, make sure our group is also root */ if (geteuid () == 0) { /* Never trust the environment when running setuid() */ if (getuid() != 0) { if (clearenv () != 0) err (1, "couldn't clear environment"); } /* set a minimal environment */ setenv ("PATH", "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", 1); if (setgid (0) != 0 || setuid (0) != 0) err (1, "couldn't switch permissions correctly"); } /* We should never leak our auth fd to other processes */ flags = fcntl (AUTH_FD, F_GETFD); if (flags < 0 || fcntl (AUTH_FD, F_SETFD, flags | FD_CLOEXEC)) err (1, "couldn't set auth fd flags"); auth = argv[1]; rhost = argv[2]; signal (SIGALRM, SIG_DFL); signal (SIGQUIT, SIG_DFL); signal (SIGTSTP, SIG_IGN); signal (SIGHUP, SIG_IGN); signal (SIGPIPE, SIG_IGN); /* Switch namespaces if we've been requested to do so */ maybe_nsenter (); if (strcmp (auth, "basic") == 0) pamh = perform_basic (); else if (strcmp (auth, "negotiate") == 0) pamh = perform_gssapi (); else errx (2, "unrecognized authentication method: %s", auth); for (i = 0; env_saved[i] != NULL; i++) pam_putenv (pamh, env_saved[i]); env = pam_getenvlist (pamh); if (env == NULL) errx (EX, "get pam environment failed"); if (want_session) { assert (pwd != NULL); if (initgroups (pwd->pw_name, pwd->pw_gid) < 0) err (EX, "%s: can't init groups", pwd->pw_name); signal (SIGTERM, pass_to_child); signal (SIGINT, pass_to_child); signal (SIGQUIT, pass_to_child); utmp_log (1); status = fork_session (env); utmp_log (0); signal (SIGTERM, SIG_DFL); signal (SIGINT, SIG_DFL); signal (SIGQUIT, SIG_DFL); res = pam_setcred (pamh, PAM_DELETE_CRED); if (res != PAM_SUCCESS) err (EX, "%s: couldn't delete creds: %s", pwd->pw_name, pam_strerror (pamh, res)); res = pam_close_session (pamh, 0); if (res != PAM_SUCCESS) err (EX, "%s: couldn't close session: %s", pwd->pw_name, pam_strerror (pamh, res)); } else { status = session (env); } pam_end (pamh, PAM_SUCCESS); if (WIFEXITED(status)) exit (WEXITSTATUS(status)); else if (WIFSIGNALED(status)) raise (WTERMSIG(status)); else exit (127); }