Hello All. Attached is an update to my previous patch to make do_pam_chauthtok and privsep play nicely together. First, a question: does anybody care about these or the password expiration patches? Anyway, the "PRIVSEP(do_pam_hauthtok())" has been moved to just after the pty has been allocated but before it's made the controlling tty. This allows the child running chauthtok to acquire a controlling tty so the PAM conversation function works without modification. The child then runs to completion so the slave can acquire its controlling tty and continue as normal. Description from previous patch: Attached is a patch that implements password expiry with PAM and privsep. It works by passing a descriptor to the tty to the monitor, which sets up a child with that tty as stdin/stdout/stderr, then runs chauthtok(). No setuid helpers. -- Darren Tucker (dtucker at zip.com.au) GPG key 8FF4FA69 / D9A3 86E9 7EEE AF4B B2D4 37C9 C982 80C7 8FF4 FA69 Good judgement comes with experience. Unfortunately, the experience usually comes from bad judgement. -------------- next part -------------- Index: auth-pam.c ==================================================================RCS file: /cvs/openssh/auth-pam.c,v retrieving revision 1.54 diff -u -r1.54 auth-pam.c --- auth-pam.c 28 Jul 2002 20:24:08 -0000 1.54 +++ auth-pam.c 21 Dec 2002 11:39:05 -0000 @@ -42,8 +42,6 @@ #define NEW_AUTHTOK_MSG \ "Warning: Your password has expired, please change it now." -#define NEW_AUTHTOK_MSG_PRIVSEP \ - "Your password has expired, the session cannot proceed." static int do_pam_conversation(int num_msg, const struct pam_message **msg, struct pam_response **resp, void *appdata_ptr); @@ -186,12 +184,15 @@ pam_retval, PAM_STRERROR(__pamh, pam_retval)); } +/* HP-UX doesn't like credentials to be deleted. Skip and rely on pam_end() */ +#ifndef __hpux if (__pamh && creds_set) { pam_retval = pam_setcred(__pamh, PAM_DELETE_CRED); if (pam_retval != PAM_SUCCESS) debug("Cannot delete credentials[%d]: %.200s", pam_retval, PAM_STRERROR(__pamh, pam_retval)); } +#endif if (__pamh) { pam_retval = pam_end(__pamh, pam_retval); @@ -256,10 +257,8 @@ case PAM_SUCCESS: /* This is what we want */ break; -#if 0 case PAM_NEW_AUTHTOK_REQD: - message_cat(&__pam_msg, use_privsep ? - NEW_AUTHTOK_MSG_PRIVSEP : NEW_AUTHTOK_MSG); + message_cat(&__pam_msg, NEW_AUTHTOK_MSG); /* flag that password change is necessary */ password_change_required = 1; /* disallow other functionality for now */ @@ -267,7 +266,6 @@ no_agent_forwarding_flag |= 2; no_x11_forwarding_flag |= 2; break; -#endif default: log("PAM rejected by account configuration[%d]: " "%.200s", pam_retval, PAM_STRERROR(__pamh, @@ -301,6 +299,18 @@ session_opened = 1; } +/* Set the TTY after session is open */ +void do_pam_set_tty(const char *ttyname) { + int pam_retval; + if (ttyname != NULL) { + debug("PAM setting tty to \"%.200s\"", ttyname); + pam_retval = pam_set_item(__pamh, PAM_TTY, ttyname); + if (pam_retval != PAM_SUCCESS) + fatal("PAM set tty failed[%d]: %.200s", + pam_retval, PAM_STRERROR(__pamh, pam_retval)); + } +} + /* Set PAM credentials */ void do_pam_setcred(int init) { @@ -344,17 +354,15 @@ do_pam_set_conv(&conv); if (password_change_required) { - if (use_privsep) - fatal("Password changing is currently unsupported" - " with privilege separation"); pamstate = OTHER; pam_retval = pam_chauthtok(__pamh, PAM_CHANGE_EXPIRED_AUTHTOK); if (pam_retval != PAM_SUCCESS) fatal("PAM pam_chauthtok failed[%d]: %.200s", pam_retval, PAM_STRERROR(__pamh, pam_retval)); -#if 0 /* XXX: This would need to be done in the parent process, * but there's currently no way to pass such request. */ + password_change_required = 0; +#if 0 no_port_forwarding_flag &= ~2; no_agent_forwarding_flag &= ~2; no_x11_forwarding_flag &= ~2; Index: auth-pam.h ==================================================================RCS file: /cvs/openssh/auth-pam.h,v retrieving revision 1.16 diff -u -r1.16 auth-pam.h --- auth-pam.h 23 Jul 2002 00:44:07 -0000 1.16 +++ auth-pam.h 21 Dec 2002 11:39:05 -0000 @@ -25,6 +25,8 @@ */ #include "includes.h" +#include "channels.h" +#include "session.h" #ifdef USE_PAM #if !defined(SSHD_PAM_SERVICE) Index: monitor.c ==================================================================RCS file: /cvs/openssh/monitor.c,v retrieving revision 1.33 diff -u -r1.33 monitor.c --- monitor.c 9 Nov 2002 15:47:49 -0000 1.33 +++ monitor.c 21 Dec 2002 11:39:06 -0000 @@ -118,6 +118,7 @@ #ifdef USE_PAM int mm_answer_pam_start(int, Buffer *); +int mm_answer_pam_chauthtok(int, Buffer *); #endif #ifdef KRB4 @@ -183,6 +184,9 @@ {MONITOR_REQ_PTY, 0, mm_answer_pty}, {MONITOR_REQ_PTYCLEANUP, 0, mm_answer_pty_cleanup}, {MONITOR_REQ_TERM, 0, mm_answer_term}, +#ifdef USE_PAM + {MONITOR_REQ_PAM_CHAUTHTOK, 0, mm_answer_pam_chauthtok}, +#endif {0, 0, NULL} }; @@ -219,6 +223,9 @@ {MONITOR_REQ_PTY, MON_ONCE, mm_answer_pty}, {MONITOR_REQ_PTYCLEANUP, MON_ONCE, mm_answer_pty_cleanup}, {MONITOR_REQ_TERM, 0, mm_answer_term}, +#ifdef USE_PAM + {MONITOR_REQ_PAM_CHAUTHTOK, 0, mm_answer_pam_chauthtok}, +#endif {0, 0, NULL} }; @@ -328,6 +335,7 @@ if (!no_pty_flag) { monitor_permit(mon_dispatch, MONITOR_REQ_PTY, 1); monitor_permit(mon_dispatch, MONITOR_REQ_PTYCLEANUP, 1); + monitor_permit(mon_dispatch, MONITOR_REQ_PAM_CHAUTHTOK, 1); } for (;;) @@ -746,6 +754,56 @@ xfree(user); return (0); +} + +int +mm_answer_pam_chauthtok(int socket, Buffer *m) +{ + pid_t pid; + int ttyfd, status; + mysig_t old_signal; + + old_signal = mysignal(SIGCHLD, SIG_DFL); + + ttyfd = mm_receive_fd(socket); + debug3("%s: ttyfd=%d, ttyname=%s", __func__, ttyfd, ttyname(ttyfd)); + + if ((pid = fork()) == 0) { + /* acquire controlling tty */ + pty_make_controlling_tty(ttyfd, ttyname(ttyfd)); + + /* set up stdin, stdout and stderr */ + if (dup2(ttyfd, 0) < 0) + error("dup2 stdin: %s", strerror(errno)); + if (dup2(ttyfd, 1) < 0) + error("dup2 stdout: %s", strerror(errno)); + if (dup2(ttyfd, 2) < 0) + error("dup2 stderr: %s", strerror(errno)); + + /* close extra descriptors */ + close(socket); + close(ttyfd); + + /* call PAM chauthtok and return status to parent */ + do_pam_chauthtok(); + if(is_pam_password_change_required()) + exit(1); /* failed */ + else + exit(0); /* success */ + } + close(ttyfd); + + if (waitpid(pid, &status, 0) == -1) + fatal("Couldn't wait for child: %s", strerror(errno)); + + if (WEXITSTATUS(status)) + fatal("do_pam_chauthtok() failed, child returned %d", status); + + mysignal(SIGCHLD, old_signal); + + mm_request_send(socket, MONITOR_ANS_PAM_CHAUTHTOK, m); + + return 1; } #endif Index: monitor.h ==================================================================RCS file: /cvs/openssh/monitor.h,v retrieving revision 1.10 diff -u -r1.10 monitor.h --- monitor.h 27 Sep 2002 03:26:02 -0000 1.10 +++ monitor.h 21 Dec 2002 11:39:06 -0000 @@ -52,6 +52,7 @@ MONITOR_REQ_KRB4, MONITOR_ANS_KRB4, MONITOR_REQ_KRB5, MONITOR_ANS_KRB5, MONITOR_REQ_PAM_START, + MONITOR_REQ_PAM_CHAUTHTOK, MONITOR_ANS_PAM_CHAUTHTOK, MONITOR_REQ_TERM }; Index: monitor_wrap.c ==================================================================RCS file: /cvs/openssh/monitor_wrap.c,v retrieving revision 1.20 diff -u -r1.20 monitor_wrap.c --- monitor_wrap.c 27 Sep 2002 03:26:03 -0000 1.20 +++ monitor_wrap.c 21 Dec 2002 11:39:06 -0000 @@ -663,6 +663,31 @@ buffer_free(&m); } + +/* + * Privsep chauthtok works by passing a descriptor to the session's + * stdin/stdout to the monitor, which then sets up a child with this + * descriptor as stdin, stdout and controlling terminal, then calls + * chauthtok() + * + * This MUST be called before the session has acquired its controlling + * tty or the chauthtok child will not be able to acquire it and + * will fail. + */ + +void +mm_do_pam_chauthtok(void) +{ + int result; + Buffer m; + + buffer_init(&m); + mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_CHAUTHTOK, &m); + mm_send_fd(pmonitor->m_recvfd, STDIN_FILENO); + mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PAM_CHAUTHTOK, &m); + + buffer_free(&m); +} #endif /* USE_PAM */ /* Request process termination */ Index: monitor_wrap.h ==================================================================RCS file: /cvs/openssh/monitor_wrap.h,v retrieving revision 1.9 diff -u -r1.9 monitor_wrap.h --- monitor_wrap.h 27 Sep 2002 03:26:04 -0000 1.9 +++ monitor_wrap.h 21 Dec 2002 11:39:06 -0000 @@ -57,6 +57,7 @@ #ifdef USE_PAM void mm_start_pam(char *); +void mm_pam_chauthtok(void); #endif void mm_terminate(void); Index: session.c ==================================================================RCS file: /cvs/openssh/session.c,v retrieving revision 1.222 diff -u -r1.222 session.c --- session.c 26 Sep 2002 00:38:50 -0000 1.222 +++ session.c 21 Dec 2002 11:39:07 -0000 @@ -454,7 +454,6 @@ session_proctitle(s); #if defined(USE_PAM) - do_pam_session(s->pw->pw_name, NULL); do_pam_setcred(1); if (is_pam_password_change_required()) packet_disconnect("Password change required but no " @@ -581,7 +580,7 @@ ttyfd = s->ttyfd; #if defined(USE_PAM) - do_pam_session(s->pw->pw_name, s->tty); + do_pam_set_tty(s->tty); do_pam_setcred(1); #endif @@ -594,9 +593,6 @@ /* Close the master side of the pseudo tty. */ close(ptyfd); - /* Make the pseudo tty our controlling tty. */ - pty_make_controlling_tty(&ttyfd, s->tty); - /* Redirect stdin/stdout/stderr from the pseudo tty. */ if (dup2(ttyfd, 0) < 0) error("dup2 stdin: %s", strerror(errno)); @@ -608,6 +604,24 @@ /* Close the extra descriptor for the pseudo tty. */ close(ttyfd); +#ifdef USE_PAM + /* + * If password change is needed, do it now. + * For privsep, this needs to occur before we acquire a + * controlling tty. + */ + print_pam_messages(); + if (use_privsep && is_pam_password_change_required()) + PRIVSEP(do_pam_chauthtok()); +#endif + /* Make the pseudo tty our controlling tty. */ + pty_make_controlling_tty(&ttyfd, s->tty); + + /* without privsep, chauthtok requires a controlling tty */ + if (!use_privsep) + do_pam_chauthtok(); + + /* record login, etc. similar to login(1) */ #ifndef HAVE_OSF_SIA if (!(options.use_login && command == NULL)) { @@ -746,16 +760,6 @@ options.verify_reverse_mapping), (struct sockaddr *)&from, fromlen); -#ifdef USE_PAM - /* - * If password change is needed, do it now. - * This needs to occur before the ~/.hushlogin check. - */ - if (is_pam_password_change_required()) { - print_pam_messages(); - do_pam_chauthtok(); - } -#endif if (check_quietlogin(s, command)) return; @@ -1238,6 +1242,12 @@ * Reestablish them here. */ do_pam_setcred(0); + + /* + * We need to open the session here because PAM on HP-UX does not + * work after the call to permanently_set_uid. + */ + do_pam_session(pw->pw_name,NULL); # endif /* USE_PAM */ # if defined(WITH_IRIX_PROJECT) || defined(WITH_IRIX_JOBS) || defined(WITH_IRIX_ARRAY) irix_setusercontext(pw);
On Sat, Dec 21, 2002 at 11:11:04PM +1100, Darren Tucker wrote:> Attached is an update to my previous patch to make do_pam_chauthtok and > privsep play nicely together. > > First, a question: does anybody care about these or the password > expiration patches?yes, i feel it's the most important issue for portable right now. i'll try to catch up on history and progress. i'd like to get solar involved but i know he is busy also.
Darren Tucker wrote:> Hello All. > Attached is an update to my previous patch to make do_pam_chauthtok and > privsep play nicely together. > > First, a question: does anybody care about these or the password > expiration patches?Yes - I'll look at these later this week or early next week (once the NYE hangover wears off...) -d
On Sat, Dec 21, 2002 at 11:11:04PM +1100, Darren Tucker wrote:> Index: session.c > ==================================================================> RCS file: /cvs/openssh/session.c,v > retrieving revision 1.222 > diff -u -r1.222 session.c > --- session.c 26 Sep 2002 00:38:50 -0000 1.222 > +++ session.c 21 Dec 2002 11:39:07 -0000 > @@ -454,7 +454,6 @@ > session_proctitle(s); > > #if defined(USE_PAM) > - do_pam_session(s->pw->pw_name, NULL); > do_pam_setcred(1); > if (is_pam_password_change_required()) > packet_disconnect("Password change required but no "> if (check_quietlogin(s, command)) > return; > @@ -1238,6 +1242,12 @@ > * Reestablish them here. > */ > do_pam_setcred(0); > + > + /* > + * We need to open the session here because PAM on HP-UX does not > + * work after the call to permanently_set_uid. > + */ > + do_pam_session(pw->pw_name,NULL); > # endif /* USE_PAM */ > # if defined(WITH_IRIX_PROJECT) || defined(WITH_IRIX_JOBS) || defined(WITH_IRIX_ARRAY) > irix_setusercontext(pw);this should be separated out as it's addressing a different problem: running session modules as root. i think we have agreement that a system service like sshd really needs to run PAM modules as root, since there is no mechanism in the API for a module to indicate privilege requirements to a consumer, or a mechanism for a consumer to determine the highest privilege required of all configured service modules. on hp-ux, in the trusted case, the pam_unix session module needs root because it wants to write in /tcb. so, we want to do this, but i am not sure this is the "correct" way to do this. i'm not saying it's wrong, i want to make sure it is correct. we want to be very careful moving this stuff around.
Could somebody give me a hint on how to use the patch for password expiration? I am about to start "./configure" OpenSSH35p1. I have downloaded Darren Tucker's id#200, openssh-passwordpatch.11. This patch has sections like "Index: acconfig.h" and "Index: auth-pam.c". Do I need to append these sections to appropriate files in the openssh-3.5.p1 directory? I have searched the net but could not find an explanation on its usage for non-developers like myself. Also I am doing this to fix my first 3.5.p1 build which has a password expiration problem. Is there any work around, other than rebuilding package and reinstalling it on servers? Thank you. Mesut Pak Darren Tucker <dtucker at zip.com.au> To: OpenSSH Devel List <openssh-unix-dev at mindrot.org> Sent by: cc: openssh-unix-dev-admin@ Subject: [PATCH] PAM chauthtok + Privsep mindrot.org 12/21/2002 07:11 AM Hello All. Attached is an update to my previous patch to make do_pam_chauthtok and privsep play nicely together. First, a question: does anybody care about these or the password expiration patches? Anyway, the "PRIVSEP(do_pam_hauthtok())" has been moved to just after the pty has been allocated but before it's made the controlling tty. This allows the child running chauthtok to acquire a controlling tty so the PAM conversation function works without modification. The child then runs to completion so the slave can acquire its controlling tty and continue as normal. Description from previous patch: Attached is a patch that implements password expiry with PAM and privsep. It works by passing a descriptor to the tty to the monitor, which sets up a child with that tty as stdin/stdout/stderr, then runs chauthtok(). No setuid helpers. -- Darren Tucker (dtucker at zip.com.au) GPG key 8FF4FA69 / D9A3 86E9 7EEE AF4B B2D4 37C9 C982 80C7 8FF4 FA69 Good judgement comes with experience. Unfortunately, the experience usually comes from bad judgement.Index: auth-pam.c ==================================================================RCS file: /cvs/openssh/auth-pam.c,v retrieving revision 1.54 diff -u -r1.54 auth-pam.c --- auth-pam.c 28 Jul 2002 20:24:08 -0000 1.54 +++ auth-pam.c 21 Dec 2002 11:39:05 -0000 @@ -42,8 +42,6 @@ #define NEW_AUTHTOK_MSG \ "Warning: Your password has expired, please change it now." -#define NEW_AUTHTOK_MSG_PRIVSEP \ - "Your password has expired, the session cannot proceed." static int do_pam_conversation(int num_msg, const struct pam_message **msg, struct pam_response **resp, void *appdata_ptr); @@ -186,12 +184,15 @@ pam_retval, PAM_STRERROR(__pamh, pam_retval)); } +/* HP-UX doesn't like credentials to be deleted. Skip and rely on pam_end () */ +#ifndef __hpux if (__pamh && creds_set) { pam_retval = pam_setcred(__pamh, PAM_DELETE_CRED); if (pam_retval != PAM_SUCCESS) debug("Cannot delete credentials[%d]: %.200s", pam_retval, PAM_STRERROR(__pamh, pam_retval)); } +#endif if (__pamh) { pam_retval = pam_end(__pamh, pam_retval); @@ -256,10 +257,8 @@ case PAM_SUCCESS: /* This is what we want */ break; -#if 0 case PAM_NEW_AUTHTOK_REQD: - message_cat(&__pam_msg, use_privsep ? - NEW_AUTHTOK_MSG_PRIVSEP : NEW_AUTHTOK_MSG); + message_cat(&__pam_msg, NEW_AUTHTOK_MSG); /* flag that password change is necessary */ password_change_required = 1; /* disallow other functionality for now */ @@ -267,7 +266,6 @@ no_agent_forwarding_flag |= 2; no_x11_forwarding_flag |= 2; break; -#endif default: log("PAM rejected by account configuration [%d]: " "%.200s", pam_retval, PAM_STRERROR (__pamh, @@ -301,6 +299,18 @@ session_opened = 1; } +/* Set the TTY after session is open */ +void do_pam_set_tty(const char *ttyname) { + int pam_retval; + if (ttyname != NULL) { + debug("PAM setting tty to \"%.200s\"", ttyname); + pam_retval = pam_set_item(__pamh, PAM_TTY, ttyname); + if (pam_retval != PAM_SUCCESS) + fatal("PAM set tty failed[%d]: %.200s", + pam_retval, PAM_STRERROR(__pamh, pam_retval)); + } +} + /* Set PAM credentials */ void do_pam_setcred(int init) { @@ -344,17 +354,15 @@ do_pam_set_conv(&conv); if (password_change_required) { - if (use_privsep) - fatal("Password changing is currently unsupported" - " with privilege separation"); pamstate = OTHER; pam_retval = pam_chauthtok(__pamh, PAM_CHANGE_EXPIRED_AUTHTOK); if (pam_retval != PAM_SUCCESS) fatal("PAM pam_chauthtok failed[%d]: %.200s", pam_retval, PAM_STRERROR(__pamh, pam_retval)); -#if 0 /* XXX: This would need to be done in the parent process, * but there's currently no way to pass such request. */ + password_change_required = 0; +#if 0 no_port_forwarding_flag &= ~2; no_agent_forwarding_flag &= ~2; no_x11_forwarding_flag &= ~2; Index: auth-pam.h ==================================================================RCS file: /cvs/openssh/auth-pam.h,v retrieving revision 1.16 diff -u -r1.16 auth-pam.h --- auth-pam.h 23 Jul 2002 00:44:07 -0000 1.16 +++ auth-pam.h 21 Dec 2002 11:39:05 -0000 @@ -25,6 +25,8 @@ */ #include "includes.h" +#include "channels.h" +#include "session.h" #ifdef USE_PAM #if !defined(SSHD_PAM_SERVICE) Index: monitor.c ==================================================================RCS file: /cvs/openssh/monitor.c,v retrieving revision 1.33 diff -u -r1.33 monitor.c --- monitor.c 9 Nov 2002 15:47:49 -0000 1.33 +++ monitor.c 21 Dec 2002 11:39:06 -0000 @@ -118,6 +118,7 @@ #ifdef USE_PAM int mm_answer_pam_start(int, Buffer *); +int mm_answer_pam_chauthtok(int, Buffer *); #endif #ifdef KRB4 @@ -183,6 +184,9 @@ {MONITOR_REQ_PTY, 0, mm_answer_pty}, {MONITOR_REQ_PTYCLEANUP, 0, mm_answer_pty_cleanup}, {MONITOR_REQ_TERM, 0, mm_answer_term}, +#ifdef USE_PAM + {MONITOR_REQ_PAM_CHAUTHTOK, 0, mm_answer_pam_chauthtok}, +#endif {0, 0, NULL} }; @@ -219,6 +223,9 @@ {MONITOR_REQ_PTY, MON_ONCE, mm_answer_pty}, {MONITOR_REQ_PTYCLEANUP, MON_ONCE, mm_answer_pty_cleanup}, {MONITOR_REQ_TERM, 0, mm_answer_term}, +#ifdef USE_PAM + {MONITOR_REQ_PAM_CHAUTHTOK, 0, mm_answer_pam_chauthtok}, +#endif {0, 0, NULL} }; @@ -328,6 +335,7 @@ if (!no_pty_flag) { monitor_permit(mon_dispatch, MONITOR_REQ_PTY, 1); monitor_permit(mon_dispatch, MONITOR_REQ_PTYCLEANUP, 1); + monitor_permit(mon_dispatch, MONITOR_REQ_PAM_CHAUTHTOK, 1); } for (;;) @@ -746,6 +754,56 @@ xfree(user); return (0); +} + +int +mm_answer_pam_chauthtok(int socket, Buffer *m) +{ + pid_t pid; + int ttyfd, status; + mysig_t old_signal; + + old_signal = mysignal(SIGCHLD, SIG_DFL); + + ttyfd = mm_receive_fd(socket); + debug3("%s: ttyfd=%d, ttyname=%s", __func__, ttyfd, ttyname(ttyfd)); + + if ((pid = fork()) == 0) { + /* acquire controlling tty */ + pty_make_controlling_tty(ttyfd, ttyname(ttyfd)); + + /* set up stdin, stdout and stderr */ + if (dup2(ttyfd, 0) < 0) + error("dup2 stdin: %s", strerror(errno)); + if (dup2(ttyfd, 1) < 0) + error("dup2 stdout: %s", strerror(errno)); + if (dup2(ttyfd, 2) < 0) + error("dup2 stderr: %s", strerror(errno)); + + /* close extra descriptors */ + close(socket); + close(ttyfd); + + /* call PAM chauthtok and return status to parent */ + do_pam_chauthtok(); + if(is_pam_password_change_required()) + exit(1); /* failed */ + else + exit(0); /* success */ + } + close(ttyfd); + + if (waitpid(pid, &status, 0) == -1) + fatal("Couldn't wait for child: %s", strerror(errno)); + + if (WEXITSTATUS(status)) + fatal("do_pam_chauthtok() failed, child returned %d", status); + + mysignal(SIGCHLD, old_signal); + + mm_request_send(socket, MONITOR_ANS_PAM_CHAUTHTOK, m); + + return 1; } #endif Index: monitor.h ==================================================================RCS file: /cvs/openssh/monitor.h,v retrieving revision 1.10 diff -u -r1.10 monitor.h --- monitor.h 27 Sep 2002 03:26:02 -0000 1.10 +++ monitor.h 21 Dec 2002 11:39:06 -0000 @@ -52,6 +52,7 @@ MONITOR_REQ_KRB4, MONITOR_ANS_KRB4, MONITOR_REQ_KRB5, MONITOR_ANS_KRB5, MONITOR_REQ_PAM_START, + MONITOR_REQ_PAM_CHAUTHTOK, MONITOR_ANS_PAM_CHAUTHTOK, MONITOR_REQ_TERM }; Index: monitor_wrap.c ==================================================================RCS file: /cvs/openssh/monitor_wrap.c,v retrieving revision 1.20 diff -u -r1.20 monitor_wrap.c --- monitor_wrap.c 27 Sep 2002 03:26:03 -0000 1.20 +++ monitor_wrap.c 21 Dec 2002 11:39:06 -0000 @@ -663,6 +663,31 @@ buffer_free(&m); } + +/* + * Privsep chauthtok works by passing a descriptor to the session's + * stdin/stdout to the monitor, which then sets up a child with this + * descriptor as stdin, stdout and controlling terminal, then calls + * chauthtok() + * + * This MUST be called before the session has acquired its controlling + * tty or the chauthtok child will not be able to acquire it and + * will fail. + */ + +void +mm_do_pam_chauthtok(void) +{ + int result; + Buffer m; + + buffer_init(&m); + mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_CHAUTHTOK, &m); + mm_send_fd(pmonitor->m_recvfd, STDIN_FILENO); + mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PAM_CHAUTHTOK, &m); + + buffer_free(&m); +} #endif /* USE_PAM */ /* Request process termination */ Index: monitor_wrap.h ==================================================================RCS file: /cvs/openssh/monitor_wrap.h,v retrieving revision 1.9 diff -u -r1.9 monitor_wrap.h --- monitor_wrap.h 27 Sep 2002 03:26:04 -0000 1.9 +++ monitor_wrap.h 21 Dec 2002 11:39:06 -0000 @@ -57,6 +57,7 @@ #ifdef USE_PAM void mm_start_pam(char *); +void mm_pam_chauthtok(void); #endif void mm_terminate(void); Index: session.c ==================================================================RCS file: /cvs/openssh/session.c,v retrieving revision 1.222 diff -u -r1.222 session.c --- session.c 26 Sep 2002 00:38:50 -0000 1.222 +++ session.c 21 Dec 2002 11:39:07 -0000 @@ -454,7 +454,6 @@ session_proctitle(s); #if defined(USE_PAM) - do_pam_session(s->pw->pw_name, NULL); do_pam_setcred(1); if (is_pam_password_change_required()) packet_disconnect("Password change required but no " @@ -581,7 +580,7 @@ ttyfd = s->ttyfd; #if defined(USE_PAM) - do_pam_session(s->pw->pw_name, s->tty); + do_pam_set_tty(s->tty); do_pam_setcred(1); #endif @@ -594,9 +593,6 @@ /* Close the master side of the pseudo tty. */ close(ptyfd); - /* Make the pseudo tty our controlling tty. */ - pty_make_controlling_tty(&ttyfd, s->tty); - /* Redirect stdin/stdout/stderr from the pseudo tty. */ if (dup2(ttyfd, 0) < 0) error("dup2 stdin: %s", strerror(errno)); @@ -608,6 +604,24 @@ /* Close the extra descriptor for the pseudo tty. */ close(ttyfd); +#ifdef USE_PAM + /* + * If password change is needed, do it now. + * For privsep, this needs to occur before we acquire a + * controlling tty. + */ + print_pam_messages(); + if (use_privsep && is_pam_password_change_required()) + PRIVSEP(do_pam_chauthtok()); +#endif + /* Make the pseudo tty our controlling tty. */ + pty_make_controlling_tty(&ttyfd, s->tty); + + /* without privsep, chauthtok requires a controlling tty */ + if (!use_privsep) + do_pam_chauthtok(); + + /* record login, etc. similar to login(1) */ #ifndef HAVE_OSF_SIA if (!(options.use_login && command == NULL)) { @@ -746,16 +760,6 @@ options.verify_reverse_mapping), (struct sockaddr *)&from, fromlen); -#ifdef USE_PAM - /* - * If password change is needed, do it now. - * This needs to occur before the ~/.hushlogin check. - */ - if (is_pam_password_change_required()) { - print_pam_messages(); - do_pam_chauthtok(); - } -#endif if (check_quietlogin(s, command)) return; @@ -1238,6 +1242,12 @@ * Reestablish them here. */ do_pam_setcred(0); + + /* + * We need to open the session here because PAM on HP-UX does not + * work after the call to permanently_set_uid. + */ + do_pam_session(pw->pw_name,NULL); # endif /* USE_PAM */ # if defined(WITH_IRIX_PROJECT) || defined(WITH_IRIX_JOBS) || defined(WITH_IRIX_ARRAY) irix_setusercontext(pw);
Thank you for the response. Platform is Sparc Solaris 8, with 2 or 3 Solaris 7s. Darren Tucker <dtucker at zip.c To: MPak at dotsconnect.com om.au> cc: openssh-unix-dev at mindrot.org 01/10/2003 Subject: Re: [PATCH] PAM chauthtok + Privsep 04:59 AM MPak at dotsconnect.com wrote:> Could somebody give me a hint on how to use the patch for password > expiration? > I am about to start "./configure" OpenSSH35p1. I have downloaded Darren > Tucker's id#200, openssh-passwordpatch.11.Please don't use patches 10 or 11, I've just found that they don't correctly check for successful password change. I'm working on it now.> This patch has sections like "Index: acconfig.h" and "Index: auth-pam.c". > Do I need to append these sections to appropriate files in the > openssh-3.5.p1 directory? > I have searched the net but could not find an explanation on its usagefor> non-developers like myself. > > Also I am doing this to fix my first 3.5.p1 build which has a password > expiration problem. Is there any work around, other than rebuildingpackage> and reinstalling it on servers?Patches 9 and up are against the current CVS tree and not 3.5p1 and won't apply cleanly (ie you'll need to fix conflicts yourself). What platform are you using? There are a couple of patches that apply to 3.5p1 but the one to use depends on your platform. -- Darren Tucker (dtucker at zip.com.au) GPG key 8FF4FA69 / D9A3 86E9 7EEE AF4B B2D4 37C9 C982 80C7 8FF4 FA69 Good judgement comes with experience. Unfortunately, the experience usually comes from bad judgement.
[This is a re-send, the previous message bounced] MPak at dotsconnect.com wrote:> Could somebody give me a hint on how to use the patch for password > expiration?Grab the following patch (against the 3.5p1 release): http://www.zip.com.au/~dtucker/openssh/openssh-3.5p1-passexpire12.patch Untar the openssh-3.5p1 tarball. patch -p0 <openssh-3.5p1-passexpire12.patch cd openssh-3.5p1 ./configure && make You may need GNU patch (ftp://ftp.gnu.org/pub/gnu/patch/patch-2.5.4.tar.gz). Please let me know how it goes. -- Darren Tucker (dtucker at zip.com.au) GPG key 8FF4FA69 / D9A3 86E9 7EEE AF4B B2D4 37C9 C982 80C7 8FF4 FA69 Good judgement comes with experience. Unfortunately, the experience usually comes from bad judgement.