Bugzilla – Attachment 162 Details for
Bug 423
Workaround for pw change in privsep mode (3.5.p1)
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Patch: Workaround for pw change in privsep mode (3.5.p1)
openssh-3.5p1-chauthtok-helper.patch (text/plain), 17.15 KB, created by
Michael Steffens
on 2002-11-02 02:40:10 AEDT
(
hide
)
Description:
Patch: Workaround for pw change in privsep mode (3.5.p1)
Filename:
MIME Type:
Creator:
Michael Steffens
Created:
2002-11-02 02:40:10 AEDT
Size:
17.15 KB
patch
obsolete
>diff -u -r -P openssh-3.5p1/Makefile.in openssh-3.5p1d/Makefile.in >--- openssh-3.5p1/Makefile.in Sun Jul 14 19:02:21 2002 >+++ openssh-3.5p1d/Makefile.in Wed Oct 23 06:55:55 2002 >@@ -25,6 +25,7 @@ > SFTP_SERVER=$(libexecdir)/sftp-server > SSH_KEYSIGN=$(libexecdir)/ssh-keysign > RAND_HELPER=$(libexecdir)/ssh-rand-helper >+CHAUTHTOK_HELPER=$(libexecdir)/ssh-chauthtok-helper > PRIVSEP_PATH=@PRIVSEP_PATH@ > SSH_PRIVSEP_USER=@SSH_PRIVSEP_USER@ > >@@ -35,7 +36,8 @@ > -D_PATH_SSH_KEY_SIGN=\"$(SSH_KEYSIGN)\" \ > -D_PATH_SSH_PIDDIR=\"$(piddir)\" \ > -D_PATH_PRIVSEP_CHROOT_DIR=\"$(PRIVSEP_PATH)\" \ >- -DSSH_RAND_HELPER=\"$(RAND_HELPER)\" >+ -DSSH_RAND_HELPER=\"$(RAND_HELPER)\" \ >+ -DSSH_CHAUTHTOK_HELPER=\"$(CHAUTHTOK_HELPER)\" > > CC=@CC@ > LD=@LD@ >@@ -55,10 +57,11 @@ > > INSTALL_SSH_PRNG_CMDS=@INSTALL_SSH_PRNG_CMDS@ > INSTALL_SSH_RAND_HELPER=@INSTALL_SSH_RAND_HELPER@ >+INSTALL_SSH_CHAUTHTOK_HELPER=yes > > @NO_SFTP@SFTP_PROGS=sftp-server$(EXEEXT) sftp$(EXEEXT) > >-TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) ssh-add$(EXEEXT) ssh-keygen$(EXEEXT) ssh-keyscan${EXEEXT} ssh-keysign${EXEEXT} ssh-agent$(EXEEXT) scp$(EXEEXT) ssh-rand-helper${EXEEXT} $(SFTP_PROGS) >+TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) ssh-add$(EXEEXT) ssh-keygen$(EXEEXT) ssh-keyscan${EXEEXT} ssh-keysign${EXEEXT} ssh-agent$(EXEEXT) scp$(EXEEXT) ssh-rand-helper${EXEEXT} ssh-chauthtok-helper${EXEEXT} $(SFTP_PROGS) > > LIBSSH_OBJS=atomicio.o authfd.o authfile.o bufaux.o buffer.o canohost.o channels.o cipher.o compat.o compress.o crc32.o deattack.o dh.o dispatch.o fatal.o mac.o msg.o hostfile.o key.o kex.o kexdh.o kexgex.o log.o match.o misc.o mpaux.o nchan.o packet.o radix.o rijndael.o entropy.o readpass.o rsa.o scard.o scard-opensc.o ssh-dss.o ssh-rsa.o tildexpand.o ttymodes.o uidswap.o uuencode.o xmalloc.o monitor_wrap.o monitor_fdpass.o > >@@ -143,6 +146,9 @@ > ssh-rand-helper${EXEEXT}: $(LIBCOMPAT) libssh.a ssh-rand-helper.o > $(LD) -o $@ ssh-rand-helper.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) > >+ssh-chauthtok-helper${EXEEXT}: $(LIBCOMPAT) libssh.a ssh-chauthtok-helper.o >+ $(LD) -o $@ ssh-chauthtok-helper.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBPAM) $(LIBS) >+ > # test driver for the loginrec code - not built by default > logintest: logintest.o $(LIBCOMPAT) libssh.a loginrec.o > $(LD) -o $@ logintest.o $(LDFLAGS) loginrec.o -lopenbsd-compat -lssh $(LIBS) >@@ -227,6 +233,9 @@ > if test ! -z "$(INSTALL_SSH_RAND_HELPER)" ; then \ > $(INSTALL) -m 0755 -s ssh-rand-helper $(DESTDIR)$(libexecdir)/ssh-rand-helper ; \ > fi >+ if test ! -z "$(INSTALL_SSH_CHAUTHTOK_HELPER)" ; then \ >+ $(INSTALL) -m 4711 -s ssh-chauthtok-helper $(DESTDIR)$(libexecdir)/ssh-chauthtok-helper ; \ >+ fi > $(INSTALL) -m 4711 -s ssh-keysign $(DESTDIR)$(SSH_KEYSIGN) > @NO_SFTP@$(INSTALL) -m 0755 -s sftp $(DESTDIR)$(bindir)/sftp > @NO_SFTP@$(INSTALL) -m 0755 -s sftp-server $(DESTDIR)$(SFTP_SERVER) >@@ -330,6 +339,7 @@ > -rm -r $(DESTDIR)$(SFTP_SERVER)$(EXEEXT) > -rm -f $(DESTDIR)$(SSH_KEYSIGN)$(EXEEXT) > -rm -f $(DESTDIR)$(RAND_HELPER)$(EXEEXT) >+ -rm -f $(DESTDIR)$(CHAUTHTOK_HELPER)$(EXEEXT) > -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/ssh.1 > -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/scp.1 > -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-add.1 >diff -u -r -P openssh-3.5p1/auth-pam.c openssh-3.5p1d/auth-pam.c >--- openssh-3.5p1/auth-pam.c Sun Jul 28 22:24:08 2002 >+++ openssh-3.5p1d/auth-pam.c Fri Nov 1 16:06:32 2002 >@@ -33,6 +33,7 @@ > #include "servconf.h" > #include "canohost.h" > #include "readpass.h" >+#include "misc.h" > > extern char *__progname; > >@@ -43,7 +44,7 @@ > #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." >+ "Warning: Your password has expired, please change it now." > > static int do_pam_conversation(int num_msg, const struct pam_message **msg, > struct pam_response **resp, void *appdata_ptr); >@@ -186,12 +187,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,7 +260,7 @@ > case PAM_SUCCESS: > /* This is what we want */ > break; >-#if 0 >+#if 1 > case PAM_NEW_AUTHTOK_REQD: > message_cat(&__pam_msg, use_privsep ? > NEW_AUTHTOK_MSG_PRIVSEP : NEW_AUTHTOK_MSG); >@@ -301,6 +305,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) > { >@@ -331,6 +347,56 @@ > return password_change_required; > } > >+/* Call external pam_chauthtok helper */ >+int do_chauthtok_helper(void) >+{ >+ mysig_t old_sigchld; >+ pid_t pid; >+ int retval; >+ int pam_retval; >+ const char *pam_user; >+ >+ pam_retval = pam_get_item(__pamh, PAM_USER, (const void **)&pam_user); >+ debug2("pam_get_item(PAM_USER) = %d", pam_retval); >+ if (pam_retval != PAM_SUCCESS) { >+ fatal("Cannot pam_get_item PAM_USER: %.200s", >+ PAM_STRERROR(__pamh, pam_retval)); >+ } >+ >+ old_sigchld = mysignal(SIGCHLD, SIG_DFL); >+ >+ pid = fork(); >+ if (pid < 0) { >+ fatal("Cannot fork %.200s: %.200s", SSH_CHAUTHTOK_HELPER, >+ strerror(errno)); >+ } >+ if (pid == 0) { >+ execl(SSH_CHAUTHTOK_HELPER, SSH_CHAUTHTOK_HELPER, >+ pam_user, (char *)0); >+ fatal("Cannot execute %.200s: %.200s", >+ SSH_CHAUTHTOK_HELPER, strerror(errno)); >+ } >+ >+ if (waitpid(pid, &retval, 0) != pid) >+ fatal("Cannot get exit status of %.200s (pid %d): %.200s", >+ SSH_CHAUTHTOK_HELPER, pid, strerror(errno)); >+ >+ mysignal(SIGCHLD, old_sigchld); >+ >+ if (!WIFEXITED(retval)) { >+ if (WIFSIGNALED(retval)) { >+ log("%.200s (pid %d) terminated by signal %d", >+ SSH_CHAUTHTOK_HELPER, pid, WTERMSIG(retval)); >+ } else { >+ log("%.200s (pid %d) terminated abnormally", >+ SSH_CHAUTHTOK_HELPER, pid); >+ } >+ return 255; >+ } >+ >+ return WEXITSTATUS(retval); >+} >+ > /* > * Have user change authentication token if pam_acct_mgmt() indicated > * it was expired. This needs to be called after an interactive >@@ -344,11 +410,13 @@ > 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 (use_privsep) { >+ pam_retval = do_chauthtok_helper(); >+ } else { >+ 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)); >diff -u -r -P openssh-3.5p1/auth-pam.h openssh-3.5p1d/auth-pam.h >--- openssh-3.5p1/auth-pam.h Tue Jul 23 02:44:07 2002 >+++ openssh-3.5p1d/auth-pam.h Wed Oct 23 06:55:55 2002 >@@ -39,6 +39,7 @@ > int do_pam_authenticate(int flags); > int do_pam_account(char *username, char *remote_user); > void do_pam_session(char *username, const char *ttyname); >+void do_pam_set_tty(const char *ttyname); > void do_pam_setcred(int init); > void print_pam_messages(void); > int is_pam_password_change_required(void); >diff -u -r -P openssh-3.5p1/session.c openssh-3.5p1d/session.c >--- openssh-3.5p1/session.c Thu Sep 26 02:38:50 2002 >+++ openssh-3.5p1d/session.c Wed Oct 23 06:55:55 2002 >@@ -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 > >@@ -1238,6 +1237,13 @@ > * 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); >diff -u -r -P openssh-3.5p1/ssh-chauthtok-helper.c openssh-3.5p1d/ssh-chauthtok-helper.c >--- openssh-3.5p1/ssh-chauthtok-helper.c Thu Jan 1 01:00:00 1970 >+++ openssh-3.5p1d/ssh-chauthtok-helper.c Fri Nov 1 14:52:07 2002 >@@ -0,0 +1,270 @@ >+/* >+ * Copyright (c) 2002 Michael Steffens. All rights reserved. >+ * >+ * Derived from auth-pam.c, >+ * Copyright (c) 2000 Damien Miller. All rights reserved. >+ * >+ * Redistribution and use in source and binary forms, with or without >+ * modification, are permitted provided that the following conditions >+ * are met: >+ * 1. Redistributions of source code must retain the above copyright >+ * notice, this list of conditions and the following disclaimer. >+ * 2. Redistributions in binary form must reproduce the above copyright >+ * notice, this list of conditions and the following disclaimer in the >+ * documentation and/or other materials provided with the distribution. >+ * >+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR >+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES >+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. >+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, >+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT >+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, >+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY >+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT >+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF >+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. >+ */ >+ >+/* >+ * This program provides a workaround for sshd presently not supporting >+ * user changes of expired passwords when running in privsep mode. >+ * >+ * When encountering an expired authentication token, the non-privileged >+ * session daemon can delegate change to ssh-chauthtok-helper, which >+ * should be installed suid root for performing this task. >+ * >+ * It is somewhat similar to the system passwd program, but dedicatedly >+ * talks to modules configured for PAM service "sshd", rather than those >+ * configured for passwd. These might be the same, but can also be >+ * different. >+ * >+ * By nature this helper program can also be invoked by local users >+ * directly, just as the passwd program can. But in any case >+ * >+ * - non-root users can only change their own authentication tokens. >+ * >+ * - root users can change authentication tokens for others, but only >+ * with providing the old token. >+ * >+ * The second restriction is meant to be a fuse against the helper program >+ * being accidentally invoked by a privileged daemon... >+ * >+ * The ssh-chauthtok-helper program unfortunately can't safely deal >+ * with the PAM_RUSER and PAM_RHOST items, because there is no way of >+ * preventing local users to feed in arbitrary values for these. >+ * They are being left undefined here, relying on modules and their >+ * configuration to decide whether to accept requests from unknown users >+ * at unknown hosts. (Always provided they have authenticated for the >+ * local account, of course!) >+ */ >+ >+#include "includes.h" >+ >+#ifdef USE_PAM >+ >+#include "xmalloc.h" >+#include "log.h" >+#include "readpass.h" >+ >+#define SSHD_PAM_SERVICE "sshd" >+ >+#ifdef HAVE___PROGNAME >+extern char *__progname; >+#else >+char *__progname; >+#endif >+ >+int null_pam_conv; >+ >+/* >+ * This is a downstripped version of do_pam_conversation() in pam-auth.c, >+ * with the INITIAL_LOGIN mode removed. At the time this program can be >+ * run we already are authenticated and do have STDIN available. >+ * The null_pam_conv flag enforces modules to be silent even if >+ * they do not honor the PAM_SILENT flag. We just don't need to tell >+ * the user again that passwords are expired when calling pam_acct_mgmt(), >+ * as this has already been done by the calling daemon. >+ */ >+static int do_pam_conversation(int num_msg, const struct pam_message **msg, >+ struct pam_response **resp, void *appdata_ptr) >+{ >+ struct pam_response *reply; >+ int count; >+ char buf[1024]; >+ >+ /* PAM will free this later */ >+ reply = xmalloc(num_msg * sizeof(*reply)); >+ >+ for (count = 0; count < num_msg; count++) { >+ /* >+ * stdio is connected, so interact directly >+ */ >+ switch(PAM_MSG_MEMBER(msg, count, msg_style)) { >+ case PAM_PROMPT_ECHO_ON: >+ if (null_pam_conv) { >+ xfree(reply); >+ return PAM_CONV_ERR; >+ } >+ fputs(PAM_MSG_MEMBER(msg, count, msg), stderr); >+ fgets(buf, sizeof(buf), stdin); >+ reply[count].resp = xstrdup(buf); >+ reply[count].resp_retcode = PAM_SUCCESS; >+ break; >+ case PAM_PROMPT_ECHO_OFF: >+ if (null_pam_conv) { >+ xfree(reply); >+ return PAM_CONV_ERR; >+ } >+ /* >+ * Lets's be a bit more paranoid than the original and >+ * avoid the read_passphrase() wrapper. There is no >+ * need to care for non-tty, and eventually call >+ * ssh-askpass, as we don't have X11-forwarding at >+ * this point anyway. >+ */ >+ if (readpassphrase(PAM_MSG_MEMBER(msg, count, msg), >+ buf, sizeof(buf), RPP_REQUIRE_TTY)) { >+ reply[count].resp = xstrdup(buf); >+ } else { >+ reply[count].resp = xstrdup(""); >+ } >+ memset(buf, 'x', sizeof(buf)); >+ reply[count].resp_retcode = PAM_SUCCESS; >+ break; >+ case PAM_ERROR_MSG: >+ case PAM_TEXT_INFO: >+ if (!null_pam_conv && PAM_MSG_MEMBER(msg, count, msg) != NULL) >+ fprintf(stderr, "%s\n", >+ PAM_MSG_MEMBER(msg, count, msg)); >+ reply[count].resp = xstrdup(""); >+ reply[count].resp_retcode = PAM_SUCCESS; >+ break; >+ default: >+ xfree(reply); >+ return PAM_CONV_ERR; >+ } >+ } >+ >+ *resp = reply; >+ >+ return PAM_SUCCESS; >+} >+ >+int main(int argc, char *argv[]) { >+ struct passwd *pw; >+ uid_t uid; >+ uid_t euid; >+ struct pam_conv conv = { >+ (int (*)())do_pam_conversation, >+ NULL >+ }; >+ pam_handle_t *pamh; >+ int pam_retval; >+ int retval = 0; >+ >+ __progname = get_progname(argv[0]); >+ log_init(__progname, SYSLOG_LEVEL_INFO, >+ SYSLOG_FACILITY_AUTH, 0); >+ >+ uid = getuid(); >+ euid = geteuid(); >+ if (euid != 0) >+ fatal("Cannot change authtok using effective uid %ld", (long)euid); >+ >+ switch (argc) { >+ case 2: >+ if (!(pw = getpwnam(argv[1]))) >+ fatal("Cannot get uid of user %.200s: %.200s", >+ argv[1], strerror(errno)); >+ if (uid && pw->pw_uid != uid) >+ fatal("Cannot chauthtok for user %.200s using uid %ld", >+ argv[1], (long)uid); >+ break; >+ default: >+ fprintf(stderr, "Usage: ssh-chauthtok-helper <user>\n"); >+ return 1; >+ } >+ >+ /* drop root real uid when changing authtok for another user */ >+ if (!uid && setuid(uid = pw->pw_uid)) >+ fatal("Cannot setuid %ld: %.200s", (long)uid, strerror(errno)); >+ >+ null_pam_conv = 1; >+ >+ pam_retval = pam_start(SSHD_PAM_SERVICE, pw->pw_name, &conv, &pamh); >+ switch (pam_retval) { >+ case PAM_SUCCESS: >+ break; >+ default: >+ fatal("PAM initialisation failed[%d]: %.200s", >+ pam_retval, PAM_STRERROR(pamh, pam_retval)); >+ break; >+ } >+ >+ /* >+ * Some PAM implemetations (HP-UX) require pam_acct_mgmt() to >+ * be invoked before they can identify expired tokens on >+ * pam_chauthtok(). >+ */ >+ pam_retval = pam_acct_mgmt(pamh, PAM_DISALLOW_NULL_AUTHTOK); >+ switch (pam_retval) { >+ case PAM_SUCCESS: >+ /* >+ * We were called for changing expired authentication >+ * tokens and found nothing to do! The caller should not >+ * consider this success... >+ */ >+ log("No expired authentication tokens found"); >+ retval = 255; >+ break; >+ case PAM_NEW_AUTHTOK_REQD: >+ break; >+ default: >+ fatal("PAM pam_acct_mgmt failed[%d]: %.200s", >+ pam_retval, PAM_STRERROR(pamh, pam_retval)); >+ break; >+ } >+ >+ /* >+ * pam_chauthtok() will perform authentication of its own, if required. >+ * For password change it will prompt for the old password only if >+ * the real uid is non-zero and the effective uid is zero. It doesn't >+ * work with the effective uid being non-zero, which is why this >+ * program exists... >+ */ >+ if (!retval) { >+ null_pam_conv = 0; >+ pam_retval = pam_chauthtok(pamh, PAM_CHANGE_EXPIRED_AUTHTOK); >+ switch (pam_retval) { >+ case PAM_SUCCESS: >+ break; >+ default: >+ log("PAM pam_chauthtok failed[%d]: %.200s", >+ pam_retval, PAM_STRERROR(pamh, pam_retval)); >+ break; >+ } >+ retval = pam_retval; >+ null_pam_conv = 1; >+ } >+ >+ pam_retval = pam_end(pamh, pam_retval); >+ switch (pam_retval) { >+ case PAM_SUCCESS: >+ break; >+ default: >+ log("PAM pam_end failed[%d]: %.200s", >+ pam_retval, PAM_STRERROR(pamh, pam_retval)); >+ break; >+ } >+ >+ return retval; >+} >+ >+#else /* USE_PAM */ >+ >+int main(int argc, char *argv[]) { >+ fprintf(stderr, "Sorry, no PAM support...\n"); >+ return -1; >+} >+ >+#endif /* USE_PAM */
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 423
: 162 |
163
|
198
|
246
|
375
|
376
|
377