Add init_session function to struct policy_plugin that gets called
before the uid/gid/etc changes. A struct passwd pointer is passed in,which may be NULL if the user does not exist in the passwd database.The sudoers module uses init_session to open the pam session as needed.
This commit is contained in:
@@ -52,6 +52,7 @@ typedef int (*sudo_conv_t)(int num_msgs, const struct sudo_conv_message msgs[],
|
|||||||
typedef int (*sudo_printf_t)(int msg_type, const char *fmt, ...);
|
typedef int (*sudo_printf_t)(int msg_type, const char *fmt, ...);
|
||||||
|
|
||||||
/* Policy plugin type and defines */
|
/* Policy plugin type and defines */
|
||||||
|
struct passwd;
|
||||||
struct policy_plugin {
|
struct policy_plugin {
|
||||||
#define SUDO_POLICY_PLUGIN 1
|
#define SUDO_POLICY_PLUGIN 1
|
||||||
unsigned int type; /* always SUDO_POLICY_PLUGIN */
|
unsigned int type; /* always SUDO_POLICY_PLUGIN */
|
||||||
@@ -68,6 +69,7 @@ struct policy_plugin {
|
|||||||
const char *list_user);
|
const char *list_user);
|
||||||
int (*validate)(void);
|
int (*validate)(void);
|
||||||
void (*invalidate)(int remove);
|
void (*invalidate)(int remove);
|
||||||
|
int (*init_session)(struct passwd *pwd);
|
||||||
};
|
};
|
||||||
|
|
||||||
/* I/O plugin type and defines */
|
/* I/O plugin type and defines */
|
||||||
|
@@ -202,8 +202,22 @@ pam_begin_session(pw, auth)
|
|||||||
struct passwd *pw;
|
struct passwd *pw;
|
||||||
sudo_auth *auth;
|
sudo_auth *auth;
|
||||||
{
|
{
|
||||||
int status;
|
int status = PAM_SUCCESS;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If there is no valid user we cannot open a PAM session.
|
||||||
|
* This is not an error as sudo can run commands with arbitrary
|
||||||
|
* uids, it just means we are done from a session management standpoint.
|
||||||
|
*/
|
||||||
|
if (pw == NULL) {
|
||||||
|
if (pamh != NULL) {
|
||||||
|
(void) pam_end(pamh, PAM_SUCCESS | PAM_DATA_SILENT);
|
||||||
|
pamh = NULL;
|
||||||
|
}
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If the user did not have to authenticate there is no pam handle yet. */
|
||||||
if (pamh == NULL)
|
if (pamh == NULL)
|
||||||
pam_init(pw, NULL, NULL);
|
pam_init(pw, NULL, NULL);
|
||||||
|
|
||||||
@@ -224,16 +238,14 @@ pam_begin_session(pw, auth)
|
|||||||
(void) pam_setcred(pamh, PAM_ESTABLISH_CRED);
|
(void) pam_setcred(pamh, PAM_ESTABLISH_CRED);
|
||||||
|
|
||||||
#ifndef NO_PAM_SESSION
|
#ifndef NO_PAM_SESSION
|
||||||
/*
|
|
||||||
* To fully utilize PAM sessions we would need to keep a
|
|
||||||
* sudo process around until the command exits. However, we
|
|
||||||
* can at least cause pam_limits to be run by opening and then
|
|
||||||
* immediately closing the session.
|
|
||||||
*/
|
|
||||||
status = pam_open_session(pamh, 0);
|
status = pam_open_session(pamh, 0);
|
||||||
if (status != PAM_SUCCESS)
|
if (status != PAM_SUCCESS) {
|
||||||
(void) pam_end(pamh, PAM_SUCCESS | PAM_DATA_SILENT);
|
(void) pam_end(pamh, PAM_SUCCESS | PAM_DATA_SILENT);
|
||||||
|
pamh = NULL;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
done:
|
||||||
return(status == PAM_SUCCESS ? AUTH_SUCCESS : AUTH_FAILURE);
|
return(status == PAM_SUCCESS ? AUTH_SUCCESS : AUTH_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -241,13 +253,14 @@ int
|
|||||||
pam_end_session(auth)
|
pam_end_session(auth)
|
||||||
sudo_auth *auth;
|
sudo_auth *auth;
|
||||||
{
|
{
|
||||||
int status;
|
int status = PAM_SUCCESS;
|
||||||
|
|
||||||
|
if (pamh) {
|
||||||
#ifndef NO_PAM_SESSION
|
#ifndef NO_PAM_SESSION
|
||||||
(void) pam_close_session(pamh, 0);
|
(void) pam_close_session(pamh, PAM_SILENT);
|
||||||
#endif
|
#endif
|
||||||
|
status = pam_end(pamh, PAM_SUCCESS | PAM_DATA_SILENT);
|
||||||
status = pam_end(pamh, PAM_SUCCESS | PAM_DATA_SILENT);
|
}
|
||||||
return(status == PAM_SUCCESS ? AUTH_SUCCESS : AUTH_FAILURE);
|
return(status == PAM_SUCCESS ? AUTH_SUCCESS : AUTH_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -234,7 +234,7 @@ cleanup:
|
|||||||
return rval;
|
return rval;
|
||||||
}
|
}
|
||||||
|
|
||||||
int begin_session(struct passwd *pw)
|
int auth_begin_session(struct passwd *pw)
|
||||||
{
|
{
|
||||||
sudo_auth *auth;
|
sudo_auth *auth;
|
||||||
int status;
|
int status;
|
||||||
@@ -251,7 +251,7 @@ int begin_session(struct passwd *pw)
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
int end_session(void)
|
int auth_end_session(void)
|
||||||
{
|
{
|
||||||
sudo_auth *auth;
|
sudo_auth *auth;
|
||||||
int status;
|
int status;
|
||||||
|
@@ -276,7 +276,20 @@ sudoers_policy_close(int exit_status, int error_code)
|
|||||||
/* We do not currently log the exit status. */
|
/* We do not currently log the exit status. */
|
||||||
if (error_code)
|
if (error_code)
|
||||||
warningx("unable to execute %s: %s", safe_cmnd, strerror(error_code));
|
warningx("unable to execute %s: %s", safe_cmnd, strerror(error_code));
|
||||||
end_session();
|
|
||||||
|
/* Close the session we opened in sudoers_policy_init_session(). */
|
||||||
|
if (ISSET(sudo_mode, MODE_RUN|MODE_EDIT))
|
||||||
|
(void)auth_end_session();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The init_session function is called before executing the command
|
||||||
|
* and before uid/gid changes occur.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
sudoers_policy_init_session(struct passwd *pwd)
|
||||||
|
{
|
||||||
|
return auth_begin_session(pwd);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@@ -628,15 +641,6 @@ sudoers_policy_main(int argc, char * const argv[], int pwflag, char *env_add[],
|
|||||||
|
|
||||||
restore_perms();
|
restore_perms();
|
||||||
|
|
||||||
/*
|
|
||||||
* Ideally we would like to do session setup (currently only PAM)
|
|
||||||
* from inside sudo itself, but this should be close enough.
|
|
||||||
*/
|
|
||||||
if (ISSET(sudo_mode, MODE_RUN))
|
|
||||||
rval = begin_session(runas_pw);
|
|
||||||
if (ISSET(sudo_mode, MODE_EDIT))
|
|
||||||
rval = begin_session(sudo_user.pw);
|
|
||||||
|
|
||||||
done:
|
done:
|
||||||
return rval;
|
return rval;
|
||||||
}
|
}
|
||||||
@@ -1438,7 +1442,8 @@ struct policy_plugin sudoers_policy = {
|
|||||||
sudoers_policy_check,
|
sudoers_policy_check,
|
||||||
sudoers_policy_list,
|
sudoers_policy_list,
|
||||||
sudoers_policy_validate,
|
sudoers_policy_validate,
|
||||||
sudoers_policy_invalidate
|
sudoers_policy_invalidate,
|
||||||
|
sudoers_policy_init_session
|
||||||
};
|
};
|
||||||
|
|
||||||
struct io_plugin sudoers_io = {
|
struct io_plugin sudoers_io = {
|
||||||
|
@@ -210,8 +210,8 @@ int user_is_exempt(void);
|
|||||||
|
|
||||||
/* sudo_auth.c */
|
/* sudo_auth.c */
|
||||||
int verify_user(struct passwd *, char *);
|
int verify_user(struct passwd *, char *);
|
||||||
int begin_session(struct passwd *);
|
int auth_begin_session(struct passwd *);
|
||||||
int end_session();
|
int auth_end_session();
|
||||||
|
|
||||||
#ifdef HAVE_LDAP
|
#ifdef HAVE_LDAP
|
||||||
/* ldap.c */
|
/* ldap.c */
|
||||||
|
@@ -639,7 +639,7 @@ script_execve(struct command_details *details, char *argv[], char *envp[],
|
|||||||
close(sv[0]);
|
close(sv[0]);
|
||||||
fcntl(sv[1], F_SETFD, FD_CLOEXEC);
|
fcntl(sv[1], F_SETFD, FD_CLOEXEC);
|
||||||
/* XXX - defer call to exec_setup() until my_execve()? */
|
/* XXX - defer call to exec_setup() until my_execve()? */
|
||||||
if (exec_setup(details) == 0) {
|
if (exec_setup(details) == TRUE) {
|
||||||
/* headed for execve() */
|
/* headed for execve() */
|
||||||
if (log_io) {
|
if (log_io) {
|
||||||
/* Close the other end of the stdin/stdout/stderr pipes. */
|
/* Close the other end of the stdin/stdout/stderr pipes. */
|
||||||
|
31
src/sudo.c
31
src/sudo.c
@@ -651,13 +651,23 @@ cleanup(int gotsignal)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Setup the execution environment immediately prior to the call to execve()
|
* Setup the execution environment immediately prior to the call to execve()
|
||||||
|
* Returns TRUE on success and FALSE on failure.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
exec_setup(struct command_details *details)
|
exec_setup(struct command_details *details)
|
||||||
{
|
{
|
||||||
|
int rval = FALSE;
|
||||||
struct passwd *pw;
|
struct passwd *pw;
|
||||||
|
|
||||||
pw = getpwuid(details->euid);
|
pw = getpwuid(details->euid);
|
||||||
|
|
||||||
|
/* Call policy plugin's session init before other setup occurs. */
|
||||||
|
if (policy_plugin.u.policy->init_session) {
|
||||||
|
/* The session init code is expected to print an error as needed. */
|
||||||
|
if (policy_plugin.u.policy->init_session(pw) != TRUE)
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
if (pw != NULL) {
|
if (pw != NULL) {
|
||||||
#ifdef HAVE_GETUSERATTR
|
#ifdef HAVE_GETUSERATTR
|
||||||
aix_setlimits(pw->pw_name);
|
aix_setlimits(pw->pw_name);
|
||||||
@@ -732,15 +742,7 @@ exec_setup(struct command_details *details)
|
|||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (details->cwd) {
|
|
||||||
/* cwd is relative to the new root, if any */
|
|
||||||
if (chdir(details->cwd) != 0) {
|
|
||||||
warning("unable to change directory to %s", details->cwd);
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Must set uids last */
|
|
||||||
#ifdef HAVE_SETRESUID
|
#ifdef HAVE_SETRESUID
|
||||||
if (setresuid(details->uid, details->euid, details->euid) != 0) {
|
if (setresuid(details->uid, details->euid, details->euid) != 0) {
|
||||||
warning("unable to change to runas uid");
|
warning("unable to change to runas uid");
|
||||||
@@ -758,10 +760,19 @@ exec_setup(struct command_details *details)
|
|||||||
}
|
}
|
||||||
#endif /* !HAVE_SETRESUID && !HAVE_SETREUID */
|
#endif /* !HAVE_SETRESUID && !HAVE_SETREUID */
|
||||||
|
|
||||||
errno = 0;
|
/* Set cwd after uid to avoid permissions problems. */
|
||||||
|
if (details->cwd) {
|
||||||
|
/* Note: cwd is relative to the new root, if any. */
|
||||||
|
if (chdir(details->cwd) != 0) {
|
||||||
|
warning("unable to change directory to %s", details->cwd);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rval = TRUE;
|
||||||
|
|
||||||
done:
|
done:
|
||||||
return errno;
|
return rval;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
Reference in New Issue
Block a user