Add open/close session to sudo auth, only used by PAM.
This allows us to open (and close) the PAM session from sudoers.
This commit is contained in:
@@ -81,7 +81,7 @@ static int gotintr;
|
||||
#define PAM_DATA_SILENT 0
|
||||
#endif
|
||||
|
||||
static pam_handle_t *pamh; /* global due to pam_prep_user() */
|
||||
static pam_handle_t *pamh;
|
||||
|
||||
int
|
||||
pam_init(pw, promptp, auth)
|
||||
@@ -189,7 +189,7 @@ pam_cleanup(pw, auth)
|
||||
{
|
||||
int *pam_status = (int *) auth->data;
|
||||
|
||||
/* If successful, we can't close the session until pam_prep_user() */
|
||||
/* If successful, we can't close the session until pam_end_session() */
|
||||
if (auth->status == AUTH_SUCCESS)
|
||||
return(AUTH_SUCCESS);
|
||||
|
||||
@@ -198,10 +198,11 @@ pam_cleanup(pw, auth)
|
||||
}
|
||||
|
||||
int
|
||||
pam_prep_user(pw)
|
||||
pam_begin_session(pw, auth)
|
||||
struct passwd *pw;
|
||||
sudo_auth *auth;
|
||||
{
|
||||
int eval;
|
||||
int status;
|
||||
|
||||
if (pamh == NULL)
|
||||
pam_init(pw, NULL, NULL);
|
||||
@@ -229,17 +230,25 @@ pam_prep_user(pw)
|
||||
* can at least cause pam_limits to be run by opening and then
|
||||
* immediately closing the session.
|
||||
*/
|
||||
if ((eval = pam_open_session(pamh, 0)) != PAM_SUCCESS) {
|
||||
(void) pam_end(pamh, eval | PAM_DATA_SILENT);
|
||||
return(AUTH_FAILURE);
|
||||
}
|
||||
status = pam_open_session(pamh, 0);
|
||||
if (status != PAM_SUCCESS)
|
||||
(void) pam_end(pamh, PAM_SUCCESS | PAM_DATA_SILENT);
|
||||
#endif
|
||||
return(status == PAM_SUCCESS ? AUTH_SUCCESS : AUTH_FAILURE);
|
||||
}
|
||||
|
||||
int
|
||||
pam_end_session(auth)
|
||||
sudo_auth *auth;
|
||||
{
|
||||
int status;
|
||||
|
||||
#ifndef NO_PAM_SESSION
|
||||
(void) pam_close_session(pamh, 0);
|
||||
#endif
|
||||
|
||||
if (pam_end(pamh, PAM_SUCCESS | PAM_DATA_SILENT) == PAM_SUCCESS)
|
||||
return(AUTH_SUCCESS);
|
||||
else
|
||||
return(AUTH_FAILURE);
|
||||
status = pam_end(pamh, PAM_SUCCESS | PAM_DATA_SILENT);
|
||||
return(status == PAM_SUCCESS ? AUTH_SUCCESS : AUTH_FAILURE);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@@ -57,33 +57,37 @@ sudo_auth auth_switch[] = {
|
||||
AUTH_STANDALONE
|
||||
#else
|
||||
# ifndef WITHOUT_PASSWD
|
||||
AUTH_ENTRY(0, "passwd", passwd_init, NULL, passwd_verify, NULL)
|
||||
AUTH_ENTRY(0, "passwd", passwd_init, NULL, passwd_verify, NULL, NULL, NULL)
|
||||
# endif
|
||||
# if defined(HAVE_GETPRPWNAM) && !defined(WITHOUT_PASSWD)
|
||||
AUTH_ENTRY(0, "secureware", secureware_init, NULL, secureware_verify, NULL)
|
||||
AUTH_ENTRY(0, "secureware", secureware_init, NULL, secureware_verify, NULL, NULL, NULL)
|
||||
# endif
|
||||
# ifdef HAVE_AFS
|
||||
AUTH_ENTRY(0, "afs", NULL, NULL, afs_verify, NULL)
|
||||
AUTH_ENTRY(0, "afs", NULL, NULL, afs_verify, NULL, NULL, NULL)
|
||||
# endif
|
||||
# ifdef HAVE_DCE
|
||||
AUTH_ENTRY(0, "dce", NULL, NULL, dce_verify, NULL)
|
||||
AUTH_ENTRY(0, "dce", NULL, NULL, dce_verify, NULL, NULL, NULL)
|
||||
# endif
|
||||
# ifdef HAVE_KERB4
|
||||
AUTH_ENTRY(0, "kerb4", kerb4_init, NULL, kerb4_verify, NULL)
|
||||
AUTH_ENTRY(0, "kerb4", kerb4_init, NULL, kerb4_verify, NULL, NULL, NULL)
|
||||
# endif
|
||||
# ifdef HAVE_KERB5
|
||||
AUTH_ENTRY(0, "kerb5", kerb5_init, NULL, kerb5_verify, kerb5_cleanup)
|
||||
AUTH_ENTRY(0, "kerb5", kerb5_init, NULL, kerb5_verify, kerb5_cleanup, NULL, NULL)
|
||||
# endif
|
||||
# ifdef HAVE_SKEY
|
||||
AUTH_ENTRY(0, "S/Key", NULL, rfc1938_setup, rfc1938_verify, NULL)
|
||||
AUTH_ENTRY(0, "S/Key", NULL, rfc1938_setup, rfc1938_verify, NULL, NULL, NULL)
|
||||
# endif
|
||||
# ifdef HAVE_OPIE
|
||||
AUTH_ENTRY(0, "OPIE", NULL, rfc1938_setup, rfc1938_verify, NULL)
|
||||
AUTH_ENTRY(0, "OPIE", NULL, rfc1938_setup, rfc1938_verify, NULL, NULL, NULL)
|
||||
# endif
|
||||
#endif /* AUTH_STANDALONE */
|
||||
AUTH_ENTRY(0, NULL, NULL, NULL, NULL, NULL)
|
||||
AUTH_ENTRY(0, NULL, NULL, NULL, NULL, NULL, NULL, NULL)
|
||||
};
|
||||
|
||||
extern char **NewArgv; /* XXX - for auditing */
|
||||
|
||||
static void pass_warn(void);
|
||||
|
||||
int
|
||||
verify_user(struct passwd *pw, char *prompt)
|
||||
{
|
||||
@@ -93,7 +97,6 @@ verify_user(struct passwd *pw, char *prompt)
|
||||
char *p;
|
||||
sudo_auth *auth;
|
||||
sigaction_t sa, osa;
|
||||
extern char **NewArgv; /* XXX */
|
||||
|
||||
/* Enable suspend during password entry. */
|
||||
sigemptyset(&sa.sa_mask);
|
||||
@@ -181,9 +184,7 @@ verify_user(struct passwd *pw, char *prompt)
|
||||
if (p)
|
||||
zero_bytes(p, strlen(p));
|
||||
#endif
|
||||
/* XXX - need way to know if askpass was used */
|
||||
//if (!ISSET(tgetpass_flags, TGP_ASKPASS))
|
||||
pass_warn();
|
||||
pass_warn();
|
||||
}
|
||||
|
||||
cleanup:
|
||||
@@ -233,7 +234,40 @@ cleanup:
|
||||
return rval;
|
||||
}
|
||||
|
||||
void
|
||||
int begin_session(struct passwd *pw)
|
||||
{
|
||||
sudo_auth *auth;
|
||||
int status;
|
||||
|
||||
for (auth = auth_switch; auth->name; auth++) {
|
||||
if (auth->begin_session && IS_CONFIGURED(auth)) {
|
||||
status = (auth->begin_session)(pw, auth);
|
||||
if (status == AUTH_FATAL) { /* XXX log */
|
||||
audit_failure(NewArgv, "authentication failure");
|
||||
return -1; /* assume error msg already printed */
|
||||
}
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int end_session(void)
|
||||
{
|
||||
sudo_auth *auth;
|
||||
int status;
|
||||
|
||||
for (auth = auth_switch; auth->name; auth++) {
|
||||
if (auth->end_session && IS_CONFIGURED(auth)) {
|
||||
status = (auth->end_session)(auth);
|
||||
if (status == AUTH_FATAL) { /* XXX log */
|
||||
return -1; /* assume error msg already printed */
|
||||
}
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
pass_warn(void)
|
||||
{
|
||||
struct sudo_conv_message msg[2];
|
||||
|
@@ -32,6 +32,8 @@ typedef struct sudo_auth {
|
||||
int (*setup)(struct passwd *pw, char **prompt, struct sudo_auth *auth);
|
||||
int (*verify)(struct passwd *pw, char *p, struct sudo_auth *auth);
|
||||
int (*cleanup)(struct passwd *pw, struct sudo_auth *auth);
|
||||
int (*begin_session)(struct passwd *pw, struct sudo_auth *auth);
|
||||
int (*end_session)(struct sudo_auth *auth);
|
||||
} sudo_auth;
|
||||
|
||||
/* Values for sudo_auth.flags. */
|
||||
@@ -58,6 +60,8 @@ int fwtk_cleanup(struct passwd *pw, sudo_auth *auth);
|
||||
int pam_init(struct passwd *pw, char **prompt, sudo_auth *auth);
|
||||
int pam_verify(struct passwd *pw, char *prompt, sudo_auth *auth);
|
||||
int pam_cleanup(struct passwd *pw, sudo_auth *auth);
|
||||
int pam_begin_session(struct passwd *pw, sudo_auth *auth);
|
||||
int pam_end_session(sudo_auth *auth);
|
||||
int sia_setup(struct passwd *pw, char **prompt, sudo_auth *auth);
|
||||
int sia_verify(struct passwd *pw, char *prompt, sudo_auth *auth);
|
||||
int sia_cleanup(struct passwd *pw, sudo_auth *auth);
|
||||
@@ -86,34 +90,34 @@ int securid_setup(struct passwd *pw, char **prompt, sudo_auth *auth);
|
||||
int securid_verify(struct passwd *pw, char *pass, sudo_auth *auth);
|
||||
|
||||
/* Fields: need_root, name, init, setup, verify, cleanup */
|
||||
#define AUTH_ENTRY(r, n, i, s, v, c) \
|
||||
{ (r|FLAG_CONFIGURED), AUTH_FAILURE, n, NULL, i, s, v, c },
|
||||
#define AUTH_ENTRY(r, n, i, s, v, c, b, e) \
|
||||
{ (r|FLAG_CONFIGURED), AUTH_FAILURE, n, NULL, i, s, v, c , b, e },
|
||||
|
||||
/* Some methods cannots (or should not) interoperate with any others */
|
||||
/* Some methods cannot (or should not) interoperate with any others */
|
||||
#if defined(HAVE_PAM)
|
||||
# define AUTH_STANDALONE \
|
||||
AUTH_ENTRY(0, "pam", \
|
||||
pam_init, NULL, pam_verify, pam_cleanup)
|
||||
pam_init, NULL, pam_verify, pam_cleanup, pam_begin_session, pam_end_session)
|
||||
#elif defined(HAVE_SECURID)
|
||||
# define AUTH_STANDALONE \
|
||||
AUTH_ENTRY(0, "SecurId", \
|
||||
securid_init, securid_setup, securid_verify, NULL)
|
||||
securid_init, securid_setup, securid_verify, NULL, NULL, NULL)
|
||||
#elif defined(HAVE_SIA_SES_INIT)
|
||||
# define AUTH_STANDALONE \
|
||||
AUTH_ENTRY(0, "sia", \
|
||||
NULL, sia_setup, sia_verify, sia_cleanup)
|
||||
NULL, sia_setup, sia_verify, sia_cleanup, NULL, NULL)
|
||||
#elif defined(HAVE_AIXAUTH)
|
||||
# define AUTH_STANDALONE \
|
||||
AUTH_ENTRY(0, "aixauth", \
|
||||
NULL, NULL, aixauth_verify, aixauth_cleanup)
|
||||
NULL, NULL, aixauth_verify, aixauth_cleanup, NULL, NULL)
|
||||
#elif defined(HAVE_FWTK)
|
||||
# define AUTH_STANDALONE \
|
||||
AUTH_ENTRY(0, "fwtk", \
|
||||
fwtk_init, NULL, fwtk_verify, fwtk_cleanup)
|
||||
fwtk_init, NULL, fwtk_verify, fwtk_cleanup, NULL, NULL)
|
||||
#elif defined(HAVE_BSD_AUTH_H)
|
||||
# define AUTH_STANDALONE \
|
||||
AUTH_ENTRY(0, "bsdauth", \
|
||||
bsdauth_init, NULL, bsdauth_verify, bsdauth_cleanup)
|
||||
bsdauth_init, NULL, bsdauth_verify, bsdauth_cleanup, NULL, NULL)
|
||||
#endif
|
||||
|
||||
#endif /* SUDO_AUTH_H */
|
||||
|
@@ -60,9 +60,6 @@
|
||||
/*
|
||||
* Prototypes
|
||||
*/
|
||||
#if 0
|
||||
static void runas_setup(void);
|
||||
#endif
|
||||
static void runas_setgroups(void);
|
||||
|
||||
/*
|
||||
@@ -969,51 +966,3 @@ runas_setgroups()
|
||||
}
|
||||
|
||||
#endif /* HAVE_INITGROUPS */
|
||||
|
||||
#if 0
|
||||
static void
|
||||
runas_setup()
|
||||
{
|
||||
gid_t gid;
|
||||
#ifdef HAVE_LOGIN_CAP_H
|
||||
int flags;
|
||||
extern login_cap_t *lc;
|
||||
#endif
|
||||
|
||||
if (runas_pw->pw_name != NULL) {
|
||||
gid = runas_gr ? runas_gr->gr_gid : runas_pw->pw_gid;
|
||||
#ifdef HAVE_GETUSERATTR
|
||||
aix_setlimits(runas_pw->pw_name);
|
||||
#endif
|
||||
#ifdef HAVE_PAM
|
||||
/* XXX - move this */
|
||||
pam_prep_user(runas_pw);
|
||||
#endif /* HAVE_PAM */
|
||||
|
||||
#ifdef HAVE_LOGIN_CAP_H
|
||||
if (def_use_loginclass) {
|
||||
/*
|
||||
* We only use setusercontext() to set the nice value and rlimits.
|
||||
*/
|
||||
flags = LOGIN_SETRESOURCES|LOGIN_SETPRIORITY;
|
||||
if (setusercontext(lc, runas_pw, runas_pw->pw_uid, flags)) {
|
||||
if (runas_pw->pw_uid != ROOT_UID)
|
||||
error(1, "unable to set user context");
|
||||
else
|
||||
warning("unable to set user context");
|
||||
}
|
||||
}
|
||||
#endif /* HAVE_LOGIN_CAP_H */
|
||||
/*
|
||||
* Initialize group vector
|
||||
*/
|
||||
runas_setgroups();
|
||||
#ifdef HAVE_SETEUID
|
||||
if (setegid(gid))
|
||||
warning("cannot set egid to runas gid");
|
||||
#endif
|
||||
if (setgid(gid))
|
||||
warning("cannot set gid to runas gid");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@@ -276,6 +276,7 @@ sudoers_policy_close(int exit_status, int error_code)
|
||||
/* We do not currently log the exit status. */
|
||||
if (error_code)
|
||||
warningx("unable to execute %s: %s", safe_cmnd, strerror(error_code));
|
||||
end_session();
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -627,6 +628,15 @@ sudoers_policy_main(int argc, char * const argv[], int pwflag, char *env_add[],
|
||||
|
||||
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:
|
||||
return rval;
|
||||
}
|
||||
|
@@ -210,7 +210,8 @@ int user_is_exempt(void);
|
||||
|
||||
/* sudo_auth.c */
|
||||
int verify_user(struct passwd *, char *);
|
||||
void pass_warn(void);
|
||||
int begin_session(struct passwd *);
|
||||
int end_session();
|
||||
|
||||
#ifdef HAVE_LDAP
|
||||
/* ldap.c */
|
||||
|
Reference in New Issue
Block a user