Nye Liu
2006-Apr-27 04:13 UTC
bug in OpenSSH_4.3p2: pam_open_session() called but not close for root users
For root sessions pam_open_session is called, but not pam_close_session. sshd behavior is broken for root logins because if pam session is run from the child, close is never called due to exec: on open since use_privsep is not set, parent calls do_exec_pty(), which does not open session. then, it skips calling do_setusercontext(), so it does not open session. child calls do_setusercontext(), which opens session. on close child will not close sesion, because it exec'd the shell, and the sshd task is gone! parent will not close session, since session was not opened by parent, sshpam_session_open is not set. as root: parent process pid 205: do_exec_pty() uid 0 child process pid 208: do_setusercontext() uid 0 pid 208: radius pam open session (exec shell) parent process pid 208: radius pam close session (skipped!) BROKEN! but it does work for user logins because: on open parent does not call do_exec_pty since use_privsep is set. parent then drops privs via setusercontext, which opens session and sets sshpam_session_open. child calls setusercontext, but that does not open session because uid!=0 on close child will not close session, because it exec'd the shell, and the sshd task is gone. parent will close session, since session was opened by parent, and the sshpam_session_open flag is set. as nonroot: parent process pid 223: do_setusercontext() uid 0 pid 223: radius pam open session child process pid 224: do_setusercontext() uid 104 (exec shell) parent process pid 223: radius pam close session WORKS! One solution is to open session from do_exec_pty() and to NOT reopen session in if sshpam_session_open is set, so that in the case of the user, both the parent AND the child do not open session. Has drawback that open session is being called by parent, not child. root: parent process pid 205: do_exec_pty() uid 0 pid 205: radius pam open session child process pid 208: do_setusercontext() uid 0 pid 208: radius pam open session (skipped!) (exec shell) parent process pid 205: radius pam close session OK! another solution: "fake" set sshpam_session_open. has drawback that if child failed to open session, you'll get a close when the parent exists, but no open. root: parent process pid 205: do_exec_pty() uid 0 pid 205: set sshpam_session_open=1 child process pid 208: do_setusercontext() uid 0 pid 208: radius pam open session (exec shell) parent process pid 205: radius pam close session OK! see also http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=132681 and http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=150968 possible patch for first solution: Index: session.c ==================================================================--- session.c (revision 15) +++ session.c (working copy) @@ -394,8 +394,10 @@ session_proctitle(s); #if defined(USE_PAM) - if (options.use_pam && !use_privsep) + if (options.use_pam && !use_privsep) { + do_pam_session(); do_pam_setcred(1); + } #endif /* USE_PAM */ /* Fork the child. */ @@ -531,8 +533,10 @@ #if defined(USE_PAM) if (options.use_pam) { do_pam_set_tty(s->tty); - if (!use_privsep) + if (!use_privsep) { + do_pam_session(); do_pam_setcred(1); + } } #endif Index: auth-pam.c ==================================================================--- auth-pam.c (revision 15) +++ auth-pam.c (working copy) @@ -996,6 +996,8 @@ void do_pam_session(void) { + if(sshpam_session_open) return; + debug3("PAM: opening session"); sshpam_err = pam_set_item(sshpam_handle, PAM_CONV, (const void *)&store_conv); -- Nye Liu nliu at mrv.com (818) 772-6235x248 (818) 772-0576 fax "Who would be stupid enough to quote a fictitious character?" -- Don Quixote