[sudo-workers] PAM and return of init_session ignored ?
aurel
aurel at aurel-r.fr
Mon Aug 10 10:26:47 MDT 2015
Hi,
I'm developing a PAM module for/auth/ and/session/. When my module return PAM_AUTH_ERR
to sudoers, the command is not executed. But when the/session/ return PAM_SESSION_ERR,
the command is executed anyway. Why ?
However, in source code (sudo-1.8.10p3), a session error causes EXIT_FAILURE in parent before forking.
But the macro AUTH_FAILURE and AUTH_FATALdo not have the same value (see the comments) :
(sudo/plugins/sudoers/auth/pam.c)
|sudo_pam_begin_session(struct passwd *pw, char **user_envp[], sudo_auth *auth)||
||{||
|| ...||
|| if (def_pam_session) {
*pam_status = pam_open_session(pamh, 0);
if (*pam_status != PAM_SUCCESS) { /* PAM_SUCCESS = 0 */
(void) pam_end(pamh, *pam_status | PAM_DATA_SILENT);
pamh = NULL;
status = AUTH_FAILURE; /* AUTH_FAILURE = 1 */
goto done;
}
}
...
done:
|| debug_return_int(status);|| /* return 1 */
||}|
called by
(sudo/plugins/sudoers/auth/sudo_auth.c)
|static sudo_auth auth_switch[] = {||
||/* Standalone entries first */||
||#ifdef HAVE_PAM||
|| AUTH_ENTRY("pam", FLAG_STANDALONE, sudo_pam_init, NULL, sudo_pam_verify, sudo_pam_cleanup, sudo_pam_begin_session, sudo_pam_end_session)||
||#endif||
|| ...||
||}||
|...
|int sudo_auth_begin_session(struct passwd *pw, char **user_env[])||
||{||
|| sudo_auth *auth;||
|| int status = AUTH_SUCCESS;||
|| debug_decl(sudo_auth_begin_session, SUDO_DEBUG_AUTH)||
||
|| for (auth = auth_switch; auth->name; auth++) {||
|| if (auth->begin_session && !IS_DISABLED(auth)) {||
|| status = (auth->begin_session)(pw, user_env, auth); /* call|||||sudo_pam_begin_session| */
|| if (status == AUTH_FATAL) /* AUTH_FATAL = 3 ???!!! if|||sudo_pam_begin_session return error (1) status = 1|*/||
|| break; /* assume error msg already printed */||
|| }||
|| }||
|| debug_return_int(status == AUTH_FATAL ? -1 : 1); /* So always return 1 ?! */||
||}||
|
called by
(sudo/plugins/sudoers/policy.c)
|static int||
||sudoers_policy_init_session(struct passwd *pwd, char **user_env[])||
||{||
|| debug_decl(sudoers_policy_init_session, SUDO_DEBUG_PLUGIN)||
||
|| /* user_env is only specified for API version 1.2 and higher. */||
|| if (sudo_version < SUDO_API_MKVERSION(1, 2))||
|| user_env = NULL;||
||
|| if (fatal_setjmp() != 0) {||
|| /* called via fatal(), fatalx() or log_fatal() */||
|| fatal_disable_setjmp();||
|| debug_return_bool(-1);||
|| }||
||
|| debug_return_bool(sudo_auth_begin_session(pwd, user_env));||
||}|
|...||
||
||__dso_public struct policy_plugin sudoers_policy = {||
|| SUDO_POLICY_PLUGIN,||
|| SUDO_API_VERSION,||
|| sudoers_policy_open,||
|| sudoers_policy_close,||
|| sudoers_policy_version,||
|| sudoers_policy_check,||
|| sudoers_policy_list,||
|| sudoers_policy_validate,||
|| sudoers_policy_invalidate,||
|| sudoers_policy_init_session, /* (*init_session)|| */
|| sudoers_policy_register_hooks||
||};|
called by
(sudo/src/sudo.c)
|int||
||policy_init_session(struct command_details *details)||
||{||
|| int rval = true;||
|| debug_decl(policy_init_session, SUDO_DEBUG_PCOMM)||
||
|| if (policy_plugin.u.policy->init_session) {||
|| /*||
|| * Backwards compatibility for older API versions||
|| */||
|| switch (policy_plugin.u.generic->version) {||
|| case SUDO_API_MKVERSION(1, 0):||
|| case SUDO_API_MKVERSION(1, 1):||
|| rval = policy_plugin.u.policy_1_0->init_session(details->pw);||
|| break;||
|| default:||
|| rval = policy_plugin.u.policy->init_session(details->pw,||
|| &details->envp);||
|| }||
|| }||
|| debug_return_bool(rval);||
||}||
||
||
|and finally
(sudo/src/exec.c)
|static int fork_cmnd(struct command_details *details, int sv[2])||
||{||
|| ...||
|| ||if (policy_init_session(details) != true)||
|| fatalx(U_("policy plugin failed session initialization"));|||||/* exit(EXIT_FAILURE); OR siglongjmp(fatal_jmp, 1); ... but return is always true */|
|| ||
|| cmnd_pid = sudo_debug_fork();||
|| switch (cmnd_pid) {||
|| case -1:||
|| fatal(U_("unable to fork"));||
|| break;||
|| case 0:||
|| /* child */||
|| close(sv[0]);||
|| close(signal_pipe[0]);||
|| close(signal_pipe[1]);||
|| fcntl(sv[1], F_SETFD, FD_CLOEXEC);||
|| exec_cmnd(details, &cstat, sv[1]);||
|| send(sv[1], &cstat, sizeof(cstat), 0);||
|| sudo_debug_exit_int(__func__, __FILE__, __LINE__, sudo_debug_subsys, 1);||
|| _exit(1);||
|| }||
|| sudo_debug_printf(SUDO_DEBUG_INFO, "executed %s, pid %d", details->command,||
|| (int)cmnd_pid);||
|| debug_return_int(cmnd_pid);||
||}||
|
I have not tried it with gdb yet...
To reproduce : (/etc/pam.d/sudo)
@include common-auth
@include common-account
session required pam_deny.so
@include common-session-noninteractive
If it's normal, why ? And how can I stop sudo to not run the command when/session/ return PAM_SESSION_ERR ?
Thanks and sorry for my bad english.
More information about the sudo-workers
mailing list