From 7e82606eb98e6071e4ad650b91a75933c1358485 Mon Sep 17 00:00:00 2001 From: jbasney Date: Wed, 18 Aug 2004 19:11:34 +0000 Subject: [PATCH] merge OpenSSH 3.9p1 to trunk --- openssh/Makefile.in | 32 ++- openssh/README.platform | 8 + openssh/README.privsep | 6 +- openssh/acconfig.h | 12 + openssh/auth-krb5.c | 6 +- openssh/auth-pam.c | 204 +++++++++++++-- openssh/auth-pam.h | 1 + openssh/auth.c | 45 +--- openssh/auth.h | 4 +- openssh/auth1.c | 26 +- openssh/auth2-gss.c | 16 +- openssh/auth2-none.c | 11 +- openssh/auth2-pubkey.c | 8 +- openssh/auth2.c | 8 +- openssh/canohost.c | 38 +-- openssh/cipher.c | 52 ++-- openssh/compat.h | 4 +- openssh/configure.ac | 101 +++++++- openssh/contrib/solaris/buildpkg.sh | 85 ------- openssh/contrib/solaris/opensshd.in | 90 ------- openssh/defines.h | 7 + openssh/dns.c | 8 +- openssh/gss-serv-krb5.c | 10 +- openssh/includes.h | 13 +- openssh/kex.c | 45 +++- openssh/kex.h | 7 +- openssh/kexdhc.c | 13 +- openssh/kexdhs.c | 13 +- openssh/key.c | 6 +- openssh/log.c | 6 +- openssh/mdoc2man.awk | 10 +- openssh/misc.c | 36 +-- openssh/moduli.c | 86 ++++--- openssh/moduli.h | 23 -- openssh/monitor.c | 156 ++++++------ openssh/monitor_fdpass.c | 12 +- openssh/monitor_mm.c | 2 +- openssh/monitor_wrap.c | 41 +-- openssh/monitor_wrap.h | 8 +- openssh/openbsd-compat/getrrsetbyname.c | 4 + openssh/openbsd-compat/port-aix.c | 88 +++++-- openssh/openbsd-compat/port-aix.h | 4 + openssh/openbsd-compat/sys-queue.h | 19 +- openssh/openbsd-compat/xmmap.c | 9 +- openssh/packet.c | 53 ++-- openssh/packet.h | 4 +- openssh/progressmeter.c | 24 +- openssh/readconf.c | 48 +++- openssh/readconf.h | 14 +- openssh/readpass.h | 18 -- openssh/scard-opensc.c | 2 +- openssh/servconf.c | 89 +++++-- openssh/servconf.h | 18 +- openssh/session.c | 118 ++++++--- openssh/session.h | 10 +- openssh/ssh-agent.c | 15 +- openssh/ssh-gss.h | 50 ++-- openssh/ssh-keyscan.c | 15 +- openssh/ssh-keysign.c | 20 +- openssh/ssh-rand-helper.c | 8 - openssh/ssh.1 | 103 ++++++-- openssh/ssh.c | 321 ++++++++++++++++++------ openssh/ssh1.h | 8 +- openssh/ssh_config.5 | 75 +++++- openssh/sshconnect1.c | 18 +- openssh/sshconnect2.c | 7 +- openssh/sshd.8 | 4 +- openssh/sshd.c | 279 +++++++++++++++++--- openssh/sshd_config | 14 +- openssh/sshd_config.5 | 73 +++++- openssh/sshtty.h | 48 ---- openssh/tildexpand.h | 15 -- openssh/version.h | 6 +- 73 files changed, 1877 insertions(+), 983 deletions(-) delete mode 100755 openssh/contrib/solaris/buildpkg.sh delete mode 100755 openssh/contrib/solaris/opensshd.in delete mode 100644 openssh/moduli.h delete mode 100644 openssh/readpass.h delete mode 100644 openssh/sshtty.h delete mode 100644 openssh/tildexpand.h diff --git a/openssh/Makefile.in b/openssh/Makefile.in index b294727..bedf648 100644 --- a/openssh/Makefile.in +++ b/openssh/Makefile.in @@ -68,24 +68,25 @@ LIBSSH_OBJS=acss.o authfd.o authfile.o bufaux.o buffer.o \ compat.o compress.o crc32.o deattack.o fatal.o hostfile.o \ log.o match.o moduli.o mpaux.o nchan.o packet.o \ readpass.o rsa.o tildexpand.o ttymodes.o xmalloc.o \ - atomicio.o key.o dispatch.o kex.o mac.o uuencode.o misc.o \ - rijndael.o ssh-dss.o ssh-rsa.o dh.o kexdh.o kexgex.o \ - kexdhc.o kexgexc.o scard.o msg.o progressmeter.o dns.o \ - entropy.o scard-opensc.o kexgssc.o gss-genr.o + atomicio.o key.o dispatch.o kex.o mac.o uidswap.o uuencode.o misc.o \ + monitor_fdpass.o rijndael.o ssh-dss.o ssh-rsa.o dh.o kexdh.o \ + kexgex.o kexdhc.o kexgexc.o scard.o msg.o progressmeter.o dns.o \ + kexgssc.o \ + entropy.o scard-opensc.o gss-genr.o SSHOBJS= ssh.o readconf.o clientloop.o sshtty.o \ sshconnect.o sshconnect1.o sshconnect2.o SSHDOBJS=sshd.o auth-rhosts.o auth-passwd.o auth-rsa.o auth-rh-rsa.o \ - sshpty.o sshlogin.o servconf.o serverloop.o uidswap.o \ + sshpty.o sshlogin.o servconf.o serverloop.o \ auth.o auth1.o auth2.o auth-options.o session.o \ auth-chall.o auth2-chall.o groupaccess.o \ auth-skey.o auth-bsdauth.o auth2-hostbased.o auth2-kbdint.o \ auth2-none.o auth2-passwd.o auth2-pubkey.o \ - monitor_mm.o monitor.o monitor_wrap.o monitor_fdpass.o \ - kexdhs.o kexgexs.o kexgsss.o \ + monitor_mm.o monitor.o monitor_wrap.o kexdhs.o kexgexs.o \ + kexgsss.o gss-serv-gsi.o \ auth-krb5.o \ - auth2-gss.o gss-serv.o gss-serv-krb5.o gss-serv-gsi.o \ + auth2-gss.o gss-serv.o gss-serv-krb5.o \ loginrec.o auth-pam.o auth-shadow.o auth-sia.o md5crypt.o MANPAGES = scp.1.out ssh-add.1.out ssh-agent.1.out ssh-keygen.1.out ssh-keyscan.1.out ssh.1.out sshd.8.out sftp-server.8.out sftp.1.out ssh-rand-helper.8.out ssh-keysign.8.out sshd_config.5.out ssh_config.5.out @@ -201,11 +202,14 @@ clean: regressclean distclean: regressclean rm -f *.o *.a $(TARGETS) logintest config.cache config.log - rm -f *.out core - rm -f Makefile config.h config.status ssh_prng_cmds *~ + rm -f *.out core opensshd.init + rm -f Makefile buildpkg.sh config.h config.status ssh_prng_cmds *~ rm -rf autom4te.cache (cd openbsd-compat && $(MAKE) distclean) (cd scard && $(MAKE) distclean) + if test -d pkg ; then \ + rm -fr pkg ; \ + fi veryclean: distclean rm -f configure config.h.in *.0 @@ -400,7 +404,7 @@ tests: $(TARGETS) [ -d `pwd`/regress ] || mkdir -p `pwd`/regress; \ [ -f `pwd`/regress/Makefile ] || \ ln -s $(srcdir)/regress/Makefile `pwd`/regress/Makefile ; \ - TEST_SHELL="@TEST_MINUS_S_SH@"; \ + TEST_SHELL="@TEST_SHELL@"; \ TEST_SSH_SSH="$${BUILDDIR}/ssh"; \ TEST_SSH_SSHD="$${BUILDDIR}/sshd"; \ TEST_SSH_SSHAGENT="$${BUILDDIR}/ssh-agent"; \ @@ -432,3 +436,9 @@ regressclean: if [ -f regress/Makefile -a -r regress/Makefile ]; then \ (cd regress && $(MAKE) clean) \ fi + +package: $(CONFIGFILES) ssh_prng_cmds.out $(MANPAGES) $(TARGETS) + if [ "@MAKE_PACKAGE_SUPPORTED@" = yes ]; then \ + sh buildpkg.sh; \ + fi + diff --git a/openssh/README.platform b/openssh/README.platform index f9318b7..d07b2c3 100644 --- a/openssh/README.platform +++ b/openssh/README.platform @@ -13,6 +13,14 @@ Accounts in this state must have their passwords reset manually by the administrator. As a precaution, it is recommended that the administrative passwords be reset before upgrading from OpenSSH <3.8. + +Cygwin +------ +To build on Cygwin, OpenSSH requires the following packages: +gcc, gcc-mingw-core, mingw-runtime, binutils, make, openssl, +openssl-devel, zlib, minres, minires-devel. + + Solaris ------- Currently, sshd does not support BSM auditting. This can show up as errors diff --git a/openssh/README.privsep b/openssh/README.privsep index fcbae9a..ba8345c 100644 --- a/openssh/README.privsep +++ b/openssh/README.privsep @@ -42,9 +42,9 @@ PAM-enabled OpenSSH is known to function with privsep on Linux. It does not function on HP-UX with a trusted system configuration. -On Compaq Tru64 Unix, only the pre-authentication part of privsep is -supported. Post-authentication privsep is disabled automatically (so -you won't see the additional process mentioned below). +On Cygwin, Tru64 Unix, OpenServer, and Unicos only the pre-authentication +part of privsep is supported. Post-authentication privsep is disabled +automatically (so you won't see the additional process mentioned below). Note that for a normal interactive login with a shell, enabling privsep will require 1 additional process per login session. diff --git a/openssh/acconfig.h b/openssh/acconfig.h index fd14c1a..18013f2 100644 --- a/openssh/acconfig.h +++ b/openssh/acconfig.h @@ -104,6 +104,9 @@ /* Work around problematic Linux PAM modules handling of PAM_TTY */ #undef PAM_TTY_KLUDGE +/* Define if pam_chauthtok wants real uid set to the unpriv'ed user */ +#undef SSHPAM_CHAUTHTOK_NEEDS_RUID + /* Use PIPES instead of a socketpair() */ #undef USE_PIPES @@ -447,6 +450,12 @@ /* Define if cmsg_type is not passed correctly */ #undef BROKEN_CMSG_TYPE +/* + * Define to whatever link() returns for "not supported" if it doesn't + * return EOPNOTSUPP. + */ +#undef LINK_OPNOTSUPP_ERRNO + /* Strings used in /etc/passwd to denote locked account */ #undef LOCKED_PASSWD_STRING #undef LOCKED_PASSWD_PREFIX @@ -461,6 +470,9 @@ /* Define if your resolver libs need this for getrrsetbyname */ #undef BIND_8_COMPAT +/* Define if you have /proc/$pid/fd */ +#undef HAVE_PROC_PID + @BOTTOM@ /* ******************* Shouldn't need to edit below this line ************** */ diff --git a/openssh/auth-krb5.c b/openssh/auth-krb5.c index a728eba..a324ff1 100644 --- a/openssh/auth-krb5.c +++ b/openssh/auth-krb5.c @@ -69,6 +69,7 @@ auth_krb5_password(Authctxt *authctxt, const char *password) krb5_principal server; char ccname[40]; int tmpfd; + mode_t old_umask; #endif krb5_error_code problem; krb5_ccache ccache = NULL; @@ -147,7 +148,10 @@ auth_krb5_password(Authctxt *authctxt, const char *password) snprintf(ccname,sizeof(ccname),"FILE:/tmp/krb5cc_%d_XXXXXX",geteuid()); - if ((tmpfd = mkstemp(ccname+strlen("FILE:")))==-1) { + old_umask = umask(0177); + tmpfd = mkstemp(ccname + strlen("FILE:")); + umask(old_umask); + if (tmpfd == -1) { logit("mkstemp(): %.100s", strerror(errno)); problem = errno; goto out; diff --git a/openssh/auth-pam.c b/openssh/auth-pam.c index 9eb3174..63908a7 100644 --- a/openssh/auth-pam.c +++ b/openssh/auth-pam.c @@ -28,6 +28,22 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ +/* + * Copyright (c) 2003,2004 Damien Miller + * Copyright (c) 2003,2004 Darren Tucker + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ /* Based on $FreeBSD: src/crypto/openssh/auth2-pam-freebsd.c,v 1.11 2003/03/31 13:48:18 des Exp $ */ #include "includes.h" @@ -49,7 +65,7 @@ RCSID("$Id$"); #include "monitor_wrap.h" #include "msg.h" #include "packet.h" -#include "readpass.h" +#include "misc.h" #include "servconf.h" #include "ssh2.h" #include "xmalloc.h" @@ -93,10 +109,17 @@ static mysig_t sshpam_oldsig; static void sshpam_sigchld_handler(int sig) { + signal(SIGCHLD, SIG_DFL); if (cleanup_ctxt == NULL) return; /* handler called after PAM cleanup, shouldn't happen */ - if (waitpid(cleanup_ctxt->pam_thread, &sshpam_thread_status, 0) == -1) - return; /* couldn't wait for process */ + if (waitpid(cleanup_ctxt->pam_thread, &sshpam_thread_status, WNOHANG) + <= 0) { + /* PAM thread has not exitted, privsep slave must have */ + kill(cleanup_ctxt->pam_thread, SIGTERM); + if (waitpid(cleanup_ctxt->pam_thread, &sshpam_thread_status, 0) + <= 0) + return; /* could not wait */ + } if (WIFSIGNALED(sshpam_thread_status) && WTERMSIG(sshpam_thread_status) == SIGTERM) return; /* terminated by pthread_cancel */ @@ -162,6 +185,7 @@ static int sshpam_cred_established = 0; static int sshpam_account_status = -1; static char **sshpam_env = NULL; static Authctxt *sshpam_authctxt = NULL; +static const char *sshpam_password = NULL; /* Some PAM implementations don't implement this */ #ifndef HAVE_PAM_GETENVLIST @@ -177,8 +201,33 @@ pam_getenvlist(pam_handle_t *pamh) } #endif +/* + * Some platforms, notably Solaris, do not enforce password complexity + * rules during pam_chauthtok() if the real uid of the calling process + * is 0, on the assumption that it's being called by "passwd" run by root. + * This wraps pam_chauthtok and sets/restore the real uid so PAM will do + * the right thing. + */ +#ifdef SSHPAM_CHAUTHTOK_NEEDS_RUID +static int +sshpam_chauthtok_ruid(pam_handle_t *pamh, int flags) +{ + int result; + + if (sshpam_authctxt == NULL) + fatal("PAM: sshpam_authctxt not initialized"); + if (setreuid(sshpam_authctxt->pw->pw_uid, -1) == -1) + fatal("%s: setreuid failed: %s", __func__, strerror(errno)); + result = pam_chauthtok(pamh, flags); + if (setreuid(0, -1) == -1) + fatal("%s: setreuid failed: %s", __func__, strerror(errno)); + return result; +} +# define pam_chauthtok(a,b) (sshpam_chauthtok_ruid((a), (b))) +#endif + void -pam_password_change_required(int reqd) +sshpam_password_change_required(int reqd) { debug3("%s %d", __func__, reqd); if (sshpam_authctxt == NULL) @@ -208,7 +257,7 @@ import_environments(Buffer *b) #ifndef USE_POSIX_THREADS /* Import variables set by do_pam_account */ sshpam_account_status = buffer_get_int(b); - pam_password_change_required(buffer_get_int(b)); + sshpam_password_change_required(buffer_get_int(b)); /* Import environment from subprocess */ num_env = buffer_get_int(b); @@ -240,7 +289,7 @@ import_environments(Buffer *b) * Conversation function for authentication thread. */ static int -sshpam_thread_conv(int n, const struct pam_message **msg, +sshpam_thread_conv(int n, struct pam_message **msg, struct pam_response **resp, void *data) { Buffer buffer; @@ -251,6 +300,10 @@ sshpam_thread_conv(int n, const struct pam_message **msg, debug3("PAM: %s entering, %d messages", __func__, n); *resp = NULL; + if (data == NULL) { + error("PAM: conversation function passed a null context"); + return (PAM_CONV_ERR); + } ctxt = data; if (n <= 0 || n > PAM_MAX_NUM_MSG) return (PAM_CONV_ERR); @@ -328,15 +381,21 @@ sshpam_thread(void *ctxtp) struct pam_ctxt *ctxt = ctxtp; Buffer buffer; struct pam_conv sshpam_conv; + int flags = (options.permit_empty_passwd == 0 ? + PAM_DISALLOW_NULL_AUTHTOK : 0); #ifndef USE_POSIX_THREADS extern char **environ; char **env_from_pam; u_int i; const char *pam_user; - pam_get_item(sshpam_handle, PAM_USER, (const void **)&pam_user); - setproctitle("%s [pam]", pam_user); + pam_get_item(sshpam_handle, PAM_USER, (void **)&pam_user); environ[0] = NULL; + + if (sshpam_authctxt != NULL) { + setproctitle("%s [pam]", + sshpam_authctxt->valid ? pam_user : "unknown"); + } #endif sshpam_conv.conv = sshpam_thread_conv; @@ -350,7 +409,7 @@ sshpam_thread(void *ctxtp) (const void *)&sshpam_conv); if (sshpam_err != PAM_SUCCESS) goto auth_fail; - sshpam_err = pam_authenticate(sshpam_handle, 0); + sshpam_err = pam_authenticate(sshpam_handle, flags); if (sshpam_err != PAM_SUCCESS) goto auth_fail; @@ -362,7 +421,7 @@ sshpam_thread(void *ctxtp) PAM_CHANGE_EXPIRED_AUTHTOK); if (sshpam_err != PAM_SUCCESS) goto auth_fail; - pam_password_change_required(0); + sshpam_password_change_required(0); } } @@ -422,7 +481,7 @@ sshpam_thread_cleanup(void) } static int -sshpam_null_conv(int n, const struct pam_message **msg, +sshpam_null_conv(int n, struct pam_message **msg, struct pam_response **resp, void *data) { debug3("PAM: %s entering, %d messages", __func__, n); @@ -460,7 +519,7 @@ sshpam_init(Authctxt *authctxt) if (sshpam_handle != NULL) { /* We already have a PAM context; check if the user matches */ sshpam_err = pam_get_item(sshpam_handle, - PAM_USER, (const void **)&pam_user); + PAM_USER, (void **)&pam_user); if (sshpam_err == PAM_SUCCESS && strcmp(user, pam_user) == 0) return (0); pam_end(sshpam_handle, sshpam_err); @@ -712,7 +771,7 @@ do_pam_account(void) } if (sshpam_err == PAM_NEW_AUTHTOK_REQD) - pam_password_change_required(1); + sshpam_password_change_required(1); sshpam_account_status = 1; return (sshpam_account_status); @@ -758,7 +817,7 @@ do_pam_setcred(int init) } static int -pam_tty_conv(int n, const struct pam_message **msg, +sshpam_tty_conv(int n, struct pam_message **msg, struct pam_response **resp, void *data) { char input[PAM_MAX_MSG_SIZE]; @@ -787,7 +846,8 @@ pam_tty_conv(int n, const struct pam_message **msg, case PAM_PROMPT_ECHO_ON: fprintf(stderr, "%s\n", PAM_MSG_MEMBER(msg, i, msg)); fgets(input, sizeof input, stdin); - reply[i].resp = xstrdup(input); + if ((reply[i].resp = strdup(input)) == NULL) + goto fail; reply[i].resp_retcode = PAM_SUCCESS; break; case PAM_ERROR_MSG: @@ -811,7 +871,7 @@ pam_tty_conv(int n, const struct pam_message **msg, return (PAM_CONV_ERR); } -static struct pam_conv tty_conv = { pam_tty_conv, NULL }; +static struct pam_conv tty_conv = { sshpam_tty_conv, NULL }; /* * XXX this should be done in the authentication phase, but ssh1 doesn't @@ -835,7 +895,7 @@ do_pam_chauthtok(void) } static int -pam_store_conv(int n, const struct pam_message **msg, +sshpam_store_conv(int n, struct pam_message **msg, struct pam_response **resp, void *data) { struct pam_response *reply; @@ -877,7 +937,7 @@ pam_store_conv(int n, const struct pam_message **msg, return (PAM_CONV_ERR); } -static struct pam_conv store_conv = { pam_store_conv, NULL }; +static struct pam_conv store_conv = { sshpam_store_conv, NULL }; void do_pam_session(void) @@ -944,4 +1004,112 @@ free_pam_environment(char **env) xfree(env); } +/* + * "Blind" conversation function for password authentication. Assumes that + * echo-off prompts are for the password and stores messages for later + * display. + */ +static int +sshpam_passwd_conv(int n, struct pam_message **msg, + struct pam_response **resp, void *data) +{ + struct pam_response *reply; + int i; + size_t len; + + debug3("PAM: %s called with %d messages", __func__, n); + + *resp = NULL; + + if (n <= 0 || n > PAM_MAX_NUM_MSG) + return (PAM_CONV_ERR); + + if ((reply = malloc(n * sizeof(*reply))) == NULL) + return (PAM_CONV_ERR); + memset(reply, 0, n * sizeof(*reply)); + + for (i = 0; i < n; ++i) { + switch (PAM_MSG_MEMBER(msg, i, msg_style)) { + case PAM_PROMPT_ECHO_OFF: + if (sshpam_password == NULL) + goto fail; + if ((reply[i].resp = strdup(sshpam_password)) == NULL) + goto fail; + reply[i].resp_retcode = PAM_SUCCESS; + break; + case PAM_ERROR_MSG: + case PAM_TEXT_INFO: + len = strlen(PAM_MSG_MEMBER(msg, i, msg)); + if (len > 0) { + buffer_append(&loginmsg, + PAM_MSG_MEMBER(msg, i, msg), len); + buffer_append(&loginmsg, "\n", 1); + } + if ((reply[i].resp = strdup("")) == NULL) + goto fail; + reply[i].resp_retcode = PAM_SUCCESS; + break; + default: + goto fail; + } + } + *resp = reply; + return (PAM_SUCCESS); + + fail: + for(i = 0; i < n; i++) { + if (reply[i].resp != NULL) + xfree(reply[i].resp); + } + xfree(reply); + return (PAM_CONV_ERR); +} + +static struct pam_conv passwd_conv = { sshpam_passwd_conv, NULL }; + +/* + * Attempt password authentication via PAM + */ +int +sshpam_auth_passwd(Authctxt *authctxt, const char *password) +{ + int flags = (options.permit_empty_passwd == 0 ? + PAM_DISALLOW_NULL_AUTHTOK : 0); + static char badpw[] = "\b\n\r\177INCORRECT"; + + if (!options.use_pam || sshpam_handle == NULL) + fatal("PAM: %s called when PAM disabled or failed to " + "initialise.", __func__); + + sshpam_password = password; + sshpam_authctxt = authctxt; + + /* + * If the user logging in is invalid, or is root but is not permitted + * by PermitRootLogin, use an invalid password to prevent leaking + * information via timing (eg if the PAM config has a delay on fail). + */ + if (!authctxt->valid || (authctxt->pw->pw_uid == 0 && + options.permit_root_login != PERMIT_YES)) + sshpam_password = badpw; + + sshpam_err = pam_set_item(sshpam_handle, PAM_CONV, + (const void *)&passwd_conv); + if (sshpam_err != PAM_SUCCESS) + fatal("PAM: %s: failed to set PAM_CONV: %s", __func__, + pam_strerror(sshpam_handle, sshpam_err)); + + sshpam_err = pam_authenticate(sshpam_handle, flags); + sshpam_password = NULL; + if (sshpam_err == PAM_SUCCESS && authctxt->valid) { + debug("PAM: password authentication accepted for %.100s", + authctxt->user); + return 1; + } else { + debug("PAM: password authentication failed for %.100s: %s", + authctxt->valid ? authctxt->user : "an illegal user", + pam_strerror(sshpam_handle, sshpam_err)); + return 0; + } +} #endif /* USE_PAM */ diff --git a/openssh/auth-pam.h b/openssh/auth-pam.h index ff501f6..f756b31 100644 --- a/openssh/auth-pam.h +++ b/openssh/auth-pam.h @@ -44,5 +44,6 @@ char ** fetch_pam_child_environment(void); void free_pam_environment(char **); void sshpam_thread_cleanup(void); void sshpam_cleanup(void); +int sshpam_auth_passwd(Authctxt *, const char *); #endif /* USE_PAM */ diff --git a/openssh/auth.c b/openssh/auth.c index e1f4681..9d3dde0 100644 --- a/openssh/auth.c +++ b/openssh/auth.c @@ -23,7 +23,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: auth.c,v 1.51 2003/11/21 11:57:02 djm Exp $"); +RCSID("$OpenBSD: auth.c,v 1.56 2004/07/28 09:40:29 markus Exp $"); #ifdef HAVE_LOGIN_H #include @@ -47,7 +47,6 @@ RCSID("$OpenBSD: auth.c,v 1.51 2003/11/21 11:57:02 djm Exp $"); #include "buffer.h" #include "bufaux.h" #include "uidswap.h" -#include "tildexpand.h" #include "misc.h" #include "bufaux.h" #include "packet.h" @@ -204,31 +203,10 @@ allowed_user(struct passwd * pw) ga_free(); } -#ifdef WITH_AIXAUTHENTICATE - /* - * Don't check loginrestrictions() for root account (use - * PermitRootLogin to control logins via ssh), or if running as - * non-root user (since loginrestrictions will always fail). - */ - if ((pw->pw_uid != 0) && (geteuid() == 0)) { - char *msg; - - if (loginrestrictions(pw->pw_name, S_RLOGIN, NULL, &msg) != 0) { - int loginrestrict_errno = errno; - - if (msg && *msg) { - buffer_append(&loginmsg, msg, strlen(msg)); - aix_remove_embedded_newlines(msg); - logit("Login restricted for %s: %.100s", - pw->pw_name, msg); - } - /* Don't fail if /etc/nologin set */ - if (!(loginrestrict_errno == EPERM && - stat(_PATH_NOLOGIN, &st) == 0)) - return 0; - } - } -#endif /* WITH_AIXAUTHENTICATE */ +#ifdef CUSTOM_SYS_AUTH_ALLOWED_USER + if (!sys_auth_allowed_user(pw)) + return 0; +#endif /* We found no reason not to let this user try to log on... */ return 1; @@ -243,7 +221,7 @@ auth_log(Authctxt *authctxt, int authenticated, char *method, char *info) /* Raise logging level */ if (authenticated == 1 || !authctxt->valid || - authctxt->failures >= AUTH_FAIL_LOG || + authctxt->failures >= options.max_authtries / 2 || strcmp(method, "password") == 0) authlog = logit; @@ -255,8 +233,9 @@ auth_log(Authctxt *authctxt, int authenticated, char *method, char *info) authlog("%s %s for %s%.100s from %.200s port %d%s", authmsg, method, - authctxt->valid ? "" : "illegal user ", - (authctxt->user && authctxt->user[0]) ? authctxt->user : "", + authctxt->valid ? "" : "invalid user ", + (authctxt->user && authctxt->user[0]) ? + authctxt->user : "", get_remote_ipaddr(), get_remote_port(), info); @@ -484,7 +463,7 @@ getpwnamallow(const char *user) pw = getpwnam(user); if (pw == NULL) { - logit("Illegal user %.100s from %.100s", + logit("Invalid user %.100s from %.100s", (user && user[0]) ? user : "", get_remote_ipaddr()); #ifdef CUSTOM_FAILED_LOGIN @@ -564,8 +543,8 @@ fakepw(void) fake.pw_passwd = "$2a$06$r3.juUaHZDlIbQaO2dS9FuYxL1W9M81R1Tc92PoSNmzvpEqLkLGrK"; fake.pw_gecos = "NOUSER"; - fake.pw_uid = -1; - fake.pw_gid = -1; + fake.pw_uid = (uid_t)-1; + fake.pw_gid = (gid_t)-1; #ifdef HAVE_PW_CLASS_IN_PASSWD fake.pw_class = ""; #endif diff --git a/openssh/auth.h b/openssh/auth.h index b916fa6..bc4086b 100644 --- a/openssh/auth.h +++ b/openssh/auth.h @@ -1,4 +1,4 @@ -/* $OpenBSD: auth.h,v 1.49 2004/01/30 09:48:57 markus Exp $ */ +/* $OpenBSD: auth.h,v 1.50 2004/05/23 23:59:53 dtucker Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. @@ -187,8 +187,6 @@ void auth_debug_reset(void); struct passwd *fakepw(void); -#define AUTH_FAIL_MAX 6 -#define AUTH_FAIL_LOG (AUTH_FAIL_MAX/2) #define AUTH_FAIL_MSG "Too many authentication failures for %.100s" #define SKEY_PROMPT "\nS/Key Password: " diff --git a/openssh/auth1.c b/openssh/auth1.c index f145cf0..3f93b98 100644 --- a/openssh/auth1.c +++ b/openssh/auth1.c @@ -10,14 +10,13 @@ */ #include "includes.h" -RCSID("$OpenBSD: auth1.c,v 1.55 2003/11/08 16:02:40 jakob Exp $"); +RCSID("$OpenBSD: auth1.c,v 1.59 2004/07/28 09:40:29 markus Exp $"); #include "xmalloc.h" #include "rsa.h" #include "ssh1.h" #include "packet.h" #include "buffer.h" -#include "mpaux.h" #include "log.h" #include "servconf.h" #include "compat.h" @@ -70,10 +69,9 @@ do_authloop(Authctxt *authctxt) u_int dlen; u_int ulen; int prev, type = 0; - struct passwd *pw = authctxt->pw; debug("Attempting authentication for %s%.100s.", - authctxt->valid ? "" : "illegal user ", authctxt->user); + authctxt->valid ? "" : "invalid user ", authctxt->user); /* If the user has no password, accept authentication immediately. */ if (options.password_authentication && @@ -81,8 +79,13 @@ do_authloop(Authctxt *authctxt) (!options.kerberos_authentication || options.kerberos_or_local_passwd) && #endif PRIVSEP(auth_password(authctxt, ""))) { - auth_log(authctxt, 1, "without authentication", ""); - return; +#ifdef USE_PAM + if (options.use_pam && (PRIVSEP(do_pam_account()))) +#endif + { + auth_log(authctxt, 1, "without authentication", ""); + return; + } } /* Indicate that authentication is needed. */ @@ -233,9 +236,10 @@ do_authloop(Authctxt *authctxt) #ifdef HAVE_CYGWIN if (authenticated && - !check_nt_auth(type == SSH_CMSG_AUTH_PASSWORD, pw)) { + !check_nt_auth(type == SSH_CMSG_AUTH_PASSWORD, + authctxt->pw)) { packet_disconnect("Authentication rejected for uid %d.", - pw == NULL ? -1 : pw->pw_uid); + authctxt->pw == NULL ? -1 : authctxt->pw->pw_uid); authenticated = 0; } #else @@ -262,7 +266,7 @@ do_authloop(Authctxt *authctxt) if (authenticated) return; - if (authctxt->failures++ > AUTH_FAIL_MAX) + if (authctxt->failures++ > options.max_authtries) packet_disconnect(AUTH_FAIL_MSG, authctxt->user); packet_start(SSH_SMSG_FAILURE); @@ -298,11 +302,11 @@ do_authentication(Authctxt *authctxt) if ((authctxt->pw = PRIVSEP(getpwnamallow(user))) != NULL) authctxt->valid = 1; else { - debug("do_authentication: illegal user %s", user); + debug("do_authentication: invalid user %s", user); authctxt->pw = fakepw(); } - setproctitle("%s%s", authctxt->pw ? user : "unknown", + setproctitle("%s%s", authctxt->valid ? user : "unknown", use_privsep ? " [net]" : ""); #ifdef USE_PAM diff --git a/openssh/auth2-gss.c b/openssh/auth2-gss.c index 64ee332..8adf721 100644 --- a/openssh/auth2-gss.c +++ b/openssh/auth2-gss.c @@ -1,4 +1,4 @@ -/* $OpenBSD: auth2-gss.c,v 1.7 2003/11/21 11:57:03 djm Exp $ */ +/* $OpenBSD: auth2-gss.c,v 1.8 2004/06/21 17:36:31 avsm Exp $ */ /* * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved. @@ -70,7 +70,7 @@ userauth_external(Authctxt *authctxt) static int userauth_gssapi(Authctxt *authctxt) { - gss_OID_desc oid = {0, NULL}; + gss_OID_desc goid = {0, NULL}; Gssctxt *ctxt = NULL; int mechs; gss_OID_set supported; @@ -100,13 +100,13 @@ userauth_gssapi(Authctxt *authctxt) if (doid[0] != SSH_GSS_OIDTYPE || doid[1] != len-2) { logit("Mechanism OID received using the old encoding form"); - oid.elements = doid; - oid.length = len; + goid.elements = doid; + goid.length = len; } else { - oid.elements = doid + 2; - oid.length = len - 2; + goid.elements = doid + 2; + goid.length = len - 2; } - gss_test_oid_set_member(&ms, &oid, supported, &present); + gss_test_oid_set_member(&ms, &goid, supported, &present); } while (mechs > 0 && !present); gss_release_oid_set(&ms, &supported); @@ -116,7 +116,7 @@ userauth_gssapi(Authctxt *authctxt) return (0); } - if (GSS_ERROR(PRIVSEP(ssh_gssapi_server_ctx(&ctxt, &oid)))) { + if (GSS_ERROR(PRIVSEP(ssh_gssapi_server_ctx(&ctxt, &goid)))) { xfree(doid); return (0); } diff --git a/openssh/auth2-none.c b/openssh/auth2-none.c index c342add..2bf5b5c 100644 --- a/openssh/auth2-none.c +++ b/openssh/auth2-none.c @@ -23,7 +23,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: auth2-none.c,v 1.6 2003/08/26 09:58:43 markus Exp $"); +RCSID("$OpenBSD: auth2-none.c,v 1.7 2004/05/11 19:01:43 deraadt Exp $"); #include "auth.h" #include "xmalloc.h" @@ -46,7 +46,7 @@ auth2_read_banner(void) { struct stat st; char *banner = NULL; - off_t len, n; + size_t len, n; int fd; if ((fd = open(options.banner, O_RDONLY)) == -1) @@ -55,7 +55,12 @@ auth2_read_banner(void) close(fd); return (NULL); } - len = st.st_size; + if (st.st_size > 1*1024*1024) { + close(fd); + return (NULL); + } + + len = (size_t)st.st_size; /* truncate */ banner = xmalloc(len + 1); n = atomicio(read, fd, banner, len); close(fd); diff --git a/openssh/auth2-pubkey.c b/openssh/auth2-pubkey.c index 3063eec..9898d4a 100644 --- a/openssh/auth2-pubkey.c +++ b/openssh/auth2-pubkey.c @@ -23,7 +23,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: auth2-pubkey.c,v 1.6 2004/01/19 21:25:15 markus Exp $"); +RCSID("$OpenBSD: auth2-pubkey.c,v 1.7 2004/06/21 17:36:31 avsm Exp $"); #include "ssh2.h" #include "xmalloc.h" @@ -205,7 +205,7 @@ user_key_allowed2(struct passwd *pw, Key *key, char *file) found = key_new(key->type); while (fgets(line, sizeof(line), f)) { - char *cp, *options = NULL; + char *cp, *key_options = NULL; linenum++; /* Skip leading whitespace, empty and comment lines. */ for (cp = line; *cp == ' ' || *cp == '\t'; cp++) @@ -217,7 +217,7 @@ user_key_allowed2(struct passwd *pw, Key *key, char *file) /* no key? check if there are options for this key */ int quoted = 0; debug2("user_key_allowed: check options: '%s'", cp); - options = cp; + key_options = cp; for (; *cp && (quoted || (*cp != ' ' && *cp != '\t')); cp++) { if (*cp == '\\' && cp[1] == '"') cp++; /* Skip both */ @@ -234,7 +234,7 @@ user_key_allowed2(struct passwd *pw, Key *key, char *file) } } if (key_equal(found, key) && - auth_parse_options(pw, options, file, linenum) == 1) { + auth_parse_options(pw, key_options, file, linenum) == 1) { found_key = 1; debug("matching key found: file %s, line %lu", file, linenum); diff --git a/openssh/auth2.c b/openssh/auth2.c index 7cb74cf..e9aaad8 100644 --- a/openssh/auth2.c +++ b/openssh/auth2.c @@ -23,7 +23,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: auth2.c,v 1.104 2003/11/04 08:54:09 djm Exp $"); +RCSID("$OpenBSD: auth2.c,v 1.107 2004/07/28 09:40:29 markus Exp $"); #include "ssh2.h" #include "xmalloc.h" @@ -209,7 +209,7 @@ input_userauth_request(int type, u_int32_t seq, void *ctxt) PRIVSEP(start_pam(authctxt)); #endif } else { - logit("input_userauth_request: illegal user %s", user); + logit("input_userauth_request: invalid user %s", user); authctxt->pw = fakepw(); #ifdef USE_PAM if (options.use_pam) @@ -219,7 +219,7 @@ input_userauth_request(int type, u_int32_t seq, void *ctxt) #ifdef GSSAPI } /* endif for setting username based on GSSAPI context */ #endif - setproctitle("%s%s", authctxt->pw ? user : "unknown", + setproctitle("%s%s", authctxt->valid ? user : "unknown", use_privsep ? " [net]" : ""); authctxt->service = xstrdup(service); authctxt->style = style ? xstrdup(style) : NULL; @@ -295,7 +295,7 @@ userauth_finish(Authctxt *authctxt, int authenticated, char *method) /* now we can break out */ authctxt->success = 1; } else { - if (authctxt->failures++ > AUTH_FAIL_MAX) + if (authctxt->failures++ > options.max_authtries) packet_disconnect(AUTH_FAIL_MSG, authctxt->user); methods = authmethods_get(); packet_start(SSH2_MSG_USERAUTH_FAILURE); diff --git a/openssh/canohost.c b/openssh/canohost.c index 3c26885..465e6ea 100644 --- a/openssh/canohost.c +++ b/openssh/canohost.c @@ -12,7 +12,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: canohost.c,v 1.38 2003/09/23 20:17:11 markus Exp $"); +RCSID("$OpenBSD: canohost.c,v 1.41 2004/07/21 11:51:29 djm Exp $"); #include "packet.h" #include "xmalloc.h" @@ -28,7 +28,7 @@ static void ipv64_normalise_mapped(struct sockaddr_storage *, socklen_t *); */ static char * -get_remote_hostname(int socket, int use_dns) +get_remote_hostname(int sock, int use_dns) { struct sockaddr_storage from; int i; @@ -39,13 +39,13 @@ get_remote_hostname(int socket, int use_dns) /* Get IP address of client. */ fromlen = sizeof(from); memset(&from, 0, sizeof(from)); - if (getpeername(socket, (struct sockaddr *)&from, &fromlen) < 0) { + if (getpeername(sock, (struct sockaddr *)&from, &fromlen) < 0) { debug("getpeername failed: %.100s", strerror(errno)); cleanup_exit(255); } if (from.ss_family == AF_INET) - check_ip_options(socket, ntop); + check_ip_options(sock, ntop); ipv64_normalise_mapped(&from, &fromlen); @@ -138,7 +138,7 @@ get_remote_hostname(int socket, int use_dns) */ /* IPv4 only */ static void -check_ip_options(int socket, char *ipaddr) +check_ip_options(int sock, char *ipaddr) { #ifdef IP_OPTIONS u_char options[200]; @@ -152,7 +152,7 @@ check_ip_options(int socket, char *ipaddr) else ipproto = IPPROTO_IP; option_size = sizeof(options); - if (getsockopt(socket, ipproto, IP_OPTIONS, options, + if (getsockopt(sock, ipproto, IP_OPTIONS, options, &option_size) >= 0 && option_size != 0) { text[0] = '\0'; for (i = 0; i < option_size; i++) @@ -227,7 +227,7 @@ get_canonical_hostname(int use_dns) * The returned string must be freed. */ static char * -get_socket_address(int socket, int remote, int flags) +get_socket_address(int sock, int remote, int flags) { struct sockaddr_storage addr; socklen_t addrlen; @@ -238,11 +238,11 @@ get_socket_address(int socket, int remote, int flags) memset(&addr, 0, sizeof(addr)); if (remote) { - if (getpeername(socket, (struct sockaddr *)&addr, &addrlen) + if (getpeername(sock, (struct sockaddr *)&addr, &addrlen) < 0) return NULL; } else { - if (getsockname(socket, (struct sockaddr *)&addr, &addrlen) + if (getsockname(sock, (struct sockaddr *)&addr, &addrlen) < 0) return NULL; } @@ -261,29 +261,29 @@ get_socket_address(int socket, int remote, int flags) } char * -get_peer_ipaddr(int socket) +get_peer_ipaddr(int sock) { char *p; - if ((p = get_socket_address(socket, 1, NI_NUMERICHOST)) != NULL) + if ((p = get_socket_address(sock, 1, NI_NUMERICHOST)) != NULL) return p; return xstrdup("UNKNOWN"); } char * -get_local_ipaddr(int socket) +get_local_ipaddr(int sock) { char *p; - if ((p = get_socket_address(socket, 0, NI_NUMERICHOST)) != NULL) + if ((p = get_socket_address(sock, 0, NI_NUMERICHOST)) != NULL) return p; return xstrdup("UNKNOWN"); } char * -get_local_name(int socket) +get_local_name(int sock) { - return get_socket_address(socket, 0, NI_NAMEREQD); + return get_socket_address(sock, 0, NI_NAMEREQD); } /* @@ -382,7 +382,13 @@ get_peer_port(int sock) int get_remote_port(void) { - return get_port(0); + static int port = -1; + + /* Cache to avoid getpeername() on a dead connection */ + if (port == -1) + port = get_port(0); + + return port; } int diff --git a/openssh/cipher.c b/openssh/cipher.c index c13ff58..075a4c5 100644 --- a/openssh/cipher.c +++ b/openssh/cipher.c @@ -35,7 +35,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: cipher.c,v 1.68 2004/01/23 19:26:33 hshoexer Exp $"); +RCSID("$OpenBSD: cipher.c,v 1.71 2004/07/28 09:40:29 markus Exp $"); #include "xmalloc.h" #include "log.h" @@ -76,19 +76,19 @@ struct Cipher { u_int key_len; const EVP_CIPHER *(*evptype)(void); } ciphers[] = { - { "none", SSH_CIPHER_NONE, 8, 0, EVP_enc_null }, - { "des", SSH_CIPHER_DES, 8, 8, EVP_des_cbc }, - { "3des", SSH_CIPHER_3DES, 8, 16, evp_ssh1_3des }, - { "blowfish", SSH_CIPHER_BLOWFISH, 8, 32, evp_ssh1_bf }, - - { "3des-cbc", SSH_CIPHER_SSH2, 8, 24, EVP_des_ede3_cbc }, - { "blowfish-cbc", SSH_CIPHER_SSH2, 8, 16, EVP_bf_cbc }, - { "cast128-cbc", SSH_CIPHER_SSH2, 8, 16, EVP_cast5_cbc }, - { "arcfour", SSH_CIPHER_SSH2, 8, 16, EVP_rc4 }, + { "none", SSH_CIPHER_NONE, 8, 0, EVP_enc_null }, + { "des", SSH_CIPHER_DES, 8, 8, EVP_des_cbc }, + { "3des", SSH_CIPHER_3DES, 8, 16, evp_ssh1_3des }, + { "blowfish", SSH_CIPHER_BLOWFISH, 8, 32, evp_ssh1_bf }, + + { "3des-cbc", SSH_CIPHER_SSH2, 8, 24, EVP_des_ede3_cbc }, + { "blowfish-cbc", SSH_CIPHER_SSH2, 8, 16, EVP_bf_cbc }, + { "cast128-cbc", SSH_CIPHER_SSH2, 8, 16, EVP_cast5_cbc }, + { "arcfour", SSH_CIPHER_SSH2, 8, 16, EVP_rc4 }, #if OPENSSL_VERSION_NUMBER < 0x00907000L - { "aes128-cbc", SSH_CIPHER_SSH2, 16, 16, evp_rijndael }, - { "aes192-cbc", SSH_CIPHER_SSH2, 16, 24, evp_rijndael }, - { "aes256-cbc", SSH_CIPHER_SSH2, 16, 32, evp_rijndael }, + { "aes128-cbc", SSH_CIPHER_SSH2, 16, 16, evp_rijndael }, + { "aes192-cbc", SSH_CIPHER_SSH2, 16, 24, evp_rijndael }, + { "aes256-cbc", SSH_CIPHER_SSH2, 16, 32, evp_rijndael }, { "rijndael-cbc@lysator.liu.se", SSH_CIPHER_SSH2, 16, 32, evp_rijndael }, #else @@ -99,14 +99,14 @@ struct Cipher { SSH_CIPHER_SSH2, 16, 32, EVP_aes_256_cbc }, #endif #if OPENSSL_VERSION_NUMBER >= 0x00905000L - { "aes128-ctr", SSH_CIPHER_SSH2, 16, 16, evp_aes_128_ctr }, - { "aes192-ctr", SSH_CIPHER_SSH2, 16, 24, evp_aes_128_ctr }, - { "aes256-ctr", SSH_CIPHER_SSH2, 16, 32, evp_aes_128_ctr }, + { "aes128-ctr", SSH_CIPHER_SSH2, 16, 16, evp_aes_128_ctr }, + { "aes192-ctr", SSH_CIPHER_SSH2, 16, 24, evp_aes_128_ctr }, + { "aes256-ctr", SSH_CIPHER_SSH2, 16, 32, evp_aes_128_ctr }, #endif #if defined(EVP_CTRL_SET_ACSS_MODE) { "acss@openssh.org", SSH_CIPHER_SSH2, 16, 5, EVP_acss }, #endif - { NULL, SSH_CIPHER_ILLEGAL, 0, 0, NULL } + { NULL, SSH_CIPHER_INVALID, 0, 0, NULL } }; /*--*/ @@ -166,25 +166,25 @@ int ciphers_valid(const char *names) { Cipher *c; - char *ciphers, *cp; + char *cipher_list, *cp; char *p; if (names == NULL || strcmp(names, "") == 0) return 0; - ciphers = cp = xstrdup(names); + cipher_list = cp = xstrdup(names); for ((p = strsep(&cp, CIPHER_SEP)); p && *p != '\0'; (p = strsep(&cp, CIPHER_SEP))) { c = cipher_by_name(p); if (c == NULL || c->number != SSH_CIPHER_SSH2) { debug("bad cipher %s [%s]", p, names); - xfree(ciphers); + xfree(cipher_list); return 0; } else { debug3("cipher ok: %s [%s]", p, names); } } debug3("ciphers ok: [%s]", names); - xfree(ciphers); + xfree(cipher_list); return 1; } @@ -213,7 +213,7 @@ cipher_name(int id) void cipher_init(CipherContext *cc, Cipher *cipher, const u_char *key, u_int keylen, const u_char *iv, u_int ivlen, - int encrypt) + int do_encrypt) { static int dowarn = 1; #ifdef SSH_OLD_EVP @@ -252,10 +252,10 @@ cipher_init(CipherContext *cc, Cipher *cipher, type->key_len = keylen; } EVP_CipherInit(&cc->evp, type, (u_char *)key, (u_char *)iv, - (encrypt == CIPHER_ENCRYPT)); + (do_encrypt == CIPHER_ENCRYPT)); #else if (EVP_CipherInit(&cc->evp, type, NULL, (u_char *)iv, - (encrypt == CIPHER_ENCRYPT)) == 0) + (do_encrypt == CIPHER_ENCRYPT)) == 0) fatal("cipher_init: EVP_CipherInit failed for %s", cipher->name); klen = EVP_CIPHER_CTX_key_length(&cc->evp); @@ -302,7 +302,7 @@ cipher_cleanup(CipherContext *cc) void cipher_set_key_string(CipherContext *cc, Cipher *cipher, - const char *passphrase, int encrypt) + const char *passphrase, int do_encrypt) { MD5_CTX md; u_char digest[16]; @@ -311,7 +311,7 @@ cipher_set_key_string(CipherContext *cc, Cipher *cipher, MD5_Update(&md, (const u_char *)passphrase, strlen(passphrase)); MD5_Final(digest, &md); - cipher_init(cc, cipher, digest, 16, NULL, 0, encrypt); + cipher_init(cc, cipher, digest, 16, NULL, 0, do_encrypt); memset(digest, 0, sizeof(digest)); memset(&md, 0, sizeof(md)); diff --git a/openssh/compat.h b/openssh/compat.h index 99ae7ab..682e1d6 100644 --- a/openssh/compat.h +++ b/openssh/compat.h @@ -1,4 +1,4 @@ -/* $OpenBSD: compat.h,v 1.37 2003/11/02 11:01:03 markus Exp $ */ +/* $OpenBSD: compat.h,v 1.38 2004/07/11 17:48:47 deraadt Exp $ */ /* * Copyright (c) 1999, 2000, 2001 Markus Friedl. All rights reserved. @@ -27,7 +27,7 @@ #ifndef COMPAT_H #define COMPAT_H -#define SSH_PROTO_UNKNOWN 0x00 +#define SSH_PROTO_UNKNOWN 0x00 #define SSH_PROTO_1 0x01 #define SSH_PROTO_1_PREFERRED 0x02 #define SSH_PROTO_2 0x04 diff --git a/openssh/configure.ac b/openssh/configure.ac index d22c117..6f712b6 100644 --- a/openssh/configure.ac +++ b/openssh/configure.ac @@ -28,6 +28,8 @@ AC_PROG_CPP AC_PROG_RANLIB AC_PROG_INSTALL AC_PATH_PROG(AR, ar) +AC_PATH_PROG(CAT, cat) +AC_PATH_PROG(KILL, kill) AC_PATH_PROGS(PERL, perl5 perl) AC_PATH_PROG(SED, sed) AC_SUBST(PERL) @@ -37,6 +39,14 @@ AC_PATH_PROG(TEST_MINUS_S_SH, bash) AC_PATH_PROG(TEST_MINUS_S_SH, ksh) AC_PATH_PROG(TEST_MINUS_S_SH, sh) AC_PATH_PROG(SH, sh) +AC_SUBST(TEST_SHELL,sh) + +dnl for buildpkg.sh +AC_PATH_PROG(PATH_GROUPADD_PROG, groupadd, groupadd, + [/usr/sbin${PATH_SEPARATOR}/etc]) +AC_PATH_PROG(PATH_USERADD_PROG, useradd, useradd, + [/usr/sbin${PATH_SEPARATOR}/etc]) +AC_CHECK_PROG(MAKE_PACKAGE_SUPPORTED, pkgmk, yes, no) # System features AC_SYS_LARGEFILE @@ -235,6 +245,7 @@ case "$host" in AC_DEFINE(PAM_TTY_KLUDGE) AC_DEFINE(LOCKED_PASSWD_PREFIX, "!") AC_DEFINE(SPT_TYPE,SPT_REUSEARGV) + AC_DEFINE(LINK_OPNOTSUPP_ERRNO, EPERM) inet6_default_4in6=yes case `uname -r` in 1.*|2.0.*) @@ -278,6 +289,7 @@ mips-sony-bsd|mips-sony-newsos4) AC_DEFINE(LOGIN_NEEDS_UTMPX) AC_DEFINE(LOGIN_NEEDS_TERM) AC_DEFINE(PAM_TTY_KLUDGE) + AC_DEFINE(SSHPAM_CHAUTHTOK_NEEDS_RUID) AC_DEFINE(LOCKED_PASSWD_STRING, "*LK*") # Pushing STREAMS modules will cause sshd to acquire a controlling tty. AC_DEFINE(SSHD_ACQUIRES_CTTY) @@ -357,6 +369,7 @@ mips-sony-bsd|mips-sony-newsos4) AC_CHECK_FUNCS(getluid setluid) MANTYPE=man do_sco3_extra_lib_check=yes + TEST_SHELL=ksh ;; *-*-sco3.2v5*) if test -z "$GCC"; then @@ -372,8 +385,10 @@ mips-sony-bsd|mips-sony-newsos4) AC_DEFINE(BROKEN_SETREUID) AC_DEFINE(BROKEN_SETREGID) AC_DEFINE(WITH_ABBREV_NO_TTY) + AC_DEFINE(BROKEN_UPDWTMPX) AC_CHECK_FUNCS(getluid setluid) MANTYPE=man + TEST_SHELL=ksh ;; *-*-unicosmk*) AC_DEFINE(NO_SSH_LASTLOG) @@ -494,16 +509,16 @@ int main(){exit(0);} ) # Checks for header files. -AC_CHECK_HEADERS(bstring.h crypt.h endian.h features.h floatingpoint.h \ - getopt.h glob.h ia.h lastlog.h limits.h login.h \ - login_cap.h maillock.h netdb.h netgroup.h \ +AC_CHECK_HEADERS(bstring.h crypt.h dirent.h endian.h features.h \ + floatingpoint.h getopt.h glob.h ia.h lastlog.h limits.h login.h \ + login_cap.h maillock.h ndir.h netdb.h netgroup.h \ netinet/in_systm.h pam/pam_appl.h paths.h pty.h readpassphrase.h \ rpc/types.h security/pam_appl.h shadow.h stddef.h stdint.h \ - strings.h sys/strtio.h sys/audit.h sys/bitypes.h sys/bsdtty.h \ - sys/cdefs.h sys/mman.h sys/prctl.h sys/pstat.h sys/ptms.h \ - sys/select.h sys/stat.h sys/stream.h sys/stropts.h \ - sys/sysmacros.h sys/time.h sys/timers.h sys/un.h time.h tmpdir.h \ - ttyent.h usersec.h util.h utime.h utmp.h utmpx.h vis.h) + strings.h sys/dir.h sys/strtio.h sys/audit.h sys/bitypes.h \ + sys/bsdtty.h sys/cdefs.h sys/mman.h sys/ndir.h sys/prctl.h \ + sys/pstat.h sys/ptms.h sys/select.h sys/stat.h sys/stream.h \ + sys/stropts.h sys/sysmacros.h sys/time.h sys/timers.h sys/un.h \ + time.h tmpdir.h ttyent.h usersec.h util.h utime.h utmp.h utmpx.h vis.h) # Checks for libraries. AC_CHECK_FUNC(yp_match, , AC_CHECK_LIB(nsl, yp_match)) @@ -854,6 +869,14 @@ fi AC_SUBST(INSTALL_GSISSH) # End Globus/GSI section +AC_MSG_CHECKING([for /proc/pid/fd directory]) +if test -d "/proc/$$/fd" ; then + AC_DEFINE(HAVE_PROC_PID) + AC_MSG_RESULT(yes) +else + AC_MSG_RESULT(no) +fi + # Check whether user wants S/Key support SKEY_MSG="no" AC_ARG_WITH(skey, @@ -955,9 +978,9 @@ AC_ARG_WITH(tcp-wrappers, dnl Checks for library functions. Please keep in alphabetical order AC_CHECK_FUNCS(\ - arc4random __b64_ntop b64_ntop __b64_pton b64_pton \ - bcopy bindresvport_sa clock fchmod fchown freeaddrinfo futimes \ - getaddrinfo getcwd getgrouplist getnameinfo getopt \ + arc4random __b64_ntop b64_ntop __b64_pton b64_pton bcopy \ + bindresvport_sa clock closefrom dirfd fchmod fchown freeaddrinfo \ + futimes getaddrinfo getcwd getgrouplist getnameinfo getopt \ getpeereid _getpty getrlimit getttyent glob inet_aton \ inet_ntoa inet_ntop innetgr login_getcapbool md5_crypt memmove \ mkdtemp mmap ngetaddrinfo nsleep ogetaddrinfo openlog_r openpty \ @@ -997,6 +1020,8 @@ AC_CHECK_DECL(tcsendbreak, [#include ] ) +AC_CHECK_DECLS(h_errno, , ,[#include ]) + AC_CHECK_FUNCS(setresuid, [ dnl Some platorms have setresuid that isn't implemented, test for this AC_MSG_CHECKING(if setresuid seems to work) @@ -1061,6 +1086,20 @@ int main(void){char b[5];snprintf(b,5,"123456789");exit(b[4]!='\0');} ) fi +# Check for missing getpeereid (or equiv) support +NO_PEERCHECK="" +if test "x$ac_cv_func_getpeereid" != "xyes" ; then + AC_MSG_CHECKING([whether system supports SO_PEERCRED getsockopt]) + AC_TRY_COMPILE( + [#include + #include ], + [int i = SO_PEERCRED;], + [AC_MSG_RESULT(yes)], + [AC_MSG_RESULT(no) + NO_PEERCHECK=1] + ) +fi + dnl see whether mkstemp() requires XXXXXX if test "x$ac_cv_func_mkdtemp" = "xyes" ; then AC_MSG_CHECKING([for (overly) strict mkstemp]) @@ -2293,6 +2332,25 @@ AC_SEARCH_LIBS(getrrsetbyname, resolv, # Needed by our getrrsetbyname() AC_SEARCH_LIBS(res_query, resolv) AC_SEARCH_LIBS(dn_expand, resolv) + AC_MSG_CHECKING(if res_query will link) + AC_TRY_LINK_FUNC(res_query, AC_MSG_RESULT(yes), + [AC_MSG_RESULT(no) + saved_LIBS="$LIBS" + LIBS="$LIBS -lresolv" + AC_MSG_CHECKING(for res_query in -lresolv) + AC_LINK_IFELSE([ +#include +int main() +{ + res_query (0, 0, 0, 0, 0); + return 0; +} + ], + [LIBS="$LIBS -lresolv" + AC_MSG_RESULT(yes)], + [LIBS="$saved_LIBS" + AC_MSG_RESULT(no)]) + ]) AC_CHECK_FUNCS(_getshort _getlong) AC_CHECK_MEMBER(HEADER.ad, [AC_DEFINE(HAVE_HEADER_AD)],, @@ -2346,7 +2404,10 @@ AC_ARG_WITH(kerberos5, [ char *tmp = heimdal_version; ], [ AC_MSG_RESULT(yes) AC_DEFINE(HEIMDAL) - K5LIBS="-lkrb5 -ldes -lcom_err -lasn1 -lroken" + K5LIBS="-lkrb5 -ldes" + K5LIBS="$K5LIBS -lcom_err -lasn1" + AC_CHECK_LIB(roken, net_write, + [K5LIBS="$K5LIBS -lroken"]) ], [ AC_MSG_RESULT(no) K5LIBS="-lkrb5 -lk5crypto -lcom_err" @@ -3055,7 +3116,7 @@ if test "$ac_cv_lib_pam_pam_set_item" = yes ; then fi AC_EXEEXT -AC_CONFIG_FILES([Makefile openbsd-compat/Makefile scard/Makefile ssh_prng_cmds]) +AC_CONFIG_FILES([Makefile buildpkg.sh opensshd.init openbsd-compat/Makefile scard/Makefile ssh_prng_cmds]) AC_OUTPUT # Print summary of options @@ -3120,6 +3181,10 @@ echo " Libraries: ${LIBWRAP} ${LIBPAM} ${LIBS}" echo "" +if test "x$MAKE_PACKAGE_SUPPORTED" = "xyes" ; then + echo "SVR4 style packages are supported with \"make package\"\n" +fi + if test "x$PAM_MSG" = "xyes" ; then echo "PAM is enabled. You may need to install a PAM control file " echo "for sshd, otherwise password authentication may fail. " @@ -3136,3 +3201,13 @@ if test ! -z "$RAND_HELPER_CMDHASH" ; then echo "" fi +if test ! -z "$NO_PEERCHECK" ; then + echo "WARNING: the operating system that you are using does not " + echo "appear to support either the getpeereid() API nor the " + echo "SO_PEERCRED getsockopt() option. These facilities are used to " + echo "enforce security checks to prevent unauthorised connections to " + echo "ssh-agent. Their absence increases the risk that a malicious " + echo "user can connect to your agent. " + echo "" +fi + diff --git a/openssh/contrib/solaris/buildpkg.sh b/openssh/contrib/solaris/buildpkg.sh deleted file mode 100755 index 05abb22..0000000 --- a/openssh/contrib/solaris/buildpkg.sh +++ /dev/null @@ -1,85 +0,0 @@ -#!/bin/sh -# -# Fake Root Solaris Build System - Prototype -# -# The following code has been provide under Public Domain License. I really -# don't care what you use it for. Just as long as you don't complain to me -# nor my employer if you break it. - Ben Lindstrom (mouring@eviladmin.org) -# -umask 022 -PKGNAME=OpenSSH - -## Extract common info requires for the 'info' part of the package. -VERSION=`tail -1 ../../version.h | sed -e 's/.*_\([0-9]\)/\1/g' | sed 's/\"$//'` -ARCH=`uname -p` - -## Start by faking root install -echo "Faking root install..." -START=`pwd` -FAKE_ROOT=$START/package -mkdir $FAKE_ROOT -cd ../.. -make install-nokeys DESTDIR=$FAKE_ROOT - -## Fill in some details, like prefix and sysconfdir -ETCDIR=`grep "^sysconfdir=" Makefile | sed 's/sysconfdir=//'` -PREFIX=`grep "^prefix=" Makefile | cut -d = -f 2` -PIDDIR=`grep "^piddir=" Makefile | cut -d = -f 2` -cd $FAKE_ROOT - -## Setup our run level stuff while we are at it. -mkdir -p $FAKE_ROOT/etc/init.d -mkdir -p $FAKE_ROOT/etc/rcS.d -mkdir -p $FAKE_ROOT/etc/rc0.d -mkdir -p $FAKE_ROOT/etc/rc1.d -mkdir -p $FAKE_ROOT/etc/rc2.d - - -## setup our initscript correctly -sed -e "s#%%configDir%%#$ETCDIR#g" \ - -e "s#%%openSSHDir%%#$PREFIX#g" \ - -e "s#%%pidDir%%#$PIDDIR#g" \ - ../opensshd.in > $FAKE_ROOT/etc/init.d/opensshd -chmod 711 $FAKE_ROOT/etc/init.d/opensshd - -ln -s ../init.d/opensshd $FAKE_ROOT/etc/rcS.d/K30opensshd -ln -s ../init.d/opensshd $FAKE_ROOT/etc/rc0.d/K30opensshd -ln -s ../init.d/opensshd $FAKE_ROOT/etc/rc1.d/K30opensshd -ln -s ../init.d/opensshd $FAKE_ROOT/etc/rc2.d/S98opensshd - - -## Ok, this is outright wrong, but it will work. I'm tired of pkgmk -## whining. -for i in *; do - PROTO_ARGS="$PROTO_ARGS $i=/$i"; -done - -## Build info file -echo "Building pkginfo file..." -cat > pkginfo << _EOF -PKG=$PKGNAME -NAME=OpenSSH Portable for Solaris -DESC="Secure Shell remote access utility; replaces telnet and rlogin/rsh." -VENDOR="OpenSSH Portable Team - http://www.openssh.com/portable.html" -BASEDIR=$FAKE_ROOT -ARCH=$ARCH -VERSION=$VERSION -CATEGORY=Security -BASEDIR=/ -_EOF - -## Next Build our prototype -echo "Building prototype file..." -find . | egrep -v "prototype|pkginfo" | sort | pkgproto $PROTO_ARGS | \ - awk ' - BEGIN { print "i pkginfo" } - { $5="root"; $6="sys"; } - { print; }' > prototype - -## Step back a directory and now build the package. -echo "Building package.." -cd .. -pkgmk -d . -f $FAKE_ROOT/prototype -o -rm -rf $FAKE_ROOT -echo | pkgtrans -os . $PKGNAME-$ARCH-$VERSION.pkg -rm -rf $PKGNAME diff --git a/openssh/contrib/solaris/opensshd.in b/openssh/contrib/solaris/opensshd.in deleted file mode 100755 index 212254d..0000000 --- a/openssh/contrib/solaris/opensshd.in +++ /dev/null @@ -1,90 +0,0 @@ -#!/sbin/sh -# Donated code that was put under PD license. -# -# Stripped PRNGd out of it for the time being. - -AWK=/usr/bin/awk -CAT=/usr/bin/cat -KILL=/usr/bin/kill -PS=/usr/bin/ps -XARGS=/usr/bin/xargs - -prefix=%%openSSHDir%% -etcdir=%%configDir%% -piddir=%%pidDir%% - -SSHD=$prefix/sbin/sshd -PIDFILE=$piddir/sshd.pid -SSH_KEYGEN=$prefix/bin/ssh-keygen -HOST_KEY_RSA1=$etcdir/ssh_host_key -HOST_KEY_DSA=$etcdir/ssh_host_dsa_key -HOST_KEY_RSA=$etcdir/ssh_host_rsa_key - -killproc() { - _procname=$1 - _signal=$2 - ${PS} -u root | ${AWK} '/'"$_procname"'$/ {print $1}' | ${XARGS} ${KILL} -} - - -checkkeys() { - if [ ! -f $HOST_KEY_RSA1 ]; then - ${SSH_KEYGEN} -t rsa1 -f ${HOST_KEY_RSA1} -N "" - fi - if [ ! -f $HOST_KEY_DSA ]; then - ${SSH_KEYGEN} -t dsa -f ${HOST_KEY_DSA} -N "" - fi - if [ ! -f $HOST_KEY_RSA ]; then - ${SSH_KEYGEN} -t rsa -f ${HOST_KEY_RSA} -N "" - fi -} - -stop_service() { - if [ -r $PIDFILE -a ! -z ${PIDFILE} ]; then - PID=`${CAT} ${PIDFILE}` - fi - if [ ${PID:=0} -gt 1 -a ! "X$PID" = "X " ]; then - ${KILL} ${PID} - else - echo "Unable to read PID file, killing using alternate method" - killproc sshd TERM - fi -} - -start_service() { - # XXX We really should check if the service is already going, but - # XXX we will opt out at this time. - Bal - - # Check to see if we have keys that need to be made - checkkeys - - # Start SSHD - echo "starting $SSHD... \c" ; $SSHD - - sshd_rc=$? - if [ $sshd_rc -ne 0 ]; then - echo "$0: Error ${sshd_rc} starting ${SSHD}... bailing." - exit $sshd_rc - fi - echo done. -} - -case $1 in - -'start') - start_service - ;; - -'stop') - stop_service - ;; - -'restart') - stop_service - start_service - ;; - -*) - echo "$0: usage: $0 {start|stop|restart}" - ;; -esac diff --git a/openssh/defines.h b/openssh/defines.h index 889b918..b21235f 100644 --- a/openssh/defines.h +++ b/openssh/defines.h @@ -424,6 +424,10 @@ struct winsize { # define __attribute__(x) #endif /* !defined(__GNUC__) || (__GNUC__ < 2) */ +#ifndef __dead +# define __dead __attribute__((noreturn)) +#endif + /* *-*-nto-qnx doesn't define this macro in the system headers */ #ifdef MISSING_HOWMANY # define howmany(x,y) (((x)+((y)-1))/(y)) @@ -462,6 +466,9 @@ struct winsize { (struct cmsghdr *)NULL) #endif /* CMSG_FIRSTHDR */ +#ifndef offsetof +# define offsetof(type, member) ((size_t) &((type *)0)->member) +#endif /* Function replacement / compatibility hacks */ diff --git a/openssh/dns.c b/openssh/dns.c index ad634f1..140ab60 100644 --- a/openssh/dns.c +++ b/openssh/dns.c @@ -1,4 +1,4 @@ -/* $OpenBSD: dns.c,v 1.9 2003/11/21 11:57:03 djm Exp $ */ +/* $OpenBSD: dns.c,v 1.10 2004/06/21 17:36:31 avsm Exp $ */ /* * Copyright (c) 2003 Wesley Griffin. All rights reserved. @@ -43,7 +43,7 @@ #include "uuencode.h" extern char *__progname; -RCSID("$OpenBSD: dns.c,v 1.9 2003/11/21 11:57:03 djm Exp $"); +RCSID("$OpenBSD: dns.c,v 1.10 2004/06/21 17:36:31 avsm Exp $"); #ifndef LWRES static const char *errset_text[] = { @@ -56,9 +56,9 @@ static const char *errset_text[] = { }; static const char * -dns_result_totext(unsigned int error) +dns_result_totext(unsigned int res) { - switch (error) { + switch (res) { case ERRSET_SUCCESS: return errset_text[ERRSET_SUCCESS]; case ERRSET_NOMEMORY: diff --git a/openssh/gss-serv-krb5.c b/openssh/gss-serv-krb5.c index 485ecd6..24929dc 100644 --- a/openssh/gss-serv-krb5.c +++ b/openssh/gss-serv-krb5.c @@ -1,4 +1,4 @@ -/* $OpenBSD: gss-serv-krb5.c,v 1.2 2003/11/21 11:57:03 djm Exp $ */ +/* $OpenBSD: gss-serv-krb5.c,v 1.3 2004/07/21 10:36:23 djm Exp $ */ /* * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved. @@ -77,7 +77,7 @@ ssh_gssapi_mech gssapi_kerberos_mech_old = { /* Initialise the krb5 library, for the stuff that GSSAPI won't do */ static int -ssh_gssapi_krb5_init() +ssh_gssapi_krb5_init(void) { krb5_error_code problem; @@ -188,11 +188,15 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_client *client) { int tmpfd; char ccname[40]; + mode_t old_umask; snprintf(ccname, sizeof(ccname), "FILE:/tmp/krb5cc_%d_XXXXXX", geteuid()); - if ((tmpfd = mkstemp(ccname + strlen("FILE:"))) == -1) { + old_umask = umask(0177); + tmpfd = mkstemp(ccname + strlen("FILE:")); + umask(old_umask); + if (tmpfd == -1) { logit("mkstemp(): %.100s", strerror(errno)); problem = errno; return; diff --git a/openssh/includes.h b/openssh/includes.h index ca943c7..3a6b4c3 100644 --- a/openssh/includes.h +++ b/openssh/includes.h @@ -1,4 +1,4 @@ -/* $OpenBSD: includes.h,v 1.17 2002/01/26 16:44:22 stevesk Exp $ */ +/* $OpenBSD: includes.h,v 1.18 2004/06/13 15:03:02 djm Exp $ */ /* * Author: Tatu Ylonen @@ -33,6 +33,7 @@ static /**/const char *const rcsid[] = { (char *)rcsid, "\100(#)" msg } #include #include #include +#include #ifdef HAVE_LIMITS_H # include /* For PATH_MAX */ @@ -180,6 +181,16 @@ static /**/const char *const rcsid[] = { (char *)rcsid, "\100(#)" msg } # include #endif +/* + * On HP-UX 11.11, shadow.h and prot.h provide conflicting declarations + * of getspnam when _INCLUDE__STDC__ is defined, so we unset it here. + */ +#ifdef __hpux +# ifdef _INCLUDE__STDC__ +# undef _INCLUDE__STDC__ +# endif +#endif + #include /* For OPENSSL_VERSION_NUMBER */ #include "defines.h" diff --git a/openssh/kex.c b/openssh/kex.c index 183044c..5a764a9 100644 --- a/openssh/kex.c +++ b/openssh/kex.c @@ -23,7 +23,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: kex.c,v 1.56 2003/11/21 11:57:03 djm Exp $"); +RCSID("$OpenBSD: kex.c,v 1.60 2004/06/21 17:36:31 avsm Exp $"); #include @@ -152,7 +152,7 @@ kex_finish(Kex *kex) void kex_send_kexinit(Kex *kex) { - u_int32_t rand = 0; + u_int32_t rnd = 0; u_char *cookie; int i; @@ -172,9 +172,9 @@ kex_send_kexinit(Kex *kex) cookie = buffer_ptr(&kex->my); for (i = 0; i < KEX_COOKIE_LEN; i++) { if (i % 4 == 0) - rand = arc4random(); - cookie[i] = rand; - rand >>= 8; + rnd = arc4random(); + cookie[i] = rnd; + rnd >>= 8; } packet_start(SSH2_MSG_KEXINIT); packet_put_raw(buffer_ptr(&kex->my), buffer_len(&kex->my)); @@ -297,6 +297,8 @@ choose_kex(Kex *k, char *client, char *server) fatal("no kex alg"); if (strcmp(k->name, KEX_DH1) == 0) { k->kex_type = KEX_DH_GRP1_SHA1; + } else if (strcmp(k->name, KEX_DH14) == 0) { + k->kex_type = KEX_DH_GRP14_SHA1; } else if (strcmp(k->name, KEX_DHGEX) == 0) { k->kex_type = KEX_DH_GEX_SHA1; #ifdef GSSAPI @@ -487,6 +489,39 @@ kex_get_newkeys(int mode) return ret; } +void +derive_ssh1_session_id(BIGNUM *host_modulus, BIGNUM *server_modulus, + u_int8_t cookie[8], u_int8_t id[16]) +{ + const EVP_MD *evp_md = EVP_md5(); + EVP_MD_CTX md; + u_int8_t nbuf[2048], obuf[EVP_MAX_MD_SIZE]; + int len; + + EVP_DigestInit(&md, evp_md); + + len = BN_num_bytes(host_modulus); + if (len < (512 / 8) || len > sizeof(nbuf)) + fatal("%s: bad host modulus (len %d)", __func__, len); + BN_bn2bin(host_modulus, nbuf); + EVP_DigestUpdate(&md, nbuf, len); + + len = BN_num_bytes(server_modulus); + if (len < (512 / 8) || len > sizeof(nbuf)) + fatal("%s: bad server modulus (len %d)", __func__, len); + BN_bn2bin(server_modulus, nbuf); + EVP_DigestUpdate(&md, nbuf, len); + + EVP_DigestUpdate(&md, cookie, 8); + + EVP_DigestFinal(&md, obuf, NULL); + memcpy(id, obuf, 16); + + memset(nbuf, 0, sizeof(nbuf)); + memset(obuf, 0, sizeof(obuf)); + memset(&md, 0, sizeof(md)); +} + #if defined(DEBUG_KEX) || defined(DEBUG_KEXDH) void dump_digest(char *msg, u_char *digest, int len) diff --git a/openssh/kex.h b/openssh/kex.h index 50b8659..da49f6b 100644 --- a/openssh/kex.h +++ b/openssh/kex.h @@ -1,4 +1,4 @@ -/* $OpenBSD: kex.h,v 1.33 2003/02/16 17:09:57 markus Exp $ */ +/* $OpenBSD: kex.h,v 1.35 2004/06/13 12:53:24 djm Exp $ */ /* * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. @@ -32,6 +32,7 @@ #include "key.h" #define KEX_DH1 "diffie-hellman-group1-sha1" +#define KEX_DH14 "diffie-hellman-group14-sha1" #define KEX_DHGEX "diffie-hellman-group-exchange-sha1" enum kex_init_proposals { @@ -56,6 +57,7 @@ enum kex_modes { enum kex_exchange { KEX_DH_GRP1_SHA1, + KEX_DH_GRP14_SHA1, KEX_DH_GEX_SHA1, KEX_GSS_GRP1_SHA1, KEX_MAX @@ -148,6 +150,9 @@ u_char * kexgex_hash(char *, char *, char *, int, char *, int, u_char *, int, int, int, int, BIGNUM *, BIGNUM *, BIGNUM *, BIGNUM *, BIGNUM *); +void +derive_ssh1_session_id(BIGNUM *, BIGNUM *, u_int8_t[8], u_int8_t[16]); + #if defined(DEBUG_KEX) || defined(DEBUG_KEXDH) void dump_digest(char *, u_char *, int); #endif diff --git a/openssh/kexdhc.c b/openssh/kexdhc.c index fe6dc53..f48bd46 100644 --- a/openssh/kexdhc.c +++ b/openssh/kexdhc.c @@ -23,7 +23,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: kexdhc.c,v 1.1 2003/02/16 17:09:57 markus Exp $"); +RCSID("$OpenBSD: kexdhc.c,v 1.2 2004/06/13 12:53:24 djm Exp $"); #include "xmalloc.h" #include "key.h" @@ -44,7 +44,16 @@ kexdh_client(Kex *kex) u_int klen, kout, slen, sbloblen; /* generate and send 'e', client DH public key */ - dh = dh_new_group1(); + switch (kex->kex_type) { + case KEX_DH_GRP1_SHA1: + dh = dh_new_group1(); + break; + case KEX_DH_GRP14_SHA1: + dh = dh_new_group14(); + break; + default: + fatal("%s: Unexpected KEX type %d", __func__, kex->kex_type); + } dh_gen_key(dh, kex->we_need * 8); packet_start(SSH2_MSG_KEXDH_INIT); packet_put_bignum2(dh->pub_key); diff --git a/openssh/kexdhs.c b/openssh/kexdhs.c index f04bce8..225e655 100644 --- a/openssh/kexdhs.c +++ b/openssh/kexdhs.c @@ -23,7 +23,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: kexdhs.c,v 1.1 2003/02/16 17:09:57 markus Exp $"); +RCSID("$OpenBSD: kexdhs.c,v 1.2 2004/06/13 12:53:24 djm Exp $"); #include "xmalloc.h" #include "key.h" @@ -45,7 +45,16 @@ kexdh_server(Kex *kex) u_int slen; /* generate server DH public key */ - dh = dh_new_group1(); + switch (kex->kex_type) { + case KEX_DH_GRP1_SHA1: + dh = dh_new_group1(); + break; + case KEX_DH_GRP14_SHA1: + dh = dh_new_group14(); + break; + default: + fatal("%s: Unexpected KEX type %d", __func__, kex->kex_type); + } dh_gen_key(dh, kex->we_need * 8); debug("expecting SSH2_MSG_KEXDH_INIT"); diff --git a/openssh/key.c b/openssh/key.c index f5fe582..2cf75ce 100644 --- a/openssh/key.c +++ b/openssh/key.c @@ -32,7 +32,7 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "includes.h" -RCSID("$OpenBSD: key.c,v 1.55 2003/11/10 16:23:41 jakob Exp $"); +RCSID("$OpenBSD: key.c,v 1.56 2004/07/28 09:40:29 markus Exp $"); #include @@ -784,7 +784,7 @@ key_sign( return ssh_rsa_sign(key, sigp, lenp, data, datalen); break; default: - error("key_sign: illegal key type %d", key->type); + error("key_sign: invalid key type %d", key->type); return -1; break; } @@ -811,7 +811,7 @@ key_verify( return ssh_rsa_verify(key, signature, signaturelen, data, datalen); break; default: - error("key_verify: illegal key type %d", key->type); + error("key_verify: invalid key type %d", key->type); return -1; break; } diff --git a/openssh/log.c b/openssh/log.c index 0c4d512..5d8625d 100644 --- a/openssh/log.c +++ b/openssh/log.c @@ -51,6 +51,9 @@ static char *argv0; extern char *__progname; +#define LOG_SYSLOG_VIS (VIS_CSTYLE|VIS_NL|VIS_TAB|VIS_OCTAL) +#define LOG_STDERR_VIS (VIS_SAFE|VIS_OCTAL) + /* textual representation of log-facilities/levels */ static struct { @@ -316,7 +319,8 @@ do_log(LogLevel level, const char *fmt, va_list args) } else { vsnprintf(msgbuf, sizeof(msgbuf), fmt, args); } - strnvis(fmtbuf, msgbuf, sizeof(fmtbuf), VIS_SAFE|VIS_OCTAL); + strnvis(fmtbuf, msgbuf, sizeof(fmtbuf), + log_on_stderr ? LOG_STDERR_VIS : LOG_SYSLOG_VIS); if (log_on_stderr) { snprintf(msgbuf, sizeof msgbuf, "%s\r\n", fmtbuf); write(STDERR_FILENO, msgbuf, strlen(msgbuf)); diff --git a/openssh/mdoc2man.awk b/openssh/mdoc2man.awk index 9135af0..4e72cdc 100644 --- a/openssh/mdoc2man.awk +++ b/openssh/mdoc2man.awk @@ -32,6 +32,7 @@ BEGIN { extopt=0 literal=0 prenl=0 + breakw=0 line="" } @@ -298,6 +299,13 @@ function add(str) { w=nwords } else if(match(words[w],"^El$")) { optlist=oldoptlist + } else if(match(words[w],"^Bk$")) { + if(match(words[w+1],"-words")) { + w++ + breakw=1 + } + } else if(match(words[w],"^Ek$")) { + breakw=0 } else if(match(words[w],"^It$")&&optlist) { if(optlist==1) add(".IP \\(bu") @@ -306,7 +314,7 @@ function add(str) { else if(optlist==3) { add(".TP") prenl++ - if(match(words[w+1],"^Pa|Ev$")) { + if(match(words[w+1],"^Pa$|^Ev$")) { add(".B") w++ } diff --git a/openssh/misc.c b/openssh/misc.c index 36e5057..bba0382 100644 --- a/openssh/misc.c +++ b/openssh/misc.c @@ -23,7 +23,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: misc.c,v 1.23 2003/10/28 09:08:06 markus Exp $"); +RCSID("$OpenBSD: misc.c,v 1.25 2004/08/11 21:43:05 avsm Exp $"); #include "misc.h" #include "log.h" @@ -46,7 +46,7 @@ chop(char *s) } /* set/unset filedescriptor to non-blocking */ -void +int set_nonblock(int fd) { int val; @@ -54,20 +54,23 @@ set_nonblock(int fd) val = fcntl(fd, F_GETFL, 0); if (val < 0) { error("fcntl(%d, F_GETFL, 0): %s", fd, strerror(errno)); - return; + return (-1); } if (val & O_NONBLOCK) { - debug2("fd %d is O_NONBLOCK", fd); - return; + debug3("fd %d is O_NONBLOCK", fd); + return (0); } debug2("fd %d setting O_NONBLOCK", fd); val |= O_NONBLOCK; - if (fcntl(fd, F_SETFL, val) == -1) - debug("fcntl(%d, F_SETFL, O_NONBLOCK): %s", - fd, strerror(errno)); + if (fcntl(fd, F_SETFL, val) == -1) { + debug("fcntl(%d, F_SETFL, O_NONBLOCK): %s", fd, + strerror(errno)); + return (-1); + } + return (0); } -void +int unset_nonblock(int fd) { int val; @@ -75,17 +78,20 @@ unset_nonblock(int fd) val = fcntl(fd, F_GETFL, 0); if (val < 0) { error("fcntl(%d, F_GETFL, 0): %s", fd, strerror(errno)); - return; + return (-1); } if (!(val & O_NONBLOCK)) { - debug2("fd %d is not O_NONBLOCK", fd); - return; + debug3("fd %d is not O_NONBLOCK", fd); + return (0); } debug("fd %d clearing O_NONBLOCK", fd); val &= ~O_NONBLOCK; - if (fcntl(fd, F_SETFL, val) == -1) - debug("fcntl(%d, F_SETFL, O_NONBLOCK): %s", + if (fcntl(fd, F_SETFL, val) == -1) { + debug("fcntl(%d, F_SETFL, ~O_NONBLOCK): %s", fd, strerror(errno)); + return (-1); + } + return (0); } /* disable nagle on socket */ @@ -326,7 +332,7 @@ addargs(arglist *args, char *fmt, ...) { va_list ap; char buf[1024]; - int nalloc; + u_int nalloc; va_start(ap, fmt); vsnprintf(buf, sizeof(buf), fmt, ap); diff --git a/openssh/moduli.c b/openssh/moduli.c index a09073a..581b035 100644 --- a/openssh/moduli.c +++ b/openssh/moduli.c @@ -1,4 +1,4 @@ -/* $OpenBSD: moduli.c,v 1.5 2003/12/22 09:16:57 djm Exp $ */ +/* $OpenBSD: moduli.c,v 1.9 2004/07/11 17:48:47 deraadt Exp $ */ /* * Copyright 1994 Phil Karn * Copyright 1996-1998, 2003 William Allen Simpson @@ -38,7 +38,6 @@ */ #include "includes.h" -#include "moduli.h" #include "xmalloc.h" #include "log.h" @@ -49,55 +48,68 @@ */ /* need line long enough for largest moduli plus headers */ -#define QLINESIZE (100+8192) +#define QLINESIZE (100+8192) /* Type: decimal. * Specifies the internal structure of the prime modulus. */ -#define QTYPE_UNKNOWN (0) -#define QTYPE_UNSTRUCTURED (1) -#define QTYPE_SAFE (2) -#define QTYPE_SCHNOOR (3) -#define QTYPE_SOPHIE_GERMAINE (4) -#define QTYPE_STRONG (5) +#define QTYPE_UNKNOWN (0) +#define QTYPE_UNSTRUCTURED (1) +#define QTYPE_SAFE (2) +#define QTYPE_SCHNOOR (3) +#define QTYPE_SOPHIE_GERMAIN (4) +#define QTYPE_STRONG (5) /* Tests: decimal (bit field). * Specifies the methods used in checking for primality. * Usually, more than one test is used. */ -#define QTEST_UNTESTED (0x00) -#define QTEST_COMPOSITE (0x01) -#define QTEST_SIEVE (0x02) -#define QTEST_MILLER_RABIN (0x04) -#define QTEST_JACOBI (0x08) -#define QTEST_ELLIPTIC (0x10) +#define QTEST_UNTESTED (0x00) +#define QTEST_COMPOSITE (0x01) +#define QTEST_SIEVE (0x02) +#define QTEST_MILLER_RABIN (0x04) +#define QTEST_JACOBI (0x08) +#define QTEST_ELLIPTIC (0x10) /* * Size: decimal. * Specifies the number of the most significant bit (0 to M). * WARNING: internally, usually 1 to N. */ -#define QSIZE_MINIMUM (511) +#define QSIZE_MINIMUM (511) /* * Prime sieving defines */ /* Constant: assuming 8 bit bytes and 32 bit words */ -#define SHIFT_BIT (3) -#define SHIFT_BYTE (2) -#define SHIFT_WORD (SHIFT_BIT+SHIFT_BYTE) -#define SHIFT_MEGABYTE (20) -#define SHIFT_MEGAWORD (SHIFT_MEGABYTE-SHIFT_BYTE) +#define SHIFT_BIT (3) +#define SHIFT_BYTE (2) +#define SHIFT_WORD (SHIFT_BIT+SHIFT_BYTE) +#define SHIFT_MEGABYTE (20) +#define SHIFT_MEGAWORD (SHIFT_MEGABYTE-SHIFT_BYTE) + +/* + * Using virtual memory can cause thrashing. This should be the largest + * number that is supported without a large amount of disk activity -- + * that would increase the run time from hours to days or weeks! + */ +#define LARGE_MINIMUM (8UL) /* megabytes */ + +/* + * Do not increase this number beyond the unsigned integer bit size. + * Due to a multiple of 4, it must be LESS than 128 (yielding 2**30 bits). + */ +#define LARGE_MAXIMUM (127UL) /* megabytes */ /* * Constant: when used with 32-bit integers, the largest sieve prime * has to be less than 2**32. */ -#define SMALL_MAXIMUM (0xffffffffUL) +#define SMALL_MAXIMUM (0xffffffffUL) /* Constant: can sieve all primes less than 2**32, as 65537**2 > 2**32-1. */ -#define TINY_NUMBER (1UL<<16) +#define TINY_NUMBER (1UL<<16) /* Ensure enough bit space for testing 2*q. */ #define TEST_MAXIMUM (1UL<<16) @@ -114,6 +126,9 @@ * Prime testing defines */ +/* Minimum number of primality tests to perform */ +#define TRIAL_MINIMUM (4) + /* * Sieving data (XXX - move to struct) */ @@ -129,6 +144,8 @@ static u_int32_t *LargeSieve, largewords, largetries, largenumbers; static u_int32_t largebits, largememory; /* megabytes */ static BIGNUM *largebase; +int gen_candidates(FILE *, int, int, BIGNUM *); +int prime_test(FILE *, FILE *, u_int32_t, u_int32_t); /* * print moduli out in consistent form, @@ -219,7 +236,7 @@ sieve_large(u_int32_t s) } /* - * list candidates for Sophie-Germaine primes (where q = (p-1)/2) + * list candidates for Sophie-Germain primes (where q = (p-1)/2) * to standard output. * The list is checked against small known primes (less than 2**30). */ @@ -235,6 +252,13 @@ gen_candidates(FILE *out, int memory, int power, BIGNUM *start) largememory = memory; + if (memory != 0 && + (memory < LARGE_MINIMUM || memory > LARGE_MAXIMUM)) { + error("Invalid memory amount (min %ld, max %ld)", + LARGE_MINIMUM, LARGE_MAXIMUM); + return (-1); + } + /* * Set power to the length in bits of the prime to be generated. * This is changed to 1 less than the desired safe prime moduli p. @@ -403,7 +427,7 @@ gen_candidates(FILE *out, int memory, int power, BIGNUM *start) debug2("test q = largebase+%u", 2 * j); BN_set_word(q, 2 * j); BN_add(q, q, largebase); - if (qfileout(out, QTYPE_SOPHIE_GERMAINE, QTEST_SIEVE, + if (qfileout(out, QTYPE_SOPHIE_GERMAIN, QTEST_SIEVE, largetries, (power - 1) /* MSB */, (0), q) == -1) { ret = -1; break; @@ -430,8 +454,7 @@ gen_candidates(FILE *out, int memory, int power, BIGNUM *start) * The result is a list of so-call "safe" primes */ int -prime_test(FILE *in, FILE *out, u_int32_t trials, - u_int32_t generator_wanted) +prime_test(FILE *in, FILE *out, u_int32_t trials, u_int32_t generator_wanted) { BIGNUM *q, *p, *a; BN_CTX *ctx; @@ -441,6 +464,11 @@ prime_test(FILE *in, FILE *out, u_int32_t trials, time_t time_start, time_stop; int res; + if (trials < TRIAL_MINIMUM) { + error("Minimum primality trials is %d", TRIAL_MINIMUM); + return (-1); + } + time(&time_start); p = BN_new(); @@ -490,8 +518,8 @@ prime_test(FILE *in, FILE *out, u_int32_t trials, /* modulus (hex) */ switch (in_type) { - case QTYPE_SOPHIE_GERMAINE: - debug2("%10u: (%u) Sophie-Germaine", count_in, in_type); + case QTYPE_SOPHIE_GERMAIN: + debug2("%10u: (%u) Sophie-Germain", count_in, in_type); a = q; BN_hex2bn(&a, cp); /* p = 2*q + 1 */ diff --git a/openssh/moduli.h b/openssh/moduli.h deleted file mode 100644 index 9cd1cd3..0000000 --- a/openssh/moduli.h +++ /dev/null @@ -1,23 +0,0 @@ -/* $OpenBSD: moduli.h,v 1.1 2003/07/28 09:49:56 djm Exp $ */ - -#include -#include - -/* - * Using virtual memory can cause thrashing. This should be the largest - * number that is supported without a large amount of disk activity -- - * that would increase the run time from hours to days or weeks! - */ -#define LARGE_MINIMUM (8UL) /* megabytes */ - -/* - * Do not increase this number beyond the unsigned integer bit size. - * Due to a multiple of 4, it must be LESS than 128 (yielding 2**30 bits). - */ -#define LARGE_MAXIMUM (127UL) /* megabytes */ - -/* Minimum number of primality tests to perform */ -#define TRIAL_MINIMUM (4) - -int gen_candidates(FILE *, int, int, BIGNUM *); -int prime_test(FILE *, FILE *, u_int32_t, u_int32_t); diff --git a/openssh/monitor.c b/openssh/monitor.c index 494c430..eecd9d4 100644 --- a/openssh/monitor.c +++ b/openssh/monitor.c @@ -25,7 +25,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: monitor.c,v 1.55 2004/02/05 05:37:17 dtucker Exp $"); +RCSID("$OpenBSD: monitor.c,v 1.61 2004/07/17 05:31:41 dtucker Exp $"); #include @@ -63,7 +63,6 @@ RCSID("$OpenBSD: monitor.c,v 1.55 2004/02/05 05:37:17 dtucker Exp $"); #include "bufaux.h" #include "compat.h" #include "ssh2.h" -#include "mpaux.h" #ifdef GSSAPI #include "ssh-gss.h" @@ -80,6 +79,7 @@ extern u_char session_id[]; extern Buffer input, output; extern Buffer auth_debug; extern int auth_debug_init; +extern Buffer loginmsg; /* State exported from the child */ @@ -385,9 +385,9 @@ monitor_set_child_handler(pid_t pid) } static void -monitor_child_handler(int signal) +monitor_child_handler(int sig) { - kill(monitor_child_pid, signal); + kill(monitor_child_pid, sig); } void @@ -513,7 +513,7 @@ monitor_reset_key_state(void) } int -mm_answer_moduli(int socket, Buffer *m) +mm_answer_moduli(int sock, Buffer *m) { DH *dh; int min, want, max; @@ -543,12 +543,12 @@ mm_answer_moduli(int socket, Buffer *m) DH_free(dh); } - mm_request_send(socket, MONITOR_ANS_MODULI, m); + mm_request_send(sock, MONITOR_ANS_MODULI, m); return (0); } int -mm_answer_sign(int socket, Buffer *m) +mm_answer_sign(int sock, Buffer *m) { Key *key; u_char *p; @@ -584,7 +584,7 @@ mm_answer_sign(int socket, Buffer *m) xfree(p); xfree(signature); - mm_request_send(socket, MONITOR_ANS_SIGN, m); + mm_request_send(sock, MONITOR_ANS_SIGN, m); /* Turn on permissions for getpwnam */ monitor_permit(mon_dispatch, MONITOR_REQ_PWNAM, 1); @@ -595,22 +595,22 @@ mm_answer_sign(int socket, Buffer *m) /* Retrieves the password entry and also checks if the user is permitted */ int -mm_answer_pwnamallow(int socket, Buffer *m) +mm_answer_pwnamallow(int sock, Buffer *m) { - char *login; + char *username; struct passwd *pwent; int allowed = 0; debug3("%s", __func__); - login = buffer_get_string(m, NULL); + username = buffer_get_string(m, NULL); - pwent = getpwnamallow(login); + pwent = getpwnamallow(username); if (authctxt->user) xfree(authctxt->user); - authctxt->user = xstrdup(login); - setproctitle("%s [priv]", pwent ? login : "unknown"); - xfree(login); + authctxt->user = xstrdup(username); + setproctitle("%s [priv]", pwent ? username : "unknown"); + xfree(username); buffer_clear(m); @@ -637,7 +637,7 @@ mm_answer_pwnamallow(int socket, Buffer *m) out: debug3("%s: sending MONITOR_ANS_PWNAM: %d", __func__, allowed); - mm_request_send(socket, MONITOR_ANS_PWNAM, m); + mm_request_send(sock, MONITOR_ANS_PWNAM, m); /* For SSHv1 allow authentication now */ if (!compat20) @@ -656,14 +656,14 @@ mm_answer_pwnamallow(int socket, Buffer *m) return (0); } -int mm_answer_auth2_read_banner(int socket, Buffer *m) +int mm_answer_auth2_read_banner(int sock, Buffer *m) { char *banner; buffer_clear(m); banner = auth2_read_banner(); buffer_put_cstring(m, banner != NULL ? banner : ""); - mm_request_send(socket, MONITOR_ANS_AUTH2_READ_BANNER, m); + mm_request_send(sock, MONITOR_ANS_AUTH2_READ_BANNER, m); if (banner != NULL) xfree(banner); @@ -672,7 +672,7 @@ int mm_answer_auth2_read_banner(int socket, Buffer *m) } int -mm_answer_authserv(int socket, Buffer *m) +mm_answer_authserv(int sock, Buffer *m) { monitor_permit_authentications(1); @@ -690,7 +690,7 @@ mm_answer_authserv(int socket, Buffer *m) } int -mm_answer_authpassword(int socket, Buffer *m) +mm_answer_authpassword(int sock, Buffer *m) { static int call_count; char *passwd; @@ -708,7 +708,7 @@ mm_answer_authpassword(int socket, Buffer *m) buffer_put_int(m, authenticated); debug3("%s: sending result %d", __func__, authenticated); - mm_request_send(socket, MONITOR_ANS_AUTHPASSWORD, m); + mm_request_send(sock, MONITOR_ANS_AUTHPASSWORD, m); call_count++; if (plen == 0 && call_count == 1) @@ -722,7 +722,7 @@ mm_answer_authpassword(int socket, Buffer *m) #ifdef BSD_AUTH int -mm_answer_bsdauthquery(int socket, Buffer *m) +mm_answer_bsdauthquery(int sock, Buffer *m) { char *name, *infotxt; u_int numprompts; @@ -739,7 +739,7 @@ mm_answer_bsdauthquery(int socket, Buffer *m) buffer_put_cstring(m, prompts[0]); debug3("%s: sending challenge success: %u", __func__, success); - mm_request_send(socket, MONITOR_ANS_BSDAUTHQUERY, m); + mm_request_send(sock, MONITOR_ANS_BSDAUTHQUERY, m); if (success) { xfree(name); @@ -752,7 +752,7 @@ mm_answer_bsdauthquery(int socket, Buffer *m) } int -mm_answer_bsdauthrespond(int socket, Buffer *m) +mm_answer_bsdauthrespond(int sock, Buffer *m) { char *response; int authok; @@ -771,7 +771,7 @@ mm_answer_bsdauthrespond(int socket, Buffer *m) buffer_put_int(m, authok); debug3("%s: sending authenticated: %d", __func__, authok); - mm_request_send(socket, MONITOR_ANS_BSDAUTHRESPOND, m); + mm_request_send(sock, MONITOR_ANS_BSDAUTHRESPOND, m); auth_method = "bsdauth"; @@ -781,7 +781,7 @@ mm_answer_bsdauthrespond(int socket, Buffer *m) #ifdef SKEY int -mm_answer_skeyquery(int socket, Buffer *m) +mm_answer_skeyquery(int sock, Buffer *m) { struct skey skey; char challenge[1024]; @@ -796,13 +796,13 @@ mm_answer_skeyquery(int socket, Buffer *m) buffer_put_cstring(m, challenge); debug3("%s: sending challenge success: %u", __func__, success); - mm_request_send(socket, MONITOR_ANS_SKEYQUERY, m); + mm_request_send(sock, MONITOR_ANS_SKEYQUERY, m); return (0); } int -mm_answer_skeyrespond(int socket, Buffer *m) +mm_answer_skeyrespond(int sock, Buffer *m) { char *response; int authok; @@ -820,7 +820,7 @@ mm_answer_skeyrespond(int socket, Buffer *m) buffer_put_int(m, authok); debug3("%s: sending authenticated: %d", __func__, authok); - mm_request_send(socket, MONITOR_ANS_SKEYRESPOND, m); + mm_request_send(sock, MONITOR_ANS_SKEYRESPOND, m); auth_method = "skey"; @@ -830,7 +830,7 @@ mm_answer_skeyrespond(int socket, Buffer *m) #ifdef USE_PAM int -mm_answer_pam_start(int socket, Buffer *m) +mm_answer_pam_start(int sock, Buffer *m) { if (!options.use_pam) fatal("UsePAM not set, but ended up in %s anyway", __func__); @@ -843,7 +843,7 @@ mm_answer_pam_start(int socket, Buffer *m) } int -mm_answer_pam_account(int socket, Buffer *m) +mm_answer_pam_account(int sock, Buffer *m) { u_int ret; @@ -854,7 +854,7 @@ mm_answer_pam_account(int socket, Buffer *m) buffer_put_int(m, ret); - mm_request_send(socket, MONITOR_ANS_PAM_ACCOUNT, m); + mm_request_send(sock, MONITOR_ANS_PAM_ACCOUNT, m); return (ret); } @@ -863,7 +863,7 @@ static void *sshpam_ctxt, *sshpam_authok; extern KbdintDevice sshpam_device; int -mm_answer_pam_init_ctx(int socket, Buffer *m) +mm_answer_pam_init_ctx(int sock, Buffer *m) { debug3("%s", __func__); @@ -877,12 +877,12 @@ mm_answer_pam_init_ctx(int socket, Buffer *m) } else { buffer_put_int(m, 0); } - mm_request_send(socket, MONITOR_ANS_PAM_INIT_CTX, m); + mm_request_send(sock, MONITOR_ANS_PAM_INIT_CTX, m); return (0); } int -mm_answer_pam_query(int socket, Buffer *m) +mm_answer_pam_query(int sock, Buffer *m) { char *name, *info, **prompts; u_int num, *echo_on; @@ -911,12 +911,12 @@ mm_answer_pam_query(int socket, Buffer *m) xfree(prompts); if (echo_on != NULL) xfree(echo_on); - mm_request_send(socket, MONITOR_ANS_PAM_QUERY, m); + mm_request_send(sock, MONITOR_ANS_PAM_QUERY, m); return (0); } int -mm_answer_pam_respond(int socket, Buffer *m) +mm_answer_pam_respond(int sock, Buffer *m) { char **resp; u_int num; @@ -938,7 +938,7 @@ mm_answer_pam_respond(int socket, Buffer *m) } buffer_clear(m); buffer_put_int(m, ret); - mm_request_send(socket, MONITOR_ANS_PAM_RESPOND, m); + mm_request_send(sock, MONITOR_ANS_PAM_RESPOND, m); auth_method = "keyboard-interactive/pam"; if (ret == 0) sshpam_authok = sshpam_ctxt; @@ -946,13 +946,13 @@ mm_answer_pam_respond(int socket, Buffer *m) } int -mm_answer_pam_free_ctx(int socket, Buffer *m) +mm_answer_pam_free_ctx(int sock, Buffer *m) { debug3("%s", __func__); (sshpam_device.free_ctx)(sshpam_ctxt); buffer_clear(m); - mm_request_send(socket, MONITOR_ANS_PAM_FREE_CTX, m); + mm_request_send(sock, MONITOR_ANS_PAM_FREE_CTX, m); return (sshpam_authok == sshpam_ctxt); } #endif @@ -969,7 +969,7 @@ mm_append_debug(Buffer *m) } int -mm_answer_keyallowed(int socket, Buffer *m) +mm_answer_keyallowed(int sock, Buffer *m) { Key *key; char *cuser, *chost; @@ -1039,7 +1039,7 @@ mm_answer_keyallowed(int socket, Buffer *m) mm_append_debug(m); - mm_request_send(socket, MONITOR_ANS_KEYALLOWED, m); + mm_request_send(sock, MONITOR_ANS_KEYALLOWED, m); if (type == MM_RSAHOSTKEY) monitor_permit(mon_dispatch, MONITOR_REQ_RSACHALLENGE, allowed); @@ -1160,7 +1160,7 @@ monitor_valid_hostbasedblob(u_char *data, u_int datalen, char *cuser, } int -mm_answer_keyverify(int socket, Buffer *m) +mm_answer_keyverify(int sock, Buffer *m) { Key *key; u_char *signature, *data, *blob; @@ -1210,7 +1210,7 @@ mm_answer_keyverify(int socket, Buffer *m) buffer_clear(m); buffer_put_int(m, verified); - mm_request_send(socket, MONITOR_ANS_KEYVERIFY, m); + mm_request_send(sock, MONITOR_ANS_KEYVERIFY, m); return (verified); } @@ -1252,7 +1252,7 @@ mm_session_close(Session *s) } int -mm_answer_pty(int socket, Buffer *m) +mm_answer_pty(int sock, Buffer *m) { extern struct monitor *pmonitor; Session *s; @@ -1274,10 +1274,6 @@ mm_answer_pty(int socket, Buffer *m) buffer_put_int(m, 1); buffer_put_cstring(m, s->tty); - mm_request_send(socket, MONITOR_ANS_PTY, m); - - mm_send_fd(socket, s->ptyfd); - mm_send_fd(socket, s->ttyfd); /* We need to trick ttyslot */ if (dup2(s->ttyfd, 0) == -1) @@ -1288,6 +1284,15 @@ mm_answer_pty(int socket, Buffer *m) /* Now we can close the file descriptor again */ close(0); + /* send messages generated by record_login */ + buffer_put_string(m, buffer_ptr(&loginmsg), buffer_len(&loginmsg)); + buffer_clear(&loginmsg); + + mm_request_send(sock, MONITOR_ANS_PTY, m); + + mm_send_fd(sock, s->ptyfd); + mm_send_fd(sock, s->ttyfd); + /* make sure nothing uses fd 0 */ if ((fd0 = open(_PATH_DEVNULL, O_RDONLY)) < 0) fatal("%s: open(/dev/null): %s", __func__, strerror(errno)); @@ -1308,12 +1313,12 @@ mm_answer_pty(int socket, Buffer *m) if (s != NULL) mm_session_close(s); buffer_put_int(m, 0); - mm_request_send(socket, MONITOR_ANS_PTY, m); + mm_request_send(sock, MONITOR_ANS_PTY, m); return (0); } int -mm_answer_pty_cleanup(int socket, Buffer *m) +mm_answer_pty_cleanup(int sock, Buffer *m) { Session *s; char *tty; @@ -1329,7 +1334,7 @@ mm_answer_pty_cleanup(int socket, Buffer *m) } int -mm_answer_sesskey(int socket, Buffer *m) +mm_answer_sesskey(int sock, Buffer *m) { BIGNUM *p; int rsafail; @@ -1350,7 +1355,7 @@ mm_answer_sesskey(int socket, Buffer *m) BN_clear_free(p); - mm_request_send(socket, MONITOR_ANS_SESSKEY, m); + mm_request_send(sock, MONITOR_ANS_SESSKEY, m); /* Turn on permissions for sessid passing */ monitor_permit(mon_dispatch, MONITOR_REQ_SESSID, 1); @@ -1359,7 +1364,7 @@ mm_answer_sesskey(int socket, Buffer *m) } int -mm_answer_sessid(int socket, Buffer *m) +mm_answer_sessid(int sock, Buffer *m) { int i; @@ -1377,7 +1382,7 @@ mm_answer_sessid(int socket, Buffer *m) } int -mm_answer_rsa_keyallowed(int socket, Buffer *m) +mm_answer_rsa_keyallowed(int sock, Buffer *m) { BIGNUM *client_n; Key *key = NULL; @@ -1417,7 +1422,7 @@ mm_answer_rsa_keyallowed(int socket, Buffer *m) mm_append_debug(m); - mm_request_send(socket, MONITOR_ANS_RSAKEYALLOWED, m); + mm_request_send(sock, MONITOR_ANS_RSAKEYALLOWED, m); monitor_permit(mon_dispatch, MONITOR_REQ_RSACHALLENGE, allowed); monitor_permit(mon_dispatch, MONITOR_REQ_RSARESPONSE, 0); @@ -1425,7 +1430,7 @@ mm_answer_rsa_keyallowed(int socket, Buffer *m) } int -mm_answer_rsa_challenge(int socket, Buffer *m) +mm_answer_rsa_challenge(int sock, Buffer *m) { Key *key = NULL; u_char *blob; @@ -1451,7 +1456,7 @@ mm_answer_rsa_challenge(int socket, Buffer *m) buffer_put_bignum2(m, ssh1_challenge); debug3("%s sending reply", __func__); - mm_request_send(socket, MONITOR_ANS_RSACHALLENGE, m); + mm_request_send(sock, MONITOR_ANS_RSACHALLENGE, m); monitor_permit(mon_dispatch, MONITOR_REQ_RSARESPONSE, 1); @@ -1461,7 +1466,7 @@ mm_answer_rsa_challenge(int socket, Buffer *m) } int -mm_answer_rsa_response(int socket, Buffer *m) +mm_answer_rsa_response(int sock, Buffer *m) { Key *key = NULL; u_char *blob, *response; @@ -1500,13 +1505,13 @@ mm_answer_rsa_response(int socket, Buffer *m) buffer_clear(m); buffer_put_int(m, success); - mm_request_send(socket, MONITOR_ANS_RSARESPONSE, m); + mm_request_send(sock, MONITOR_ANS_RSARESPONSE, m); return (success); } int -mm_answer_term(int socket, Buffer *req) +mm_answer_term(int sock, Buffer *req) { extern struct monitor *pmonitor; int res, status; @@ -1523,7 +1528,7 @@ mm_answer_term(int socket, Buffer *req) res = WIFEXITED(status) ? WEXITSTATUS(status) : 1; /* Terminate process */ - exit (res); + exit(res); } void @@ -1590,6 +1595,7 @@ mm_get_kex(Buffer *m) fatal("mm_get_get: internal error: bad session id"); kex->we_need = buffer_get_int(m); kex->kex[KEX_DH_GRP1_SHA1] = kexdh_server; + kex->kex[KEX_DH_GRP14_SHA1] = kexdh_server; kex->kex[KEX_DH_GEX_SHA1] = kexgex_server; #ifdef GSSAPI kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_server; @@ -1786,23 +1792,23 @@ monitor_reinit(struct monitor *mon) #ifdef GSSAPI int -mm_answer_gss_setup_ctx(int socket, Buffer *m) +mm_answer_gss_setup_ctx(int sock, Buffer *m) { - gss_OID_desc oid; + gss_OID_desc goid; OM_uint32 major; u_int len; - oid.elements = buffer_get_string(m, &len); - oid.length = len; + goid.elements = buffer_get_string(m, &len); + goid.length = len; - major = ssh_gssapi_server_ctx(&gsscontext, &oid); + major = ssh_gssapi_server_ctx(&gsscontext, &goid); - xfree(oid.elements); + xfree(goid.elements); buffer_clear(m); buffer_put_int(m, major); - mm_request_send(socket,MONITOR_ANS_GSSSETUP, m); + mm_request_send(sock,MONITOR_ANS_GSSSETUP, m); /* Now we have a context, enable the step */ monitor_permit(mon_dispatch, MONITOR_REQ_GSSSTEP, 1); @@ -1811,7 +1817,7 @@ mm_answer_gss_setup_ctx(int socket, Buffer *m) } int -mm_answer_gss_accept_ctx(int socket, Buffer *m) +mm_answer_gss_accept_ctx(int sock, Buffer *m) { gss_buffer_desc in; gss_buffer_desc out = GSS_C_EMPTY_BUFFER; @@ -1828,7 +1834,7 @@ mm_answer_gss_accept_ctx(int socket, Buffer *m) buffer_put_int(m, major); buffer_put_string(m, out.value, out.length); buffer_put_int(m, flags); - mm_request_send(socket, MONITOR_ANS_GSSSTEP, m); + mm_request_send(sock, MONITOR_ANS_GSSSTEP, m); gss_release_buffer(&minor, &out); @@ -1842,7 +1848,7 @@ mm_answer_gss_accept_ctx(int socket, Buffer *m) } int -mm_answer_gss_checkmic(int socket, Buffer *m) +mm_answer_gss_checkmic(int sock, Buffer *m) { gss_buffer_desc gssbuf, mic; OM_uint32 ret; @@ -1861,7 +1867,7 @@ mm_answer_gss_checkmic(int socket, Buffer *m) buffer_clear(m); buffer_put_int(m, ret); - mm_request_send(socket, MONITOR_ANS_GSSCHECKMIC, m); + mm_request_send(sock, MONITOR_ANS_GSSCHECKMIC, m); if (!GSS_ERROR(ret)) monitor_permit(mon_dispatch, MONITOR_REQ_GSSUSEROK, 1); @@ -1870,7 +1876,7 @@ mm_answer_gss_checkmic(int socket, Buffer *m) } int -mm_answer_gss_userok(int socket, Buffer *m) +mm_answer_gss_userok(int sock, Buffer *m) { int authenticated; @@ -1880,7 +1886,7 @@ mm_answer_gss_userok(int socket, Buffer *m) buffer_put_int(m, authenticated); debug3("%s: sending result %d", __func__, authenticated); - mm_request_send(socket, MONITOR_ANS_GSSUSEROK, m); + mm_request_send(sock, MONITOR_ANS_GSSUSEROK, m); auth_method="gssapi-with-mic"; diff --git a/openssh/monitor_fdpass.c b/openssh/monitor_fdpass.c index 22b7882..dd1a139 100644 --- a/openssh/monitor_fdpass.c +++ b/openssh/monitor_fdpass.c @@ -24,7 +24,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: monitor_fdpass.c,v 1.4 2002/06/26 14:50:04 deraadt Exp $"); +RCSID("$OpenBSD: monitor_fdpass.c,v 1.6 2004/08/13 02:51:48 djm Exp $"); #include @@ -32,7 +32,7 @@ RCSID("$OpenBSD: monitor_fdpass.c,v 1.4 2002/06/26 14:50:04 deraadt Exp $"); #include "monitor_fdpass.h" void -mm_send_fd(int socket, int fd) +mm_send_fd(int sock, int fd) { #if defined(HAVE_SENDMSG) && (defined(HAVE_ACCRIGHTS_IN_MSGHDR) || defined(HAVE_CONTROL_IN_MSGHDR)) struct msghdr msg; @@ -63,7 +63,7 @@ mm_send_fd(int socket, int fd) msg.msg_iov = &vec; msg.msg_iovlen = 1; - if ((n = sendmsg(socket, &msg, 0)) == -1) + if ((n = sendmsg(sock, &msg, 0)) == -1) fatal("%s: sendmsg(%d): %s", __func__, fd, strerror(errno)); if (n != 1) @@ -76,7 +76,7 @@ mm_send_fd(int socket, int fd) } int -mm_receive_fd(int socket) +mm_receive_fd(int sock) { #if defined(HAVE_RECVMSG) && (defined(HAVE_ACCRIGHTS_IN_MSGHDR) || defined(HAVE_CONTROL_IN_MSGHDR)) struct msghdr msg; @@ -102,7 +102,7 @@ mm_receive_fd(int socket) msg.msg_controllen = sizeof(tmp); #endif - if ((n = recvmsg(socket, &msg, 0)) == -1) + if ((n = recvmsg(sock, &msg, 0)) == -1) fatal("%s: recvmsg: %s", __func__, strerror(errno)); if (n != 1) fatal("%s: recvmsg: expected received 1 got %ld", @@ -113,6 +113,8 @@ mm_receive_fd(int socket) fatal("%s: no fd", __func__); #else cmsg = CMSG_FIRSTHDR(&msg); + if (cmsg == NULL) + fatal("%s: no message header", __func__); #ifndef BROKEN_CMSG_TYPE if (cmsg->cmsg_type != SCM_RIGHTS) fatal("%s: expected type %d got %d", __func__, diff --git a/openssh/monitor_mm.c b/openssh/monitor_mm.c index e57c87c..ff523a5 100644 --- a/openssh/monitor_mm.c +++ b/openssh/monitor_mm.c @@ -24,7 +24,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: monitor_mm.c,v 1.8 2002/08/02 14:43:15 millert Exp $"); +RCSID("$OpenBSD: monitor_mm.c,v 1.9 2004/05/11 19:01:43 deraadt Exp $"); #ifdef HAVE_SYS_MMAN_H #include diff --git a/openssh/monitor_wrap.c b/openssh/monitor_wrap.c index 396ec32..dfbfa77 100644 --- a/openssh/monitor_wrap.c +++ b/openssh/monitor_wrap.c @@ -25,7 +25,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: monitor_wrap.c,v 1.35 2003/11/17 11:06:07 markus Exp $"); +RCSID("$OpenBSD: monitor_wrap.c,v 1.39 2004/07/17 05:31:41 dtucker Exp $"); #include #include @@ -70,6 +70,7 @@ extern z_stream incoming_stream; extern z_stream outgoing_stream; extern struct monitor *pmonitor; extern Buffer input, output; +extern Buffer loginmsg; extern ServerOptions options; int @@ -83,7 +84,7 @@ mm_is_monitor(void) } void -mm_request_send(int socket, enum monitor_reqtype type, Buffer *m) +mm_request_send(int sock, enum monitor_reqtype type, Buffer *m) { u_int mlen = buffer_len(m); u_char buf[5]; @@ -92,14 +93,14 @@ mm_request_send(int socket, enum monitor_reqtype type, Buffer *m) PUT_32BIT(buf, mlen + 1); buf[4] = (u_char) type; /* 1st byte of payload is mesg-type */ - if (atomicio(vwrite, socket, buf, sizeof(buf)) != sizeof(buf)) + if (atomicio(vwrite, sock, buf, sizeof(buf)) != sizeof(buf)) fatal("%s: write", __func__); - if (atomicio(vwrite, socket, buffer_ptr(m), mlen) != mlen) + if (atomicio(vwrite, sock, buffer_ptr(m), mlen) != mlen) fatal("%s: write", __func__); } void -mm_request_receive(int socket, Buffer *m) +mm_request_receive(int sock, Buffer *m) { u_char buf[4]; u_int msg_len; @@ -107,7 +108,7 @@ mm_request_receive(int socket, Buffer *m) debug3("%s entering", __func__); - res = atomicio(read, socket, buf, sizeof(buf)); + res = atomicio(read, sock, buf, sizeof(buf)); if (res != sizeof(buf)) { if (res == 0) cleanup_exit(255); @@ -118,19 +119,19 @@ mm_request_receive(int socket, Buffer *m) fatal("%s: read: bad msg_len %d", __func__, msg_len); buffer_clear(m); buffer_append_space(m, msg_len); - res = atomicio(read, socket, buffer_ptr(m), msg_len); + res = atomicio(read, sock, buffer_ptr(m), msg_len); if (res != msg_len) fatal("%s: read: %ld != msg_len", __func__, (long)res); } void -mm_request_receive_expect(int socket, enum monitor_reqtype type, Buffer *m) +mm_request_receive_expect(int sock, enum monitor_reqtype type, Buffer *m) { u_char rtype; debug3("%s entering: type %d", __func__, type); - mm_request_receive(socket, m); + mm_request_receive(sock, m); rtype = buffer_get_char(m); if (rtype != type) fatal("%s: read: rtype %d != type %d", __func__, @@ -194,7 +195,7 @@ mm_key_sign(Key *key, u_char **sigp, u_int *lenp, u_char *data, u_int datalen) } struct passwd * -mm_getpwnamallow(const char *login) +mm_getpwnamallow(const char *username) { Buffer m; struct passwd *pw; @@ -203,7 +204,7 @@ mm_getpwnamallow(const char *login) debug3("%s entering", __func__); buffer_init(&m); - buffer_put_cstring(&m, login); + buffer_put_cstring(&m, username); mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PWNAM, &m); @@ -544,7 +545,7 @@ mm_send_kex(Buffer *m, Kex *kex) } void -mm_send_keystate(struct monitor *pmonitor) +mm_send_keystate(struct monitor *monitor) { Buffer m; u_char *blob, *p; @@ -580,7 +581,7 @@ mm_send_keystate(struct monitor *pmonitor) goto skip; } else { /* Kex for rekeying */ - mm_send_kex(&m, *pmonitor->m_pkex); + mm_send_kex(&m, *monitor->m_pkex); } debug3("%s: Sending new keys: %p %p", @@ -632,7 +633,7 @@ mm_send_keystate(struct monitor *pmonitor) buffer_put_string(&m, buffer_ptr(&input), buffer_len(&input)); buffer_put_string(&m, buffer_ptr(&output), buffer_len(&output)); - mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_KEYEXPORT, &m); + mm_request_send(monitor->m_recvfd, MONITOR_REQ_KEYEXPORT, &m); debug3("%s: Finished sending state", __func__); buffer_free(&m); @@ -642,7 +643,7 @@ int mm_pty_allocate(int *ptyfd, int *ttyfd, char *namebuf, int namebuflen) { Buffer m; - char *p; + char *p, *msg; int success = 0; buffer_init(&m); @@ -658,11 +659,15 @@ mm_pty_allocate(int *ptyfd, int *ttyfd, char *namebuf, int namebuflen) return (0); } p = buffer_get_string(&m, NULL); + msg = buffer_get_string(&m, NULL); buffer_free(&m); strlcpy(namebuf, p, namebuflen); /* Possible truncation */ xfree(p); + buffer_append(&loginmsg, msg, strlen(msg)); + xfree(msg); + *ptyfd = mm_receive_fd(pmonitor->m_recvfd); *ttyfd = mm_receive_fd(pmonitor->m_recvfd); @@ -914,6 +919,7 @@ mm_bsdauth_respond(void *ctx, u_int numresponses, char **responses) return ((authok == 0) ? -1 : 0); } +#ifdef SKEY int mm_skey_query(void *ctx, char **name, char **infotxt, u_int *numprompts, char ***prompts, u_int **echo_on) @@ -977,6 +983,7 @@ mm_skey_respond(void *ctx, u_int numresponses, char **responses) return ((authok == 0) ? -1 : 0); } +#endif /* SKEY */ void mm_ssh1_session_id(u_char session_id[16]) @@ -1093,7 +1100,7 @@ mm_auth_rsa_verify_response(Key *key, BIGNUM *p, u_char response[16]) #ifdef GSSAPI OM_uint32 -mm_ssh_gssapi_server_ctx(Gssctxt **ctx, gss_OID oid) +mm_ssh_gssapi_server_ctx(Gssctxt **ctx, gss_OID goid) { Buffer m; OM_uint32 major; @@ -1102,7 +1109,7 @@ mm_ssh_gssapi_server_ctx(Gssctxt **ctx, gss_OID oid) *ctx = NULL; buffer_init(&m); - buffer_put_string(&m, oid->elements, oid->length); + buffer_put_string(&m, goid->elements, goid->length); mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSSETUP, &m); mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSSETUP, &m); diff --git a/openssh/monitor_wrap.h b/openssh/monitor_wrap.h index 6874984..64f5068 100644 --- a/openssh/monitor_wrap.h +++ b/openssh/monitor_wrap.h @@ -1,4 +1,4 @@ -/* $OpenBSD: monitor_wrap.h,v 1.13 2003/11/17 11:06:07 markus Exp $ */ +/* $OpenBSD: monitor_wrap.h,v 1.14 2004/06/21 17:36:31 avsm Exp $ */ /* * Copyright 2002 Niels Provos @@ -58,9 +58,9 @@ BIGNUM *mm_auth_rsa_generate_challenge(Key *); #ifdef GSSAPI #include "ssh-gss.h" -OM_uint32 mm_ssh_gssapi_server_ctx(Gssctxt **ctxt, gss_OID oid); -OM_uint32 mm_ssh_gssapi_accept_ctx(Gssctxt *ctxt, - gss_buffer_desc *recv, gss_buffer_desc *send, OM_uint32 *flags); +OM_uint32 mm_ssh_gssapi_server_ctx(Gssctxt **, gss_OID); +OM_uint32 mm_ssh_gssapi_accept_ctx(Gssctxt *, + gss_buffer_desc *, gss_buffer_desc *, OM_uint32 *); int mm_ssh_gssapi_userok(char *user); OM_uint32 mm_ssh_gssapi_checkmic(Gssctxt *, gss_buffer_t, gss_buffer_t); OM_uint32 mm_ssh_gssapi_sign(Gssctxt *ctxt, gss_buffer_desc *buffer, diff --git a/openssh/openbsd-compat/getrrsetbyname.c b/openssh/openbsd-compat/getrrsetbyname.c index 66d1814..660427c 100644 --- a/openssh/openbsd-compat/getrrsetbyname.c +++ b/openssh/openbsd-compat/getrrsetbyname.c @@ -53,6 +53,10 @@ #define ANSWER_BUFFER_SIZE 1024*64 +#if defined(HAVE_DECL_H_ERRNO) && !HAVE_DECL_H_ERRNO +extern int h_errno; +#endif + struct dns_query { char *name; u_int16_t type; diff --git a/openssh/openbsd-compat/port-aix.c b/openssh/openbsd-compat/port-aix.c index 2895f0d..78f4fae 100644 --- a/openssh/openbsd-compat/port-aix.c +++ b/openssh/openbsd-compat/port-aix.c @@ -101,7 +101,7 @@ aix_remove_embedded_newlines(char *p) int sys_auth_passwd(Authctxt *ctxt, const char *password) { - char *authmsg = NULL, *host, *msg, *name = ctxt->pw->pw_name; + char *authmsg = NULL, *msg, *name = ctxt->pw->pw_name; int authsuccess = 0, expired, reenter, result; do { @@ -115,30 +115,21 @@ sys_auth_passwd(Authctxt *ctxt, const char *password) if (result == 0) { authsuccess = 1; - host = (char *)get_canonical_hostname(options.use_dns); - /* * Record successful login. We don't have a pty yet, so just * label the line as "ssh" */ aix_setauthdb(name); - if (loginsuccess((char *)name, (char *)host, "ssh", &msg) == 0) { - if (msg != NULL) { - debug("%s: msg %s", __func__, msg); - buffer_append(&loginmsg, msg, strlen(msg)); - xfree(msg); - } - } /* * Check if the user's password is expired. */ - expired = passwdexpired(name, &msg); - if (msg && *msg) { - buffer_append(&loginmsg, msg, strlen(msg)); - aix_remove_embedded_newlines(msg); - } - debug3("AIX/passwdexpired returned %d msg %.100s", expired, msg); + expired = passwdexpired(name, &msg); + if (msg && *msg) { + buffer_append(&loginmsg, msg, strlen(msg)); + aix_remove_embedded_newlines(msg); + } + debug3("AIX/passwdexpired returned %d msg %.100s", expired, msg); switch (expired) { case 0: /* password not expired */ @@ -163,7 +154,70 @@ sys_auth_passwd(Authctxt *ctxt, const char *password) return authsuccess; } - + +/* + * Check if specified account is permitted to log in. + * Returns 1 if login is allowed, 0 if not allowed. + */ +int +sys_auth_allowed_user(struct passwd *pw) +{ + char *msg = NULL; + int result, permitted = 0; + struct stat st; + + /* + * Don't perform checks for root account (PermitRootLogin controls + * logins via * ssh) or if running as non-root user (since + * loginrestrictions will always fail due to insufficient privilege). + */ + if (pw->pw_uid == 0 || geteuid() != 0) { + debug3("%s: not checking", __func__); + return 1; + } + + result = loginrestrictions(pw->pw_name, S_RLOGIN, NULL, &msg); + if (result == 0) + permitted = 1; + /* + * If restricted because /etc/nologin exists, the login will be denied + * in session.c after the nologin message is sent, so allow for now + * and do not append the returned message. + */ + if (result == -1 && errno == EPERM && stat(_PATH_NOLOGIN, &st) == 0) + permitted = 1; + else if (msg != NULL) + buffer_append(&loginmsg, msg, strlen(msg)); + if (msg == NULL) + msg = xstrdup("(none)"); + aix_remove_embedded_newlines(msg); + debug3("AIX/loginrestrictions returned %d msg %.100s", result, msg); + + if (!permitted) + logit("Login restricted for %s: %.100s", pw->pw_name, msg); + xfree(msg); + return permitted; +} + +int +sys_auth_record_login(const char *user, const char *host, const char *ttynm) +{ + char *msg; + int success = 0; + + aix_setauthdb(user); + if (loginsuccess((char *)user, host, ttynm, &msg) == 0) { + success = 1; + if (msg != NULL) { + debug("AIX/loginsuccess: msg %s", __func__, msg); + buffer_append(&loginmsg, msg, strlen(msg)); + xfree(msg); + } + } + aix_restoreauthdb(); + return (success); +} + # ifdef CUSTOM_FAILED_LOGIN /* * record_failed_login: generic "login failed" interface function diff --git a/openssh/openbsd-compat/port-aix.h b/openssh/openbsd-compat/port-aix.h index 4996233..f1a9965 100644 --- a/openssh/openbsd-compat/port-aix.h +++ b/openssh/openbsd-compat/port-aix.h @@ -64,6 +64,10 @@ void aix_usrinfo(struct passwd *); #ifdef WITH_AIXAUTHENTICATE # define CUSTOM_SYS_AUTH_PASSWD 1 +# define CUSTOM_SYS_AUTH_ALLOWED_USER 1 +int sys_auth_allowed_user(struct passwd *); +# define CUSTOM_SYS_AUTH_RECORD_LOGIN 1 +int sys_auth_record_login(const char *, const char *, const char *); # define CUSTOM_FAILED_LOGIN 1 void record_failed_login(const char *, const char *); #endif diff --git a/openssh/openbsd-compat/sys-queue.h b/openssh/openbsd-compat/sys-queue.h index 8ff19e4..c49a946 100644 --- a/openssh/openbsd-compat/sys-queue.h +++ b/openssh/openbsd-compat/sys-queue.h @@ -1,6 +1,6 @@ /* OPENBSD ORIGINAL: sys/sys/queue.h */ -/* $OpenBSD: queue.h,v 1.23 2003/06/02 23:28:21 millert Exp $ */ +/* $OpenBSD: queue.h,v 1.25 2004/04/08 16:08:21 henning Exp $ */ /* $NetBSD: queue.h,v 1.11 1996/05/16 05:17:14 mycroft Exp $ */ /* @@ -38,12 +38,13 @@ #define _FAKE_QUEUE_H_ /* - * Ignore all since older platforms have broken/incomplete - * that are too hard to work around. + * Require for OS/X and other platforms that have old/broken/incomplete + * . */ #undef SLIST_HEAD #undef SLIST_HEAD_INITIALIZER #undef SLIST_ENTRY +#undef SLIST_FOREACH_PREVPTR #undef SLIST_FIRST #undef SLIST_END #undef SLIST_EMPTY @@ -54,6 +55,7 @@ #undef SLIST_INSERT_HEAD #undef SLIST_REMOVE_HEAD #undef SLIST_REMOVE +#undef SLIST_REMOVE_NEXT #undef LIST_HEAD #undef LIST_HEAD_INITIALIZER #undef LIST_ENTRY @@ -194,6 +196,11 @@ struct { \ (var) != SLIST_END(head); \ (var) = SLIST_NEXT(var, field)) +#define SLIST_FOREACH_PREVPTR(var, varp, head, field) \ + for ((varp) = &SLIST_FIRST((head)); \ + ((var) = *(varp)) != SLIST_END(head); \ + (varp) = &SLIST_NEXT((var), field)) + /* * Singly-linked List functions. */ @@ -211,6 +218,10 @@ struct { \ (head)->slh_first = (elm); \ } while (0) +#define SLIST_REMOVE_NEXT(head, elm, field) do { \ + (elm)->field.sle_next = (elm)->field.sle_next->field.sle_next; \ +} while (0) + #define SLIST_REMOVE_HEAD(head, field) do { \ (head)->slh_first = (head)->slh_first->field.sle_next; \ } while (0) @@ -400,7 +411,7 @@ struct { \ (var) != TAILQ_END(head); \ (var) = TAILQ_NEXT(var, field)) -#define TAILQ_FOREACH_REVERSE(var, head, field, headname) \ +#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \ for((var) = TAILQ_LAST(head, headname); \ (var) != TAILQ_END(head); \ (var) = TAILQ_PREV(var, headname, field)) diff --git a/openssh/openbsd-compat/xmmap.c b/openssh/openbsd-compat/xmmap.c index 0e22ec6..d136a34 100644 --- a/openssh/openbsd-compat/xmmap.c +++ b/openssh/openbsd-compat/xmmap.c @@ -40,25 +40,28 @@ void *xmmap(size_t size) #ifdef HAVE_MMAP # ifdef MAP_ANON address = mmap(NULL, size, PROT_WRITE|PROT_READ, MAP_ANON|MAP_SHARED, - -1, 0); + -1, (off_t)0); # else address = mmap(NULL, size, PROT_WRITE|PROT_READ, MAP_SHARED, - open("/dev/zero", O_RDWR), 0); + open("/dev/zero", O_RDWR), (off_t)0); # endif #define MM_SWAP_TEMPLATE "/var/run/sshd.mm.XXXXXXXX" if (address == MAP_FAILED) { char tmpname[sizeof(MM_SWAP_TEMPLATE)] = MM_SWAP_TEMPLATE; int tmpfd; + mode_t old_umask; + old_umask = umask(0177); tmpfd = mkstemp(tmpname); + umask(old_umask); if (tmpfd == -1) fatal("mkstemp(\"%s\"): %s", MM_SWAP_TEMPLATE, strerror(errno)); unlink(tmpname); ftruncate(tmpfd, size); address = mmap(NULL, size, PROT_WRITE|PROT_READ, MAP_SHARED, - tmpfd, 0); + tmpfd, (off_t)0); close(tmpfd); } diff --git a/openssh/packet.c b/openssh/packet.c index daae9ff..82a5694 100644 --- a/openssh/packet.c +++ b/openssh/packet.c @@ -37,7 +37,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: packet.c,v 1.112 2003/09/23 20:17:11 markus Exp $"); +RCSID("$OpenBSD: packet.c,v 1.115 2004/06/21 17:36:31 avsm Exp $"); #include "openbsd-compat/sys-queue.h" @@ -154,8 +154,10 @@ packet_set_connection(int fd_in, int fd_out) fatal("packet_set_connection: cannot load cipher 'none'"); connection_in = fd_in; connection_out = fd_out; - cipher_init(&send_context, none, "", 0, NULL, 0, CIPHER_ENCRYPT); - cipher_init(&receive_context, none, "", 0, NULL, 0, CIPHER_DECRYPT); + cipher_init(&send_context, none, (const u_char *)"", + 0, NULL, 0, CIPHER_ENCRYPT); + cipher_init(&receive_context, none, (const u_char *)"", + 0, NULL, 0, CIPHER_DECRYPT); newkeys[MODE_IN] = newkeys[MODE_OUT] = NULL; if (!initialized) { initialized = 1; @@ -317,13 +319,10 @@ void packet_set_nonblocking(void) { /* Set the socket into non-blocking mode. */ - if (fcntl(connection_in, F_SETFL, O_NONBLOCK) < 0) - error("fcntl O_NONBLOCK: %.100s", strerror(errno)); + set_nonblock(connection_in); - if (connection_out != connection_in) { - if (fcntl(connection_out, F_SETFL, O_NONBLOCK) < 0) - error("fcntl O_NONBLOCK: %.100s", strerror(errno)); - } + if (connection_out != connection_in) + set_nonblock(connection_out); } /* Returns the socket used for reading. */ @@ -508,7 +507,7 @@ packet_send1(void) u_char buf[8], *cp; int i, padding, len; u_int checksum; - u_int32_t rand = 0; + u_int32_t rnd = 0; /* * If using packet compression, compress the payload of the outgoing @@ -534,9 +533,9 @@ packet_send1(void) cp = buffer_ptr(&outgoing_packet); for (i = 0; i < padding; i++) { if (i % 4 == 0) - rand = arc4random(); - cp[7 - i] = rand & 0xff; - rand >>= 8; + rnd = arc4random(); + cp[7 - i] = rnd & 0xff; + rnd >>= 8; } } buffer_consume(&outgoing_packet, 8 - padding); @@ -581,18 +580,18 @@ set_newkeys(int mode) Comp *comp; CipherContext *cc; u_int64_t *max_blocks; - int encrypt; + int crypt_type; debug2("set_newkeys: mode %d", mode); if (mode == MODE_OUT) { cc = &send_context; - encrypt = CIPHER_ENCRYPT; + crypt_type = CIPHER_ENCRYPT; p_send.packets = p_send.blocks = 0; max_blocks = &max_blocks_out; } else { cc = &receive_context; - encrypt = CIPHER_DECRYPT; + crypt_type = CIPHER_DECRYPT; p_read.packets = p_read.blocks = 0; max_blocks = &max_blocks_in; } @@ -621,7 +620,7 @@ set_newkeys(int mode) mac->enabled = 1; DBG(debug("cipher_init_context: %d", mode)); cipher_init(cc, enc->cipher, enc->key, enc->key_len, - enc->iv, enc->block_size, encrypt); + enc->iv, enc->block_size, crypt_type); /* Deleting the keys does not gain extra security */ /* memset(enc->iv, 0, enc->block_size); memset(enc->key, 0, enc->key_len); */ @@ -655,7 +654,7 @@ packet_send2_wrapped(void) u_char padlen, pad; u_int packet_length = 0; u_int i, len; - u_int32_t rand = 0; + u_int32_t rnd = 0; Enc *enc = NULL; Mac *mac = NULL; Comp *comp = NULL; @@ -714,9 +713,9 @@ packet_send2_wrapped(void) /* random padding */ for (i = 0; i < padlen; i++) { if (i % 4 == 0) - rand = arc4random(); - cp[i] = rand & 0xff; - rand >>= 8; + rnd = arc4random(); + cp[i] = rnd & 0xff; + rnd >>= 8; } } else { /* clear padding */ @@ -1449,7 +1448,7 @@ packet_is_interactive(void) return interactive_mode; } -u_int +int packet_set_maxsize(u_int s) { static int called = 0; @@ -1490,20 +1489,20 @@ packet_add_padding(u_char pad) void packet_send_ignore(int nbytes) { - u_int32_t rand = 0; + u_int32_t rnd = 0; int i; packet_start(compat20 ? SSH2_MSG_IGNORE : SSH_MSG_IGNORE); packet_put_int(nbytes); for (i = 0; i < nbytes; i++) { if (i % 4 == 0) - rand = arc4random(); - packet_put_char(rand & 0xff); - rand >>= 8; + rnd = arc4random(); + packet_put_char(rnd & 0xff); + rnd >>= 8; } } -#define MAX_PACKETS (1<<31) +#define MAX_PACKETS (1U<<31) int packet_need_rekeying(void) { diff --git a/openssh/packet.h b/openssh/packet.h index 7732faf..37f82f2 100644 --- a/openssh/packet.h +++ b/openssh/packet.h @@ -1,4 +1,4 @@ -/* $OpenBSD: packet.h,v 1.40 2003/06/24 08:23:46 markus Exp $ */ +/* $OpenBSD: packet.h,v 1.41 2004/05/11 19:01:43 deraadt Exp $ */ /* * Author: Tatu Ylonen @@ -82,7 +82,7 @@ void tty_make_modes(int, struct termios *); void tty_parse_modes(int, int *); extern u_int max_packet_size; -u_int packet_set_maxsize(u_int); +int packet_set_maxsize(u_int); #define packet_get_maxsize() max_packet_size /* don't allow remaining bytes after the end of the message */ diff --git a/openssh/progressmeter.c b/openssh/progressmeter.c index f426685..93f5a3e 100644 --- a/openssh/progressmeter.c +++ b/openssh/progressmeter.c @@ -23,7 +23,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: progressmeter.c,v 1.19 2004/02/05 15:33:33 markus Exp $"); +RCSID("$OpenBSD: progressmeter.c,v 1.22 2004/07/11 17:48:47 deraadt Exp $"); #include "progressmeter.h" #include "atomicio.h" @@ -48,15 +48,15 @@ void refresh_progress_meter(void); /* signal handler for updating the progress meter */ static void update_progress_meter(int); -static time_t start; /* start progress */ -static time_t last_update; /* last progress update */ -static char *file; /* name of the file being transferred */ -static off_t end_pos; /* ending position of transfer */ -static off_t cur_pos; /* transfer position as of last refresh */ +static time_t start; /* start progress */ +static time_t last_update; /* last progress update */ +static char *file; /* name of the file being transferred */ +static off_t end_pos; /* ending position of transfer */ +static off_t cur_pos; /* transfer position as of last refresh */ static volatile off_t *counter; /* progress counter */ -static long stalled; /* how long we have been stalled */ -static int bytes_per_second; /* current speed in bytes per second */ -static int win_size; /* terminal window size */ +static long stalled; /* how long we have been stalled */ +static int bytes_per_second; /* current speed in bytes per second */ +static int win_size; /* terminal window size */ /* units for format_size */ static const char unit[] = " KMGT"; @@ -167,7 +167,7 @@ refresh_progress_meter(void) /* bandwidth usage */ format_rate(buf + strlen(buf), win_size - strlen(buf), - bytes_per_second); + (off_t)bytes_per_second); strlcat(buf, "/s ", win_size); /* ETA */ @@ -224,7 +224,7 @@ update_progress_meter(int ignore) } void -start_progress_meter(char *f, off_t filesize, off_t *stat) +start_progress_meter(char *f, off_t filesize, off_t *ctr) { struct winsize winsize; @@ -232,7 +232,7 @@ start_progress_meter(char *f, off_t filesize, off_t *stat) file = f; end_pos = filesize; cur_pos = 0; - counter = stat; + counter = ctr; stalled = 0; bytes_per_second = 0; diff --git a/openssh/readconf.c b/openssh/readconf.c index a51848e..76dc42e 100644 --- a/openssh/readconf.c +++ b/openssh/readconf.c @@ -12,7 +12,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: readconf.c,v 1.128 2004/03/05 10:53:58 markus Exp $"); +RCSID("$OpenBSD: readconf.c,v 1.134 2004/07/11 17:48:47 deraadt Exp $"); #include "ssh.h" #include "xmalloc.h" @@ -106,6 +106,7 @@ typedef enum { oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout, oAddressFamily, oGssAuthentication, oGssKeyEx, oGssDelegateCreds, oServerAliveInterval, oServerAliveCountMax, oIdentitiesOnly, + oSendEnv, oControlPath, oControlMaster, oDeprecated, oUnsupported } OpCodes; @@ -195,6 +196,9 @@ static struct { { "addressfamily", oAddressFamily }, { "serveraliveinterval", oServerAliveInterval }, { "serveralivecountmax", oServerAliveCountMax }, + { "sendenv", oSendEnv }, + { "controlpath", oControlPath }, + { "controlmaster", oControlMaster }, { NULL, oBadOption } }; @@ -755,6 +759,27 @@ parse_int: intptr = &options->server_alive_count_max; goto parse_int; + case oSendEnv: + while ((arg = strdelim(&s)) != NULL && *arg != '\0') { + if (strchr(arg, '=') != NULL) + fatal("%s line %d: Invalid environment name.", + filename, linenum); + if (options->num_send_env >= MAX_SEND_ENV) + fatal("%s line %d: too many send env.", + filename, linenum); + options->send_env[options->num_send_env++] = + xstrdup(arg); + } + break; + + case oControlPath: + charptr = &options->control_path; + goto parse_string; + + case oControlMaster: + intptr = &options->control_master; + goto parse_yesnoask; + case oDeprecated: debug("%s line %d: Deprecated option \"%s\"", filename, linenum, keyword); @@ -785,7 +810,8 @@ parse_int: */ int -read_config_file(const char *filename, const char *host, Options *options) +read_config_file(const char *filename, const char *host, Options *options, + int checkperm) { FILE *f; char line[1024]; @@ -793,10 +819,19 @@ read_config_file(const char *filename, const char *host, Options *options) int bad_options = 0; /* Open the file. */ - f = fopen(filename, "r"); - if (!f) + if ((f = fopen(filename, "r")) == NULL) return 0; + if (checkperm) { + struct stat sb; + + if (fstat(fileno(f), &sb) == -1) + fatal("fstat %s: %s", filename, strerror(errno)); + if (((sb.st_uid != 0 && sb.st_uid != getuid()) || + (sb.st_mode & 022) != 0)) + fatal("Bad owner or permissions on %s", filename); + } + debug("Reading configuration data %.200s", filename); /* @@ -886,6 +921,9 @@ initialize_options(Options * options) options->verify_host_key_dns = -1; options->server_alive_interval = -1; options->server_alive_count_max = -1; + options->num_send_env = 0; + options->control_path = NULL; + options->control_master = -1; } /* @@ -1008,6 +1046,8 @@ fill_default_options(Options * options) options->server_alive_interval = 0; if (options->server_alive_count_max == -1) options->server_alive_count_max = 3; + if (options->control_master == -1) + options->control_master = 0; /* options->proxy_command should not be set by default */ /* options->user will be set in the main program if appropriate */ /* options->hostname will be set in the main program if appropriate */ diff --git a/openssh/readconf.h b/openssh/readconf.h index 091d533..ec5116b 100644 --- a/openssh/readconf.h +++ b/openssh/readconf.h @@ -1,4 +1,4 @@ -/* $OpenBSD: readconf.h,v 1.60 2004/03/05 10:53:58 markus Exp $ */ +/* $OpenBSD: readconf.h,v 1.64 2004/07/11 17:48:47 deraadt Exp $ */ /* * Author: Tatu Ylonen @@ -27,6 +27,8 @@ typedef struct { } Forward; /* Data structure for representing option data. */ +#define MAX_SEND_ENV 256 + typedef struct { int forward_agent; /* Forward authentication agent. */ int forward_x11; /* Forward X11 display. */ @@ -104,14 +106,20 @@ typedef struct { int rekey_limit; int no_host_authentication_for_localhost; int identities_only; - int server_alive_interval; + int server_alive_interval; int server_alive_count_max; + + int num_send_env; + char *send_env[MAX_SEND_ENV]; + + char *control_path; + int control_master; } Options; void initialize_options(Options *); void fill_default_options(Options *); -int read_config_file(const char *, const char *, Options *); +int read_config_file(const char *, const char *, Options *, int); int process_config_line(Options *, const char *, char *, const char *, int, int *); diff --git a/openssh/readpass.h b/openssh/readpass.h deleted file mode 100644 index 229973c..0000000 --- a/openssh/readpass.h +++ /dev/null @@ -1,18 +0,0 @@ -/* $OpenBSD: readpass.h,v 1.6 2001/06/26 17:27:24 markus Exp $ */ - -/* - * Author: Tatu Ylonen - * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland - * All rights reserved - * - * As far as I am concerned, the code I have written for this software - * can be used freely for any purpose. Any derived versions of this - * software must be clearly marked as such, and if the derived work is - * incompatible with the protocol description in the RFC file, it must be - * called by a name other than "ssh" or "Secure Shell". - */ - -#define RP_ECHO 0x0001 -#define RP_ALLOW_STDIN 0x0002 - -char *read_passphrase(const char *, int); diff --git a/openssh/scard-opensc.c b/openssh/scard-opensc.c index a9b7ebc..dd2c28d 100644 --- a/openssh/scard-opensc.c +++ b/openssh/scard-opensc.c @@ -35,7 +35,7 @@ #include "key.h" #include "log.h" #include "xmalloc.h" -#include "readpass.h" +#include "misc.h" #include "scard.h" #if OPENSSL_VERSION_NUMBER < 0x00907000L && defined(CRYPTO_LOCK_ENGINE) diff --git a/openssh/servconf.c b/openssh/servconf.c index fb680b9..a959c4b 100644 --- a/openssh/servconf.c +++ b/openssh/servconf.c @@ -10,7 +10,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: servconf.c,v 1.130 2003/12/23 16:12:10 jakob Exp $"); +RCSID("$OpenBSD: servconf.c,v 1.137 2004/08/13 11:09:24 dtucker Exp $"); #include "ssh.h" #include "log.h" @@ -18,7 +18,6 @@ RCSID("$OpenBSD: servconf.c,v 1.130 2003/12/23 16:12:10 jakob Exp $"); #include "xmalloc.h" #include "compat.h" #include "pathnames.h" -#include "tildexpand.h" #include "misc.h" #include "cipher.h" #include "kex.h" @@ -80,7 +79,6 @@ initialize_server_options(ServerOptions *options) options->kerberos_get_afs_token = -1; options->gss_authentication=-1; options->gss_keyex=-1; - options->gss_use_session_ccache = -1; options->gss_cleanup_creds = -1; options->password_authentication = -1; options->kbd_interactive_authentication = -1; @@ -102,12 +100,14 @@ initialize_server_options(ServerOptions *options) options->max_startups_begin = -1; options->max_startups_rate = -1; options->max_startups = -1; + options->max_authtries = -1; options->banner = NULL; options->use_dns = -1; options->client_alive_interval = -1; options->client_alive_count_max = -1; options->authorized_keys_file = NULL; options->authorized_keys_file2 = NULL; + options->num_accept_env = 0; /* Needs to be accessable in many places */ use_privsep = -1; @@ -195,8 +195,6 @@ fill_default_server_options(ServerOptions *options) options->gss_authentication = 1; if (options->gss_keyex == -1) options->gss_keyex = 1; - if (options->gss_use_session_ccache == -1) - options->gss_use_session_ccache = 1; if (options->gss_cleanup_creds == -1) options->gss_cleanup_creds = 1; if (options->password_authentication == -1) @@ -223,6 +221,8 @@ fill_default_server_options(ServerOptions *options) options->max_startups_rate = 100; /* 100% */ if (options->max_startups_begin == -1) options->max_startups_begin = options->max_startups; + if (options->max_authtries == -1) + options->max_authtries = DEFAULT_AUTH_FAIL_MAX; if (options->use_dns == -1) options->use_dns = 1; if (options->client_alive_interval == -1) @@ -276,11 +276,13 @@ typedef enum { sPermitUserEnvironment, sUseLogin, sAllowTcpForwarding, sCompression, sAllowUsers, sDenyUsers, sAllowGroups, sDenyGroups, sIgnoreUserKnownHosts, sCiphers, sMacs, sProtocol, sPidFile, - sGatewayPorts, sPubkeyAuthentication, sXAuthLocation, sSubsystem, sMaxStartups, + sGatewayPorts, sPubkeyAuthentication, sXAuthLocation, sSubsystem, + sMaxStartups, sMaxAuthTries, sBanner, sUseDNS, sHostbasedAuthentication, sHostbasedUsesNameFromPacketOnly, sClientAliveInterval, sClientAliveCountMax, sAuthorizedKeysFile, sAuthorizedKeysFile2, - sGssAuthentication, sGssKeyEx, sGssUseSessionCredCache, sGssCleanupCreds, + sGssAuthentication, sGssCleanupCreds, sAcceptEnv, + sGssKeyEx, sUsePrivilegeSeparation, sDeprecated, sUnsupported } ServerOpCodes; @@ -335,14 +337,10 @@ static struct { #ifdef GSSAPI { "gssapiauthentication", sGssAuthentication }, { "gssapikeyexchange", sGssKeyEx }, - { "gssusesessionccache", sGssUseSessionCredCache }, - { "gssapiusesessioncredcache", sGssUseSessionCredCache }, { "gssapicleanupcredentials", sGssCleanupCreds }, #else { "gssapiauthentication", sUnsupported }, { "gssapikeyexchange", sUnsupported }, - { "gssusesessionccache", sUnsupported }, - { "gssapiusesessioncredcache", sUnsupported }, { "gssapicleanupcredentials", sUnsupported }, #endif #ifdef SESSION_HOOKS @@ -382,6 +380,7 @@ static struct { { "gatewayports", sGatewayPorts }, { "subsystem", sSubsystem }, { "maxstartups", sMaxStartups }, + { "maxauthtries", sMaxAuthTries }, { "banner", sBanner }, { "usedns", sUseDNS }, { "verifyreversemapping", sDeprecated }, @@ -391,6 +390,7 @@ static struct { { "authorizedkeysfile", sAuthorizedKeysFile }, { "authorizedkeysfile2", sAuthorizedKeysFile2 }, { "useprivilegeseparation", sUsePrivilegeSeparation}, + { "acceptenv", sAcceptEnv }, { NULL, sBadOption } }; @@ -677,10 +677,6 @@ parse_flag: intptr = &options->gss_keyex; goto parse_flag; - case sGssUseSessionCredCache: - intptr = &options->gss_use_session_ccache; - goto parse_flag; - case sGssCleanupCreds: intptr = &options->gss_cleanup_creds; goto parse_flag; @@ -918,6 +914,10 @@ parse_flag: options->max_startups = options->max_startups_begin; break; + case sMaxAuthTries: + intptr = &options->max_authtries; + goto parse_int; + case sBanner: charptr = &options->banner; goto parse_filename; @@ -942,6 +942,19 @@ parse_flag: intptr = &options->client_alive_count_max; goto parse_int; + case sAcceptEnv: + while ((arg = strdelim(&cp)) && *arg != '\0') { + if (strchr(arg, '=') != NULL) + fatal("%s line %d: Invalid environment name.", + filename, linenum); + if (options->num_accept_env >= MAX_ACCEPT_ENV) + fatal("%s line %d: too many allow env.", + filename, linenum); + options->accept_env[options->num_accept_env++] = + xstrdup(arg); + } + break; + case sDeprecated: logit("%s line %d: Deprecated option %s", filename, linenum, arg); @@ -969,26 +982,50 @@ parse_flag: /* Reads the server configuration file. */ void -read_server_config(ServerOptions *options, const char *filename) +load_server_config(const char *filename, Buffer *conf) { - int linenum, bad_options = 0; - char line[1024]; + char line[1024], *cp; FILE *f; - debug2("read_server_config: filename %s", filename); - f = fopen(filename, "r"); - if (!f) { + debug2("%s: filename %s", __func__, filename); + if ((f = fopen(filename, "r")) == NULL) { perror(filename); exit(1); } - linenum = 0; + buffer_clear(conf); while (fgets(line, sizeof(line), f)) { - /* Update line number counter. */ - linenum++; - if (process_server_config_line(options, line, filename, linenum) != 0) - bad_options++; + /* + * Trim out comments and strip whitespace + * NB - preserve newlines, they are needed to reproduce + * line numbers later for error messages + */ + if ((cp = strchr(line, '#')) != NULL) + memcpy(cp, "\n", 2); + cp = line + strspn(line, " \t\r"); + + buffer_append(conf, cp, strlen(cp)); } + buffer_append(conf, "\0", 1); fclose(f); + debug2("%s: done config len = %d", __func__, buffer_len(conf)); +} + +void +parse_server_config(ServerOptions *options, const char *filename, Buffer *conf) +{ + int linenum, bad_options = 0; + char *cp, *obuf, *cbuf; + + debug2("%s: config %s len %d", __func__, filename, buffer_len(conf)); + + obuf = cbuf = xstrdup(buffer_ptr(conf)); + linenum = 1; + while((cp = strsep(&cbuf, "\n")) != NULL) { + if (process_server_config_line(options, cp, filename, + linenum++) != 0) + bad_options++; + } + xfree(obuf); if (bad_options > 0) fatal("%s: terminating, %d bad configuration options", filename, bad_options); diff --git a/openssh/servconf.h b/openssh/servconf.h index bc1590d..7ce7f7f 100644 --- a/openssh/servconf.h +++ b/openssh/servconf.h @@ -1,4 +1,4 @@ -/* $OpenBSD: servconf.h,v 1.67 2003/12/23 16:12:10 jakob Exp $ */ +/* $OpenBSD: servconf.h,v 1.70 2004/06/24 19:30:54 djm Exp $ */ /* * Author: Tatu Ylonen @@ -16,6 +16,8 @@ #ifndef SERVCONF_H #define SERVCONF_H +#include "buffer.h" + #define MAX_PORTS 256 /* Max # ports. */ #define MAX_ALLOW_USERS 256 /* Max # users on allow list. */ @@ -24,6 +26,7 @@ #define MAX_DENY_GROUPS 256 /* Max # groups on deny list. */ #define MAX_SUBSYSTEMS 256 /* Max # subsystems. */ #define MAX_HOSTKEYS 256 /* Max # hostkeys. */ +#define MAX_ACCEPT_ENV 256 /* Max # of env vars. */ /* permit_root_login */ #define PERMIT_NOT_SET -1 @@ -32,6 +35,7 @@ #define PERMIT_NO_PASSWD 2 #define PERMIT_YES 3 +#define DEFAULT_AUTH_FAIL_MAX 6 /* Default for MaxAuthTries */ typedef struct { u_int num_ports; @@ -88,9 +92,7 @@ typedef struct { int kerberos_get_afs_token; /* If true, try to get AFS token if * authenticated with Kerberos. */ int gss_authentication; /* If true, permit GSSAPI authentication */ - int gss_keyex; - int gss_use_session_ccache; /* If true, delegated credentials are - * stored in a session specific cache */ + int gss_keyex; /* If true, permit GSSAPI key exchange. */ int gss_cleanup_creds; /* If true, destroy cred cache on logout */ int password_authentication; /* If true, permit password * authentication. */ @@ -115,9 +117,13 @@ typedef struct { char *subsystem_name[MAX_SUBSYSTEMS]; char *subsystem_command[MAX_SUBSYSTEMS]; + u_int num_accept_env; + char *accept_env[MAX_ACCEPT_ENV]; + int max_startups_begin; int max_startups_rate; int max_startups; + int max_authtries; char *banner; /* SSH-2 banner message */ int use_dns; int client_alive_interval; /* @@ -136,9 +142,9 @@ typedef struct { } ServerOptions; void initialize_server_options(ServerOptions *); -void read_server_config(ServerOptions *, const char *); void fill_default_server_options(ServerOptions *); int process_server_config_line(ServerOptions *, char *, const char *, int); - +void load_server_config(const char *, Buffer *); +void parse_server_config(ServerOptions *, const char *, Buffer *); #endif /* SERVCONF_H */ diff --git a/openssh/session.c b/openssh/session.c index d0d6991..09c3fe1 100644 --- a/openssh/session.c +++ b/openssh/session.c @@ -33,7 +33,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: session.c,v 1.172 2004/01/30 09:48:57 markus Exp $"); +RCSID("$OpenBSD: session.c,v 1.180 2004/07/28 09:40:29 markus Exp $"); #include "ssh.h" #include "ssh1.h" @@ -42,7 +42,7 @@ RCSID("$OpenBSD: session.c,v 1.172 2004/01/30 09:48:57 markus Exp $"); #include "sshpty.h" #include "packet.h" #include "buffer.h" -#include "mpaux.h" +#include "match.h" #include "uidswap.h" #include "compat.h" #include "channels.h" @@ -201,12 +201,11 @@ auth_input_request_forwarding(struct passwd * pw) static void display_loginmsg(void) { - if (buffer_len(&loginmsg) > 0) { - buffer_append(&loginmsg, "\0", 1); - printf("%s\n", (char *)buffer_ptr(&loginmsg)); - buffer_clear(&loginmsg); - } - fflush(stdout); + if (buffer_len(&loginmsg) > 0) { + buffer_append(&loginmsg, "\0", 1); + printf("%s", (char *)buffer_ptr(&loginmsg)); + buffer_clear(&loginmsg); + } } void @@ -285,7 +284,7 @@ do_authenticated1(Authctxt *authctxt) compression_level = packet_get_int(); packet_check_eom(); if (compression_level < 1 || compression_level > 9) { - packet_send_debug("Received illegal compression level %d.", + packet_send_debug("Received invalid compression level %d.", compression_level); break; } @@ -501,7 +500,11 @@ do_exec_no_pty(Session *s, const char *command) close(perr[1]); if (compat20) { - session_set_fds(s, pin[1], pout[0], s->is_subsystem ? -1 : perr[0]); + if (s->is_subsystem) { + close(perr[0]); + perr[0] = -1; + } + session_set_fds(s, pin[1], pout[0], perr[0]); } else { /* Enter the interactive session. */ server_loop(pid, pin[1], pout[0], perr[0]); @@ -712,14 +715,19 @@ do_exec(Session *s, const char *command) do_exec_no_pty(s, command); original_command = NULL; -} + /* + * Clear loginmsg: it's the child's responsibility to display + * it to the user, otherwise multiple sessions may accumulate + * multiple copies of the login messages. + */ + buffer_clear(&loginmsg); +} /* administrative, login(1)-like work */ void do_login(Session *s, const char *command) { - char *time_string; socklen_t fromlen; struct sockaddr_storage from; struct passwd * pw = s->pw; @@ -764,19 +772,6 @@ do_login(Session *s, const char *command) display_loginmsg(); -#ifndef NO_SSH_LASTLOG - if (options.print_lastlog && s->last_login_time != 0) { - time_string = ctime(&s->last_login_time); - if (strchr(time_string, '\n')) - *strchr(time_string, '\n') = 0; - if (strcmp(s->hostname, "") == 0) - printf("Last login: %s\r\n", time_string); - else - printf("Last login: %s from %s\r\n", time_string, - s->hostname); - } -#endif /* NO_SSH_LASTLOG */ - do_motd(); } @@ -1147,6 +1142,10 @@ do_setup_env(Session *s, const char *shell) if (!options.use_login) { /* Set basic environment. */ + for (i = 0; i < s->num_env; i++) + child_set_env(&env, &envsize, s->env[i].name, + s->env[i].val); + child_set_env(&env, &envsize, "USER", pw->pw_name); child_set_env(&env, &envsize, "LOGNAME", pw->pw_name); #ifdef _AIX @@ -1478,9 +1477,10 @@ do_setusercontext(struct passwd *pw) static void do_pwchange(Session *s) { + fflush(NULL); fprintf(stderr, "WARNING: Your password has expired.\n"); if (s->ttyfd != -1) { - fprintf(stderr, + fprintf(stderr, "You must change your password now and login again!\n"); execl(_PATH_PASSWD_PROG, "passwd", (char *)NULL); perror("passwd"); @@ -1603,6 +1603,13 @@ do_child(Session *s, const char *command) #else /* HAVE_OSF_SIA */ do_nologin(pw); do_setusercontext(pw); + /* + * PAM session modules in do_setusercontext may have + * generated messages, so if this in an interactive + * login then display them too. + */ + if (command == NULL) + display_loginmsg(); #endif /* HAVE_OSF_SIA */ } @@ -1903,12 +1910,6 @@ session_pty_req(Session *s) packet_disconnect("Protocol error: you already have a pty."); return 0; } - /* Get the time and hostname when the user last logged in. */ - if (options.print_lastlog) { - s->hostname[0] = '\0'; - s->last_login_time = get_last_login_time(s->pw->pw_uid, - s->pw->pw_name, s->hostname, sizeof(s->hostname)); - } s->term = packet_get_string(&len); @@ -2035,9 +2036,8 @@ session_exec_req(Session *s) static int session_break_req(Session *s) { - u_int break_length; - break_length = packet_get_int(); /* ignored */ + packet_get_int(); /* ignored */ packet_check_eom(); if (s->ttyfd == -1 || @@ -2046,6 +2046,41 @@ session_break_req(Session *s) return 1; } +static int +session_env_req(Session *s) +{ + char *name, *val; + u_int name_len, val_len, i; + + name = packet_get_string(&name_len); + val = packet_get_string(&val_len); + packet_check_eom(); + + /* Don't set too many environment variables */ + if (s->num_env > 128) { + debug2("Ignoring env request %s: too many env vars", name); + goto fail; + } + + for (i = 0; i < options.num_accept_env; i++) { + if (match_pattern(name, options.accept_env[i])) { + debug2("Setting env %d: %s=%s", s->num_env, name, val); + s->env = xrealloc(s->env, sizeof(*s->env) * + (s->num_env + 1)); + s->env[s->num_env].name = name; + s->env[s->num_env].val = val; + s->num_env++; + return (1); + } + } + debug2("Ignoring env request %s: disallowed name", name); + + fail: + xfree(name); + xfree(val); + return (0); +} + static int session_auth_agent_req(Session *s) { @@ -2093,13 +2128,16 @@ session_input_channel_req(Channel *c, const char *rtype) success = session_auth_agent_req(s); } else if (strcmp(rtype, "subsystem") == 0) { success = session_subsystem_req(s); - } else if (strcmp(rtype, "break") == 0) { - success = session_break_req(s); + } else if (strcmp(rtype, "env") == 0) { + success = session_env_req(s); } } if (strcmp(rtype, "window-change") == 0) { success = session_window_change_req(s); + } else if (strcmp(rtype, "break") == 0) { + success = session_break_req(s); } + return success; } @@ -2232,6 +2270,8 @@ session_exit_message(Session *s, int status) void session_close(Session *s) { + int i; + debug("session_close: session %d pid %ld", s->self, (long)s->pid); if (s->ttyfd != -1) session_pty_cleanup(s); @@ -2246,6 +2286,12 @@ session_close(Session *s) if (s->auth_proto) xfree(s->auth_proto); s->used = 0; + for (i = 0; i < s->num_env; i++) { + xfree(s->env[i].name); + xfree(s->env[i].val); + } + if (s->env != NULL) + xfree(s->env); session_proctitle(s); } diff --git a/openssh/session.h b/openssh/session.h index 405b8fe..48be507 100644 --- a/openssh/session.h +++ b/openssh/session.h @@ -1,4 +1,4 @@ -/* $OpenBSD: session.h,v 1.21 2003/09/23 20:17:11 markus Exp $ */ +/* $OpenBSD: session.h,v 1.23 2004/07/17 05:31:41 dtucker Exp $ */ /* * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. @@ -39,9 +39,6 @@ struct Session { int ptyfd, ttyfd, ptymaster; u_int row, col, xpixel, ypixel; char tty[TTYSZ]; - /* last login */ - char hostname[MAXHOSTNAMELEN]; - time_t last_login_time; /* X11 */ u_int display_number; char *display; @@ -53,6 +50,11 @@ struct Session { /* proto 2 */ int chanid; int is_subsystem; + int num_env; + struct { + char *name; + char *val; + } *env; }; void do_authenticated(Authctxt *); diff --git a/openssh/ssh-agent.c b/openssh/ssh-agent.c index f5fce6b..bc4d8d3 100644 --- a/openssh/ssh-agent.c +++ b/openssh/ssh-agent.c @@ -35,7 +35,7 @@ #include "includes.h" #include "openbsd-compat/sys-queue.h" -RCSID("$OpenBSD: ssh-agent.c,v 1.117 2003/12/02 17:01:15 markus Exp $"); +RCSID("$OpenBSD: ssh-agent.c,v 1.120 2004/08/11 21:43:05 avsm Exp $"); #include #include @@ -50,7 +50,6 @@ RCSID("$OpenBSD: ssh-agent.c,v 1.117 2003/12/02 17:01:15 markus Exp $"); #include "authfd.h" #include "compat.h" #include "log.h" -#include "readpass.h" #include "misc.h" #ifdef SMARTCARD @@ -107,11 +106,7 @@ char socket_dir[1024]; int locked = 0; char *lock_passwd = NULL; -#ifdef HAVE___PROGNAME extern char *__progname; -#else -char *__progname; -#endif /* Default lifetime (0 == forever) */ static int lifetime = 0; @@ -790,8 +785,7 @@ new_socket(sock_type type, int fd) { u_int i, old_alloc, new_alloc; - if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0) - error("fcntl O_NONBLOCK: %s", strerror(errno)); + set_nonblock(fd); if (fd > max_fd) max_fd = fd; @@ -822,7 +816,7 @@ new_socket(sock_type type, int fd) } static int -prepare_select(fd_set **fdrp, fd_set **fdwp, int *fdl, int *nallocp) +prepare_select(fd_set **fdrp, fd_set **fdwp, int *fdl, u_int *nallocp) { u_int i, sz; int n = 0; @@ -1008,7 +1002,8 @@ int main(int ac, char **av) { int c_flag = 0, d_flag = 0, k_flag = 0, s_flag = 0; - int sock, fd, ch, nalloc; + int sock, fd, ch; + u_int nalloc; char *shell, *format, *pidstr, *agentsocket = NULL; fd_set *readsetp = NULL, *writesetp = NULL; struct sockaddr_un sunaddr; diff --git a/openssh/ssh-gss.h b/openssh/ssh-gss.h index 4183bad..d59eb29 100644 --- a/openssh/ssh-gss.h +++ b/openssh/ssh-gss.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-gss.h,v 1.4 2003/11/17 11:06:07 markus Exp $ */ +/* $OpenBSD: ssh-gss.h,v 1.5 2004/06/21 17:36:31 avsm Exp $ */ /* * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved. * @@ -110,40 +110,42 @@ typedef struct { extern ssh_gssapi_mech *supported_mechs[]; -char *ssh_gssapi_client_mechanisms(char *host); -gss_OID ssh_gssapi_client_id_kex(Gssctxt *ctx, char *name); -int ssh_gssapi_check_oid(Gssctxt *ctx, void *data, size_t len); -void ssh_gssapi_set_oid_data(Gssctxt *ctx, void *data, size_t len); -void ssh_gssapi_set_oid(Gssctxt *ctx, gss_OID oid); -void ssh_gssapi_supported_oids(gss_OID_set *oidset); -ssh_gssapi_mech *ssh_gssapi_get_ctype(Gssctxt *ctxt); - -OM_uint32 ssh_gssapi_import_name(Gssctxt *ctx, const char *host); -OM_uint32 ssh_gssapi_acquire_cred(Gssctxt *ctx); -OM_uint32 ssh_gssapi_init_ctx(Gssctxt *ctx, int deleg_creds, - gss_buffer_desc *recv_tok, gss_buffer_desc *send_tok, OM_uint32 *flags); -OM_uint32 ssh_gssapi_accept_ctx(Gssctxt *ctx, - gss_buffer_desc *recv_tok, gss_buffer_desc *send_tok, OM_uint32 *flags); -OM_uint32 ssh_gssapi_getclient(Gssctxt *ctx, ssh_gssapi_client *); -void ssh_gssapi_error(Gssctxt *ctx); -char *ssh_gssapi_last_error(Gssctxt *ctxt, OM_uint32 *maj, OM_uint32 *min); -void ssh_gssapi_build_ctx(Gssctxt **ctx); -void ssh_gssapi_delete_ctx(Gssctxt **ctx); +char *ssh_gssapi_client_mechanisms(char *); +gss_OID ssh_gssapi_client_id_kex(Gssctxt *, char *); + +int ssh_gssapi_check_oid(Gssctxt *, void *, size_t); +void ssh_gssapi_set_oid_data(Gssctxt *, void *, size_t); +void ssh_gssapi_set_oid(Gssctxt *, gss_OID); +void ssh_gssapi_supported_oids(gss_OID_set *); +ssh_gssapi_mech *ssh_gssapi_get_ctype(Gssctxt *); + +OM_uint32 ssh_gssapi_import_name(Gssctxt *, const char *); +OM_uint32 ssh_gssapi_acquire_cred(Gssctxt *); +OM_uint32 ssh_gssapi_init_ctx(Gssctxt *, int, + gss_buffer_desc *, gss_buffer_desc *, OM_uint32 *); +OM_uint32 ssh_gssapi_accept_ctx(Gssctxt *, + gss_buffer_desc *, gss_buffer_desc *, OM_uint32 *); +OM_uint32 ssh_gssapi_getclient(Gssctxt *, ssh_gssapi_client *); +void ssh_gssapi_error(Gssctxt *); +char *ssh_gssapi_last_error(Gssctxt *, OM_uint32 *, OM_uint32 *); +void ssh_gssapi_build_ctx(Gssctxt **); +void ssh_gssapi_delete_ctx(Gssctxt **); OM_uint32 ssh_gssapi_sign(Gssctxt *, gss_buffer_t, gss_buffer_t); -OM_uint32 ssh_gssapi_server_ctx(Gssctxt **ctx, gss_OID oid); +OM_uint32 ssh_gssapi_server_ctx(Gssctxt **, gss_OID); void ssh_gssapi_buildmic(Buffer *, const char *, const char *, const char *); int ssh_gssapi_check_mechanism(gss_OID oid, char *host); /* In the server */ +char *ssh_gssapi_server_mechanisms(); gss_OID ssh_gssapi_server_id_kex(char *name); -int ssh_gssapi_userok(char *name); int ssh_gssapi_localname(char **name); + +int ssh_gssapi_userok(char *name); OM_uint32 ssh_gssapi_checkmic(Gssctxt *, gss_buffer_t, gss_buffer_t); -void ssh_gssapi_do_child(char ***envp, u_int *envsizep); +void ssh_gssapi_do_child(char ***, u_int *); void ssh_gssapi_cleanup_creds(void); void ssh_gssapi_storecreds(void); -char *ssh_gssapi_server_mechanisms(); #ifdef MECHGLUE gss_cred_id_t __gss_get_mechanism_cred diff --git a/openssh/ssh-keyscan.c b/openssh/ssh-keyscan.c index 266b23c..3cb52ac 100644 --- a/openssh/ssh-keyscan.c +++ b/openssh/ssh-keyscan.c @@ -7,7 +7,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: ssh-keyscan.c,v 1.47 2004/03/08 09:38:05 djm Exp $"); +RCSID("$OpenBSD: ssh-keyscan.c,v 1.50 2004/08/11 21:44:32 avsm Exp $"); #include "openbsd-compat/sys-queue.h" @@ -49,11 +49,7 @@ int timeout = 5; int maxfd; #define MAXCON (maxfd - 10) -#ifdef HAVE___PROGNAME extern char *__progname; -#else -char *__progname; -#endif fd_set *read_wait; size_t read_wait_size; int ncon; @@ -349,6 +345,7 @@ keygrab_ssh2(con *c) "ssh-dss": "ssh-rsa"; c->c_kex = kex_setup(myproposal); c->c_kex->kex[KEX_DH_GRP1_SHA1] = kexdh_client; + c->c_kex->kex[KEX_DH_GRP14_SHA1] = kexdh_client; c->c_kex->kex[KEX_DH_GEX_SHA1] = kexgex_client; c->c_kex->verify_host_key = hostjump; @@ -396,8 +393,8 @@ tcpconnect(char *host) error("socket: %s", strerror(errno)); continue; } - if (fcntl(s, F_SETFL, O_NONBLOCK) < 0) - fatal("F_SETFL: %s", strerror(errno)); + if (set_nonblock(s) == -1) + fatal("%s: set_nonblock(%d)", __func__, s); if (connect(s, ai->ai_addr, ai->ai_addrlen) < 0 && errno != EINPROGRESS) error("connect (`%s'): %s", host, strerror(errno)); @@ -497,7 +494,7 @@ congreet(int s) bufsiz = sizeof(buf); cp = buf; - while (bufsiz-- && (n = read(s, cp, 1)) == 1 && *cp != '\n') { + while (bufsiz-- && (n = atomicio(read, s, cp, 1)) == 1 && *cp != '\n') { if (*cp == '\r') *cp = '\n'; cp++; @@ -563,7 +560,7 @@ conread(int s) congreet(s); return; } - n = read(s, c->c_data + c->c_off, c->c_len - c->c_off); + n = atomicio(read, s, c->c_data + c->c_off, c->c_len - c->c_off); if (n < 0) { error("read (%s): %s", c->c_name, strerror(errno)); confree(s); diff --git a/openssh/ssh-keysign.c b/openssh/ssh-keysign.c index 9e9ebe2..5176557 100644 --- a/openssh/ssh-keysign.c +++ b/openssh/ssh-keysign.c @@ -22,7 +22,7 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "includes.h" -RCSID("$OpenBSD: ssh-keysign.c,v 1.15 2004/01/19 21:25:15 markus Exp $"); +RCSID("$OpenBSD: ssh-keysign.c,v 1.16 2004/04/18 23:10:26 djm Exp $"); #include #include @@ -41,15 +41,12 @@ RCSID("$OpenBSD: ssh-keysign.c,v 1.15 2004/01/19 21:25:15 markus Exp $"); #include "canohost.h" #include "pathnames.h" #include "readconf.h" +#include "uidswap.h" /* XXX readconf.c needs these */ uid_t original_real_uid; -#ifdef HAVE___PROGNAME extern char *__progname; -#else -char *__progname; -#endif static int valid_request(struct passwd *pw, char *host, Key **ret, u_char *data, @@ -154,8 +151,11 @@ main(int argc, char **argv) key_fd[0] = open(_PATH_HOST_RSA_KEY_FILE, O_RDONLY); key_fd[1] = open(_PATH_HOST_DSA_KEY_FILE, O_RDONLY); - seteuid(getuid()); - setuid(getuid()); + if ((pw = getpwuid(getuid())) == NULL) + fatal("getpwuid failed"); + pw = pwcopy(pw); + + permanently_set_uid(pw); init_rng(); seed_rng(); @@ -168,7 +168,7 @@ main(int argc, char **argv) /* verify that ssh-keysign is enabled by the admin */ original_real_uid = getuid(); /* XXX readconf.c needs this */ initialize_options(&options); - (void)read_config_file(_PATH_HOST_CONFIG_FILE, "", &options); + (void)read_config_file(_PATH_HOST_CONFIG_FILE, "", &options, 0); fill_default_options(&options); if (options.enable_ssh_keysign != 1) fatal("ssh-keysign not enabled in %s", @@ -177,10 +177,6 @@ main(int argc, char **argv) if (key_fd[0] == -1 && key_fd[1] == -1) fatal("could not open any host key"); - if ((pw = getpwuid(getuid())) == NULL) - fatal("getpwuid failed"); - pw = pwcopy(pw); - SSLeay_add_all_algorithms(); for (i = 0; i < 256; i++) rnd[i] = arc4random(); diff --git a/openssh/ssh-rand-helper.c b/openssh/ssh-rand-helper.c index 9c9c495..2d8707e 100644 --- a/openssh/ssh-rand-helper.c +++ b/openssh/ssh-rand-helper.c @@ -63,15 +63,7 @@ RCSID("$Id$"); # define SSH_PRNG_COMMAND_FILE SSHDIR "/ssh_prng_cmds" #endif -#ifdef HAVE___PROGNAME extern char *__progname; -#else -char *__progname; -#endif - -#ifndef offsetof -# define offsetof(type, member) ((size_t) &((type *)0)->member) -#endif #define WHITESPACE " \t\n" diff --git a/openssh/ssh.1 b/openssh/ssh.1 index 31eb66c..0ff77ea 100644 --- a/openssh/ssh.1 +++ b/openssh/ssh.1 @@ -34,7 +34,7 @@ .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.\" $OpenBSD: ssh.1,v 1.182 2004/03/05 10:53:58 markus Exp $ +.\" $OpenBSD: ssh.1,v 1.194 2004/08/12 21:41:13 jakob Exp $ .Dd September 25, 1999 .Dt SSH 1 .Os @@ -43,14 +43,14 @@ .Nd OpenSSH SSH client (remote login program) .Sh SYNOPSIS .Nm ssh -.Op Fl 1246AaCfgkNnqsTtVvXxY +.Op Fl 1246AaCfgkMNnqsTtVvXxY .Op Fl b Ar bind_address .Op Fl c Ar cipher_spec +.Bk -words .Op Fl D Ar port .Op Fl e Ar escape_char .Op Fl F Ar configfile .Op Fl i Ar identity_file -.Bk -words .Oo Fl L Xo .Sm off .Ar port : @@ -74,6 +74,7 @@ .Sm on .Xc .Oc +.Op Fl S Ar ctl .Oo Ar user Ns @ Oc Ns Ar hostname .Op Ar command .Sh DESCRIPTION @@ -241,8 +242,8 @@ Additionally, supports hostbased or challenge response authentication. .Pp Protocol 2 provides additional mechanisms for confidentiality -(the traffic is encrypted using 3DES, Blowfish, CAST128 or Arcfour) -and integrity (hmac-md5, hmac-sha1). +(the traffic is encrypted using AES, 3DES, Blowfish, CAST128 or Arcfour) +and integrity (hmac-md5, hmac-sha1, hmac-ripemd160). Note that protocol 1 lacks a strong mechanism for ensuring the integrity of the connection. .Ss Login session and remote execution @@ -302,11 +303,18 @@ Display a list of escape characters. Send a BREAK to the remote system (only useful for SSH protocol version 2 and if the peer supports it). .It Cm ~C -Open command line (only useful for adding port forwardings using the +Open command line. +Currently this allows the addition of port forwardings using the .Fl L and .Fl R -options). +options (see below). +It also allows the cancellation of existing remote port-forwardings +using +.Fl KR Ar hostport . +Basic help is available, using the +.Fl h +option. .It Cm ~R Request rekeying of the connection (only useful for SSH protocol version 2 and if the peer supports it). @@ -392,6 +400,15 @@ The option can be used to prevent logins to machines whose host key is not known or has changed. .Pp +.Nm +can be configured to verify host identification using fingerprint resource +records (SSHFP) published in DNS. +The +.Cm VerifyHostKeyDNS +option can be used to control how DNS lookups are performed. +SSHFP resource records can be generated using +.Xr ssh-keygen 1 . +.Pp The options are as follows: .Bl -tag -width Ds .It Fl 1 @@ -442,13 +459,18 @@ The default value can be set on a host-by-host basis in the configuration files; see the .Cm Compression option. -.It Fl c Ar blowfish | 3des | des -Selects the cipher to use for encrypting the session. -.Ar 3des -is used by default. -It is believed to be secure. +.It Fl c Ar cipher_spec +Selects the cipher specification for encrypting the session. +.Pp +Protocol version 1 allows specification of a single cipher. +The suported values are +.Dq 3des , +.Dq blowfish +and +.Dq des . .Ar 3des (triple-des) is an encrypt-decrypt-encrypt triple with three different keys. +It is believed to be secure. .Ar blowfish is a fast block cipher; it appears very secure and is much faster than .Ar 3des . @@ -460,12 +482,30 @@ that do not support the .Ar 3des cipher. Its use is strongly discouraged due to cryptographic weaknesses. -.It Fl c Ar cipher_spec -Additionally, for protocol version 2 a comma-separated list of ciphers can -be specified in order of preference. -See -.Cm Ciphers -for more information. +The default is +.Dq 3des . +.Pp +For protocol version 2 +.Ar cipher_spec +is a comma-separated list of ciphers +listed in order of preference. +The supported ciphers are +.Dq 3des-cbc , +.Dq aes128-cbc , +.Dq aes192-cbc , +.Dq aes256-cbc , +.Dq aes128-ctr , +.Dq aes192-ctr , +.Dq aes256-ctr , +.Dq arcfour , +.Dq blowfish-cbc , +and +.Dq cast128-cbc . +The default is +.Bd -literal + ``aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,arcfour, + aes192-cbc,aes256-cbc'' +.Ed .It Fl D Ar port Specifies a local .Dq dynamic @@ -568,6 +608,17 @@ IPv6 addresses can be specified with an alternative syntax: .It Fl l Ar login_name Specifies the user to log in as on the remote machine. This also may be specified on a per-host basis in the configuration file. +.It Fl M +Places the +.Nm +client into +.Dq master +mode for connection sharing. +Refer to the description of +.Cm ControlMaster +in +.Xr ssh_config 5 +for details. .It Fl m Ar mac_spec Additionally, for protocol version 2 a comma-separated list of MAC (message authentication code) algorithms can @@ -618,7 +669,9 @@ For full details of the options listed below, and their possible values, see .It Compression .It CompressionLevel .It ConnectionAttempts -.It ConnectionTimeout +.It ConnectTimeout +.It ControlMaster +.It ControlPath .It DynamicForward .It EscapeChar .It ForwardAgent @@ -649,6 +702,7 @@ For full details of the options listed below, and their possible values, see .It RemoteForward .It RhostsRSAAuthentication .It RSAAuthentication +.It SendEnv .It ServerAliveInterval .It ServerAliveCountMax .It SmartcardDevice @@ -693,6 +747,15 @@ IPv6 addresses can be specified with an alternative syntax: .Ar hostport . .Xc .Sm on +.It Fl S Ar ctl +Specifies the location of a control socket for connection sharing. +Refer to the description of +.Cm ControlPath +and +.Cm ControlMaster +in +.Xr ssh_config 5 +for details. .It Fl s May be used to request invocation of a subsystem on the remote system. Subsystems are a feature of the SSH2 protocol which facilitate the use @@ -885,6 +948,8 @@ the convenience of the user. This is the per-user configuration file. The file format and configuration options are described in .Xr ssh_config 5 . +Because of the potential for abuse, this file must have strict permissions: +read/write for the user, and not accessible by others. .It Pa $HOME/.ssh/authorized_keys Lists the public keys (RSA/DSA) that can be used for logging in as this user. The format of this file is described in the diff --git a/openssh/ssh.c b/openssh/ssh.c index 539ba7f..41f22ec 100644 --- a/openssh/ssh.c +++ b/openssh/ssh.c @@ -40,7 +40,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: ssh.c,v 1.209 2004/03/11 10:21:17 markus Exp $"); +RCSID("$OpenBSD: ssh.c,v 1.224 2004/07/28 09:40:29 markus Exp $"); #include #include @@ -53,31 +53,31 @@ RCSID("$OpenBSD: ssh.c,v 1.209 2004/03/11 10:21:17 markus Exp $"); #include "xmalloc.h" #include "packet.h" #include "buffer.h" +#include "bufaux.h" #include "channels.h" #include "key.h" #include "authfd.h" #include "authfile.h" #include "pathnames.h" +#include "dispatch.h" #include "clientloop.h" #include "log.h" #include "readconf.h" #include "sshconnect.h" -#include "tildexpand.h" -#include "dispatch.h" #include "misc.h" #include "kex.h" #include "mac.h" -#include "sshtty.h" +#include "sshpty.h" +#include "match.h" +#include "msg.h" +#include "monitor_fdpass.h" +#include "uidswap.h" #ifdef SMARTCARD #include "scard.h" #endif -#ifdef HAVE___PROGNAME extern char *__progname; -#else -char *__progname; -#endif /* Flag indicating whether debug mode is on. This can be set on the command line. */ int debug_flag = 0; @@ -141,16 +141,23 @@ static int client_global_request_id = 0; /* pid of proxycommand child process */ pid_t proxy_command_pid = 0; +/* fd to control socket */ +int control_fd = -1; + +/* Only used in control client mode */ +volatile sig_atomic_t control_client_terminate = 0; +u_int control_server_pid = 0; + /* Prints a help message to the user. This function never returns. */ static void usage(void) { fprintf(stderr, -"usage: ssh [-1246AaCfghkNnqsTtVvXxY] [-b bind_address] [-c cipher_spec]\n" +"usage: ssh [-1246AaCfghkMNnqsTtVvXxY] [-b bind_address] [-c cipher_spec]\n" " [-D port] [-e escape_char] [-F configfile] [-i identity_file]\n" " [-L port:host:hostport] [-l login_name] [-m mac_spec] [-o option]\n" -" [-p port] [-R port:host:hostport] [user@]hostname [command]\n" +" [-p port] [-R port:host:hostport] [-S ctl] [user@]hostname [command]\n" ); exit(1); } @@ -158,6 +165,7 @@ usage(void) static int ssh_session(void); static int ssh_session2(void); static void load_public_identity_files(void); +static void control_client(const char *path); /* * Main program for the ssh client. @@ -228,7 +236,7 @@ main(int ac, char **av) again: while ((opt = getopt(ac, av, - "1246ab:c:e:fgi:kl:m:no:p:qstvxACD:F:I:L:NPR:TVXY")) != -1) { + "1246ab:c:e:fgi:kl:m:no:p:qstvxACD:F:I:L:MNPR:S:TVXY")) != -1) { switch (opt) { case '1': options.protocol = SSH_PROTO_1; @@ -337,7 +345,7 @@ again: if (ciphers_valid(optarg)) { /* SSH2 only */ options.ciphers = xstrdup(optarg); - options.cipher = SSH_CIPHER_ILLEGAL; + options.cipher = SSH_CIPHER_INVALID; } else { /* SSH1 only */ options.cipher = cipher_number(optarg); @@ -364,6 +372,10 @@ again: exit(1); } break; + case 'M': + options.control_master = + (options.control_master >= 1) ? 2 : 1; + break; case 'p': options.port = a2port(optarg); if (options.port == 0) { @@ -432,6 +444,11 @@ again: case 's': subsystem_flag = 1; break; + case 'S': + if (options.control_path != NULL) + free(options.control_path); + options.control_path = xstrdup(optarg); + break; case 'b': options.bind_address = optarg; break; @@ -526,7 +543,7 @@ again: * file if the user specifies a config file on the command line. */ if (config != NULL) { - if (!read_config_file(config, host, &options)) + if (!read_config_file(config, host, &options, 0)) fatal("Can't open user config file %.100s: " "%.100s", config, strerror(errno)); } else { @@ -541,24 +558,25 @@ again: #ifdef GSSAPI snprintf(buf, sizeof buf, "%.100s/%.100s.gssapi", pw->pw_dir, _PATH_SSH_USER_CONFFILE); - (void)read_config_file(buf, host, &options); + (void)read_config_file(buf, host, &options, 1); #ifdef GSI snprintf(buf, sizeof buf, "%.100s/%.100s.gsi", pw->pw_dir, _PATH_SSH_USER_CONFFILE); - (void)read_config_file(buf, host, &options); + (void)read_config_file(buf, host, &options, 1); #endif #if defined(KRB5) snprintf(buf, sizeof buf, "%.100s/%.100s.krb", pw->pw_dir, _PATH_SSH_USER_CONFFILE); - (void)read_config_file(buf, host, &options); + (void)read_config_file(buf, host, &options, 1); #endif #endif snprintf(buf, sizeof buf, "%.100s/%.100s", pw->pw_dir, _PATH_SSH_USER_CONFFILE); - (void)read_config_file(buf, host, &options); + (void)read_config_file(buf, host, &options, 1); /* Read systemwide configuration file after use config. */ - (void)read_config_file(_PATH_HOST_CONFIG_FILE, host, &options); + (void)read_config_file(_PATH_HOST_CONFIG_FILE, host, + &options, 0); } /* Fill configuration defaults. */ @@ -591,6 +609,13 @@ again: strcmp(options.proxy_command, "none") == 0) options.proxy_command = NULL; + if (options.control_path != NULL) { + options.control_path = tilde_expand_filename( + options.control_path, original_real_uid); + } + if (options.control_path != NULL && options.control_master == 0) + control_client(options.control_path); /* This doesn't return */ + /* Open a connection to the remote host. */ if (ssh_connect(host, &hostaddr, options.port, options.address_family, options.connection_attempts, @@ -646,8 +671,10 @@ again: * user's home directory if it happens to be on a NFS volume where * root is mapped to nobody. */ - seteuid(original_real_uid); - setuid(original_real_uid); + if (original_effective_uid == 0) { + PRIV_START; + permanently_set_uid(pw); + } /* * Now that we are back to our own permissions, create ~/.ssh @@ -703,6 +730,9 @@ again: exit_status = compat20 ? ssh_session2() : ssh_session(); packet_close(); + if (options.control_path != NULL && control_fd != -1) + unlink(options.control_path); + /* * Send SIGHUP to proxy command if used. We don't wait() in * case it hangs and instead rely on init to reap the child @@ -802,17 +832,17 @@ x11_get_proto(char **_proto, char **_data) * for the local connection. */ if (!got_data) { - u_int32_t rand = 0; + u_int32_t rnd = 0; logit("Warning: No xauth data; " "using fake authentication data for X11 forwarding."); strlcpy(proto, SSH_X11_PROTO, sizeof proto); for (i = 0; i < 16; i++) { if (i % 4 == 0) - rand = arc4random(); + rnd = arc4random(); snprintf(data + 2 * i, sizeof data - 2 * i, "%02x", - rand & 0xff); - rand >>= 8; + rnd & 0xff); + rnd >>= 8; } } } @@ -999,7 +1029,7 @@ ssh_session(void) } static void -client_subsystem_reply(int type, u_int32_t seq, void *ctxt) +ssh_subsystem_reply(int type, u_int32_t seq, void *ctxt) { int id, len; @@ -1031,40 +1061,53 @@ client_global_request_reply_fwd(int type, u_int32_t seq, void *ctxt) options.remote_forwards[i].port); } -/* request pty/x11/agent/tcpfwd/shell for channel */ static void -ssh_session2_setup(int id, void *arg) +ssh_control_listener(void) { - int len; - int interactive = 0; - struct termios tio; + struct sockaddr_un addr; + mode_t old_umask; + int addr_len; - debug2("ssh_session2_setup: id %d", id); + if (options.control_path == NULL || options.control_master <= 0) + return; - if (tty_flag) { - struct winsize ws; - char *cp; - cp = getenv("TERM"); - if (!cp) - cp = ""; - /* Store window size in the packet. */ - if (ioctl(fileno(stdin), TIOCGWINSZ, &ws) < 0) - memset(&ws, 0, sizeof(ws)); + memset(&addr, '\0', sizeof(addr)); + addr.sun_family = AF_UNIX; + addr_len = offsetof(struct sockaddr_un, sun_path) + + strlen(options.control_path) + 1; - channel_request_start(id, "pty-req", 0); - packet_put_cstring(cp); - packet_put_int(ws.ws_col); - packet_put_int(ws.ws_row); - packet_put_int(ws.ws_xpixel); - packet_put_int(ws.ws_ypixel); - tio = get_saved_tio(); - tty_make_modes(/*ignored*/ 0, &tio); - packet_send(); - interactive = 1; - /* XXX wait for reply */ + if (strlcpy(addr.sun_path, options.control_path, + sizeof(addr.sun_path)) >= sizeof(addr.sun_path)) + fatal("ControlPath too long"); + + if ((control_fd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) + fatal("%s socket(): %s\n", __func__, strerror(errno)); + + old_umask = umask(0177); + if (bind(control_fd, (struct sockaddr*)&addr, addr_len) == -1) { + control_fd = -1; + if (errno == EINVAL) + fatal("ControlSocket %s already exists", + options.control_path); + else + fatal("%s bind(): %s\n", __func__, strerror(errno)); } - if (options.forward_x11 && - getenv("DISPLAY") != NULL) { + umask(old_umask); + + if (listen(control_fd, 64) == -1) + fatal("%s listen(): %s\n", __func__, strerror(errno)); + + set_nonblock(control_fd); +} + +/* request pty/x11/agent/tcpfwd/shell for channel */ +static void +ssh_session2_setup(int id, void *arg) +{ + extern char **environ; + + int interactive = tty_flag; + if (options.forward_x11 && getenv("DISPLAY") != NULL) { char *proto, *data; /* Get reasonable local authentication information. */ x11_get_proto(&proto, &data); @@ -1082,27 +1125,8 @@ ssh_session2_setup(int id, void *arg) packet_send(); } - len = buffer_len(&command); - if (len > 0) { - if (len > 900) - len = 900; - if (subsystem_flag) { - debug("Sending subsystem: %.*s", len, (u_char *)buffer_ptr(&command)); - channel_request_start(id, "subsystem", /*want reply*/ 1); - /* register callback for reply */ - /* XXX we assume that client_loop has already been called */ - dispatch_set(SSH2_MSG_CHANNEL_FAILURE, &client_subsystem_reply); - dispatch_set(SSH2_MSG_CHANNEL_SUCCESS, &client_subsystem_reply); - } else { - debug("Sending command: %.*s", len, (u_char *)buffer_ptr(&command)); - channel_request_start(id, "exec", 0); - } - packet_put_string(buffer_ptr(&command), buffer_len(&command)); - packet_send(); - } else { - channel_request_start(id, "shell", 0); - packet_send(); - } + client_session2_setup(id, tty_flag, subsystem_flag, getenv("TERM"), + NULL, fileno(stdin), &command, environ, &ssh_subsystem_reply); packet_set_interactive(interactive); } @@ -1148,7 +1172,7 @@ ssh_session2_open(void) channel_send_open(c->self); if (!no_shell_flag) - channel_register_confirm(c->self, ssh_session2_setup); + channel_register_confirm(c->self, ssh_session2_setup, NULL); return c->self; } @@ -1160,6 +1184,7 @@ ssh_session2(void) /* XXX should be pre-session */ ssh_init_forwarding(); + ssh_control_listener(); if (!no_shell_flag || (datafellows & SSH_BUG_DUMMYCHAN)) id = ssh_session2_open(); @@ -1213,3 +1238,149 @@ load_public_identity_files(void) options.identity_keys[i] = public; } } + +static void +control_client_sighandler(int signo) +{ + control_client_terminate = signo; +} + +static void +control_client_sigrelay(int signo) +{ + if (control_server_pid > 1) + kill(control_server_pid, signo); +} + +static int +env_permitted(char *env) +{ + int i; + char name[1024], *cp; + + strlcpy(name, env, sizeof(name)); + if ((cp = strchr(name, '=')) == NULL) + return (0); + + *cp = '\0'; + + for (i = 0; i < options.num_send_env; i++) + if (match_pattern(name, options.send_env[i])) + return (1); + + return (0); +} + +static void +control_client(const char *path) +{ + struct sockaddr_un addr; + int i, r, sock, exitval, num_env, addr_len; + Buffer m; + char *cp; + extern char **environ; + + memset(&addr, '\0', sizeof(addr)); + addr.sun_family = AF_UNIX; + addr_len = offsetof(struct sockaddr_un, sun_path) + + strlen(path) + 1; + + if (strlcpy(addr.sun_path, path, + sizeof(addr.sun_path)) >= sizeof(addr.sun_path)) + fatal("ControlPath too long"); + + if ((sock = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) + fatal("%s socket(): %s", __func__, strerror(errno)); + + if (connect(sock, (struct sockaddr*)&addr, addr_len) == -1) + fatal("Couldn't connect to %s: %s", path, strerror(errno)); + + if ((cp = getenv("TERM")) == NULL) + cp = ""; + + buffer_init(&m); + + /* Get PID of controlee */ + if (ssh_msg_recv(sock, &m) == -1) + fatal("%s: msg_recv", __func__); + if (buffer_get_char(&m) != 0) + fatal("%s: wrong version", __func__); + /* Connection allowed? */ + if (buffer_get_int(&m) != 1) + fatal("Connection to master denied"); + control_server_pid = buffer_get_int(&m); + + buffer_clear(&m); + buffer_put_int(&m, tty_flag); + buffer_put_int(&m, subsystem_flag); + buffer_put_cstring(&m, cp); + + buffer_append(&command, "\0", 1); + buffer_put_cstring(&m, buffer_ptr(&command)); + + if (options.num_send_env == 0 || environ == NULL) { + buffer_put_int(&m, 0); + } else { + /* Pass environment */ + num_env = 0; + for (i = 0; environ[i] != NULL; i++) + if (env_permitted(environ[i])) + num_env++; /* Count */ + + buffer_put_int(&m, num_env); + + for (i = 0; environ[i] != NULL && num_env >= 0; i++) + if (env_permitted(environ[i])) { + num_env--; + buffer_put_cstring(&m, environ[i]); + } + } + + if (ssh_msg_send(sock, /* version */0, &m) == -1) + fatal("%s: msg_send", __func__); + + mm_send_fd(sock, STDIN_FILENO); + mm_send_fd(sock, STDOUT_FILENO); + mm_send_fd(sock, STDERR_FILENO); + + /* Wait for reply, so master has a chance to gather ttymodes */ + buffer_clear(&m); + if (ssh_msg_recv(sock, &m) == -1) + fatal("%s: msg_recv", __func__); + if (buffer_get_char(&m) != 0) + fatal("%s: master returned error", __func__); + buffer_free(&m); + + signal(SIGINT, control_client_sighandler); + signal(SIGTERM, control_client_sighandler); + signal(SIGWINCH, control_client_sigrelay); + + if (tty_flag) + enter_raw_mode(); + + /* Stick around until the controlee closes the client_fd */ + exitval = 0; + for (;!control_client_terminate;) { + r = read(sock, &exitval, sizeof(exitval)); + if (r == 0) { + debug2("Received EOF from master"); + break; + } + if (r > 0) + debug2("Received exit status from master %d", exitval); + if (r == -1 && errno != EINTR) + fatal("%s: read %s", __func__, strerror(errno)); + } + + if (control_client_terminate) + debug2("Exiting on signal %d", control_client_terminate); + + close(sock); + + leave_raw_mode(); + + if (tty_flag && options.log_level != SYSLOG_LEVEL_QUIET) + fprintf(stderr, "Connection to master closed.\r\n"); + + exit(exitval); +} diff --git a/openssh/ssh1.h b/openssh/ssh1.h index 98d1dc9..cc7fbc8 100644 --- a/openssh/ssh1.h +++ b/openssh/ssh1.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh1.h,v 1.3 2001/05/30 12:55:13 markus Exp $ */ +/* $OpenBSD: ssh1.h,v 1.4 2004/07/11 17:48:47 deraadt Exp $ */ /* * Author: Tatu Ylonen @@ -29,8 +29,8 @@ #define SSH_SMSG_AUTH_RSA_CHALLENGE 7 /* int (BIGNUM) */ #define SSH_CMSG_AUTH_RSA_RESPONSE 8 /* int (BIGNUM) */ #define SSH_CMSG_AUTH_PASSWORD 9 /* pass (string) */ -#define SSH_CMSG_REQUEST_PTY 10 /* TERM, tty modes */ -#define SSH_CMSG_WINDOW_SIZE 11 /* row,col,xpix,ypix */ +#define SSH_CMSG_REQUEST_PTY 10 /* TERM, tty modes */ +#define SSH_CMSG_WINDOW_SIZE 11 /* row,col,xpix,ypix */ #define SSH_CMSG_EXEC_SHELL 12 /* */ #define SSH_CMSG_EXEC_CMD 13 /* cmd (string) */ #define SSH_SMSG_SUCCESS 14 /* */ @@ -45,7 +45,7 @@ #define SSH_MSG_CHANNEL_DATA 23 /* ch,data (int,str) */ #define SSH_MSG_CHANNEL_CLOSE 24 /* channel (int) */ #define SSH_MSG_CHANNEL_CLOSE_CONFIRMATION 25 /* channel (int) */ -/* SSH_CMSG_X11_REQUEST_FORWARDING 26 OBSOLETE */ +/* SSH_CMSG_X11_REQUEST_FORWARDING 26 OBSOLETE */ #define SSH_SMSG_X11_OPEN 27 /* channel (int) */ #define SSH_CMSG_PORT_FORWARD_REQUEST 28 /* p,host,hp (i,s,i) */ #define SSH_MSG_PORT_OPEN 29 /* ch,h,p (i,s,i) */ diff --git a/openssh/ssh_config.5 b/openssh/ssh_config.5 index a5be8f5..b40a789 100644 --- a/openssh/ssh_config.5 +++ b/openssh/ssh_config.5 @@ -34,7 +34,7 @@ .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.\" $OpenBSD: ssh_config.5,v 1.29 2004/03/05 10:53:58 markus Exp $ +.\" $OpenBSD: ssh_config.5,v 1.38 2004/06/26 09:11:14 jmc Exp $ .Dd September 25, 1999 .Dt SSH_CONFIG 5 .Os @@ -191,6 +191,18 @@ The default is Specifies the ciphers allowed for protocol version 2 in order of preference. Multiple ciphers must be comma-separated. +The supported ciphers are +.Dq 3des-cbc , +.Dq aes128-cbc , +.Dq aes192-cbc , +.Dq aes256-cbc , +.Dq aes128-ctr , +.Dq aes192-ctr , +.Dq aes256-ctr , +.Dq arcfour , +.Dq blowfish-cbc , +and +.Dq cast128-cbc . The default is .Bd -literal ``aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,arcfour, @@ -238,6 +250,37 @@ Specifies the timeout (in seconds) used when connecting to the ssh server, instead of using the default system TCP timeout. This value is used only when the target is down or really unreachable, not when it refuses the connection. +.It Cm ControlMaster +Enables the sharing of multiple sessions over a single network connection. +When set to +.Dq yes +.Nm ssh +will listen for connections on a control socket specified using the +.Cm ControlPath +argument. +Additional sessions can connect to this socket using the same +.Cm ControlPath +with +.Cm ControlMaster +set to +.Dq no +(the default). +These sessions will reuse the master instance's network connection rather +than initiating new ones. +Setting this to +.Dq ask +will cause +.Nm ssh +to listen for control connections, but require confirmation using the +.Ev SSH_ASKPASS +program before they are accepted (see +.Xr ssh-add 1 +for details). +.It Cm ControlPath +Specify the path to the control socket used for connection sharing. +See +.Cm ControlMaster +above. .It Cm DynamicForward Specifies that a TCP/IP port on the local machine be forwarded over the secure channel, and the application @@ -319,7 +362,7 @@ if the .Cm ForwardX11Trusted option is also enabled. .It Cm ForwardX11Trusted -If the this option is set to +If this option is set to .Dq yes then remote X11 clients will have full access to the original X11 display. If this option is set to @@ -422,7 +465,7 @@ identities will be tried in sequence. Specifies that .Nm ssh should only use the authentication identity files configured in the -.Nm +.Nm files, even if the .Nm ssh-agent @@ -582,6 +625,27 @@ running. The default is .Dq yes . Note that this option applies to protocol version 1 only. +.It Cm SendEnv +Specifies what variables from the local +.Xr environ 7 +should be sent to the server. +Note that environment passing is only supported for protocol 2, the +server must also support it, and the server must be configured to +accept these environment variables. +Refer to +.Cm AcceptEnv +in +.Xr sshd_config 5 +for how to configure the server. +Variables are specified by name, which may contain the wildcard characters +.Ql \&* +and +.Ql \&? . +Multiple environment variables may be separated by whitespace or spread +across multiple +.Cm SendEnv +directives. +The default is not to send any environment variables. .It Cm ServerAliveInterval Sets a timeout interval in seconds after which if no data has been received from the server, @@ -741,9 +805,8 @@ The format of this file is described above. This file is used by the .Nm ssh client. -This file does not usually contain any sensitive information, -but the recommended permissions are read/write for the user, and not -accessible by others. +Because of the potential for abuse, this file must have strict permissions: +read/write for the user, and not accessible by others. .It Pa /etc/ssh/ssh_config Systemwide configuration file. This file provides defaults for those diff --git a/openssh/sshconnect1.c b/openssh/sshconnect1.c index 2f89964..6e2e31c 100644 --- a/openssh/sshconnect1.c +++ b/openssh/sshconnect1.c @@ -13,7 +13,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: sshconnect1.c,v 1.56 2003/08/28 12:54:34 markus Exp $"); +RCSID("$OpenBSD: sshconnect1.c,v 1.60 2004/07/28 09:40:29 markus Exp $"); #include #include @@ -24,7 +24,7 @@ RCSID("$OpenBSD: sshconnect1.c,v 1.56 2003/08/28 12:54:34 markus Exp $"); #include "rsa.h" #include "buffer.h" #include "packet.h" -#include "mpaux.h" +#include "kex.h" #include "uidswap.h" #include "log.h" #include "readconf.h" @@ -32,7 +32,7 @@ RCSID("$OpenBSD: sshconnect1.c,v 1.56 2003/08/28 12:54:34 markus Exp $"); #include "authfd.h" #include "sshconnect.h" #include "authfile.h" -#include "readpass.h" +#include "misc.h" #include "cipher.h" #include "canohost.h" #include "auth.h" @@ -476,7 +476,7 @@ ssh_kex(char *host, struct sockaddr *hostaddr) u_char cookie[8]; u_int supported_ciphers; u_int server_flags, client_flags; - u_int32_t rand = 0; + u_int32_t rnd = 0; debug("Waiting for server public key."); @@ -528,7 +528,7 @@ ssh_kex(char *host, struct sockaddr *hostaddr) client_flags = SSH_PROTOFLAG_SCREEN_NUMBER | SSH_PROTOFLAG_HOST_IN_FWD_OPEN; - compute_session_id(session_id, cookie, host_key->rsa->n, server_key->rsa->n); + derive_ssh1_session_id(host_key->rsa->n, server_key->rsa->n, cookie, session_id); /* Generate a session key. */ arc4random_stir(); @@ -540,9 +540,9 @@ ssh_kex(char *host, struct sockaddr *hostaddr) */ for (i = 0; i < 32; i++) { if (i % 4 == 0) - rand = arc4random(); - session_key[i] = rand & 0xff; - rand >>= 8; + rnd = arc4random(); + session_key[i] = rnd & 0xff; + rnd >>= 8; } /* @@ -598,7 +598,7 @@ ssh_kex(char *host, struct sockaddr *hostaddr) if (options.cipher == SSH_CIPHER_NOT_SET) { if (cipher_mask_ssh1(1) & supported_ciphers & (1 << ssh_cipher_default)) options.cipher = ssh_cipher_default; - } else if (options.cipher == SSH_CIPHER_ILLEGAL || + } else if (options.cipher == SSH_CIPHER_INVALID || !(cipher_mask_ssh1(1) & (1 << options.cipher))) { logit("No valid SSH1 cipher, using %.100s instead.", cipher_name(ssh_cipher_default)); diff --git a/openssh/sshconnect2.c b/openssh/sshconnect2.c index 8aada10..1e38e43 100644 --- a/openssh/sshconnect2.c +++ b/openssh/sshconnect2.c @@ -23,7 +23,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: sshconnect2.c,v 1.135 2004/03/05 10:53:58 markus Exp $"); +RCSID("$OpenBSD: sshconnect2.c,v 1.138 2004/06/13 12:53:24 djm Exp $"); #include "openbsd-compat/sys-queue.h" @@ -43,7 +43,7 @@ RCSID("$OpenBSD: sshconnect2.c,v 1.135 2004/03/05 10:53:58 markus Exp $"); #include "authfd.h" #include "log.h" #include "readconf.h" -#include "readpass.h" +#include "misc.h" #include "match.h" #include "dispatch.h" #include "canohost.h" @@ -149,6 +149,7 @@ ssh_kex2(char *host, struct sockaddr *hostaddr) /* start key exchange */ kex = kex_setup(myproposal); kex->kex[KEX_DH_GRP1_SHA1] = kexdh_client; + kex->kex[KEX_DH_GRP14_SHA1] = kexdh_client; kex->kex[KEX_DH_GEX_SHA1] = kexgex_client; #ifdef GSSAPI kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_client; @@ -513,7 +514,7 @@ input_userauth_pk_ok(int type, u_int32_t seq, void *ctxt) * moved to the end of the queue. this also avoids confusion by * duplicate keys */ - TAILQ_FOREACH_REVERSE(id, &authctxt->keys, next, idlist) { + TAILQ_FOREACH_REVERSE(id, &authctxt->keys, idlist, next) { if (key_equal(key, id->key)) { sent = sign_and_send_pubkey(authctxt, id); break; diff --git a/openssh/sshd.8 b/openssh/sshd.8 index 34413e2..233b000 100644 --- a/openssh/sshd.8 +++ b/openssh/sshd.8 @@ -34,7 +34,7 @@ .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.\" $OpenBSD: sshd.8,v 1.200 2003/10/08 08:27:36 jmc Exp $ +.\" $OpenBSD: sshd.8,v 1.201 2004/05/02 11:54:31 dtucker Exp $ .Dd September 25, 1999 .Dt SSHD 8 .Os @@ -196,7 +196,7 @@ configuration file. .Nm rereads its configuration file when it receives a hangup signal, .Dv SIGHUP , -by executing itself with the name it was started as, i.e., +by executing itself with the name and options it was started with, e.g., .Pa /usr/sbin/sshd . .Pp The options are as follows: diff --git a/openssh/sshd.c b/openssh/sshd.c index f5d8d68..6554578 100644 --- a/openssh/sshd.c +++ b/openssh/sshd.c @@ -42,7 +42,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: sshd.c,v 1.290 2004/03/11 10:21:17 markus Exp $"); +RCSID("$OpenBSD: sshd.c,v 1.301 2004/08/11 11:50:09 dtucker Exp $"); #include #include @@ -60,12 +60,12 @@ RCSID("$OpenBSD: sshd.c,v 1.290 2004/03/11 10:21:17 markus Exp $"); #include "rsa.h" #include "sshpty.h" #include "packet.h" -#include "mpaux.h" #include "log.h" #include "servconf.h" #include "uidswap.h" #include "compat.h" #include "buffer.h" +#include "bufaux.h" #include "cipher.h" #include "kex.h" #include "key.h" @@ -77,6 +77,7 @@ RCSID("$OpenBSD: sshd.c,v 1.290 2004/03/11 10:21:17 markus Exp $"); #include "canohost.h" #include "auth.h" #include "misc.h" +#include "msg.h" #include "dispatch.h" #include "channels.h" #include "session.h" @@ -105,11 +106,13 @@ int deny_severity = LOG_WARNING; #define O_NOCTTY 0 #endif -#ifdef HAVE___PROGNAME +/* Re-exec fds */ +#define REEXEC_DEVCRYPTO_RESERVED_FD (STDERR_FILENO + 1) +#define REEXEC_STARTUP_PIPE_FD (STDERR_FILENO + 2) +#define REEXEC_CONFIG_PASS_FD (STDERR_FILENO + 3) +#define REEXEC_MIN_FREE_FD (STDERR_FILENO + 4) + extern char *__progname; -#else -char *__progname; -#endif /* Server configuration options. */ ServerOptions options; @@ -147,6 +150,12 @@ int log_stderr = 0; char **saved_argv; int saved_argc; +/* re-exec */ +int rexeced_flag = 0; +int rexec_flag = 1; +int rexec_argc = 0; +char **rexec_argv; + /* * The sockets that the server is listening; this is used in the SIGHUP * signal handler. @@ -210,12 +219,12 @@ int startup_pipe; /* in child */ int use_privsep; struct monitor *pmonitor = NULL; -/* message to be displayed after login */ -Buffer loginmsg; - /* global authentication context */ Authctxt *the_authctxt = NULL; +/* message to be displayed after login */ +Buffer loginmsg; + /* Prototypes for various functions defined later in this file. */ void destroy_sensitive_data(void); void demote_sensitive_data(void); @@ -659,6 +668,7 @@ privsep_postauth(Authctxt *authctxt) else if (pmonitor->m_pid != 0) { debug2("User child is on pid %ld", (long)pmonitor->m_pid); close(pmonitor->m_recvfd); + buffer_clear(&loginmsg); monitor_child_postauth(pmonitor); /* NEVERREACHED */ @@ -781,6 +791,87 @@ usage(void) exit(1); } +static void +send_rexec_state(int fd, Buffer *conf) +{ + Buffer m; + + debug3("%s: entering fd = %d config len %d", __func__, fd, + buffer_len(conf)); + + /* + * Protocol from reexec master to child: + * string configuration + * u_int ephemeral_key_follows + * bignum e (only if ephemeral_key_follows == 1) + * bignum n " + * bignum d " + * bignum iqmp " + * bignum p " + * bignum q " + */ + buffer_init(&m); + buffer_put_cstring(&m, buffer_ptr(conf)); + + if (sensitive_data.server_key != NULL && + sensitive_data.server_key->type == KEY_RSA1) { + buffer_put_int(&m, 1); + buffer_put_bignum(&m, sensitive_data.server_key->rsa->e); + buffer_put_bignum(&m, sensitive_data.server_key->rsa->n); + buffer_put_bignum(&m, sensitive_data.server_key->rsa->d); + buffer_put_bignum(&m, sensitive_data.server_key->rsa->iqmp); + buffer_put_bignum(&m, sensitive_data.server_key->rsa->p); + buffer_put_bignum(&m, sensitive_data.server_key->rsa->q); + } else + buffer_put_int(&m, 0); + + if (ssh_msg_send(fd, 0, &m) == -1) + fatal("%s: ssh_msg_send failed", __func__); + + buffer_free(&m); + + debug3("%s: done", __func__); +} + +static void +recv_rexec_state(int fd, Buffer *conf) +{ + Buffer m; + char *cp; + u_int len; + + debug3("%s: entering fd = %d", __func__, fd); + + buffer_init(&m); + + if (ssh_msg_recv(fd, &m) == -1) + fatal("%s: ssh_msg_recv failed", __func__); + if (buffer_get_char(&m) != 0) + fatal("%s: rexec version mismatch", __func__); + + cp = buffer_get_string(&m, &len); + if (conf != NULL) + buffer_append(conf, cp, len + 1); + xfree(cp); + + if (buffer_get_int(&m)) { + if (sensitive_data.server_key != NULL) + key_free(sensitive_data.server_key); + sensitive_data.server_key = key_new_private(KEY_RSA1); + buffer_get_bignum(&m, sensitive_data.server_key->rsa->e); + buffer_get_bignum(&m, sensitive_data.server_key->rsa->n); + buffer_get_bignum(&m, sensitive_data.server_key->rsa->d); + buffer_get_bignum(&m, sensitive_data.server_key->rsa->iqmp); + buffer_get_bignum(&m, sensitive_data.server_key->rsa->p); + buffer_get_bignum(&m, sensitive_data.server_key->rsa->q); + rsa_generate_additional_parameters( + sensitive_data.server_key->rsa); + } + buffer_free(&m); + + debug3("%s: done", __func__); +} + /* * Main program for the daemon. */ @@ -789,7 +880,8 @@ main(int ac, char **av) { extern char *optarg; extern int optind; - int opt, sock_in = 0, sock_out = 0, newsock, j, i, fdsetsz, on = 1; + int opt, j, i, fdsetsz, on = 1; + int sock_in = -1, sock_out = -1, newsock = -1; pid_t pid; socklen_t fromlen; fd_set *fdset; @@ -801,11 +893,12 @@ main(int ac, char **av) char ntop[NI_MAXHOST], strport[NI_MAXSERV]; char *line; int listen_sock, maxfd; - int startup_p[2]; + int startup_p[2], config_s[2]; int startups = 0; Key *key; Authctxt *authctxt; int ret, key_used = 0; + Buffer cfg; #ifdef HAVE_SECUREWARE (void)set_auth_parameters(ac, av); @@ -815,6 +908,7 @@ main(int ac, char **av) /* Save argv. Duplicate so setproctitle emulation doesn't clobber it */ saved_argc = ac; + rexec_argc = ac; saved_argv = xmalloc(sizeof(*saved_argv) * (ac + 1)); for (i = 0; i < ac; i++) saved_argv[i] = xstrdup(av[i]); @@ -833,7 +927,7 @@ main(int ac, char **av) initialize_server_options(&options); /* Parse command-line arguments. */ - while ((opt = getopt(ac, av, "f:p:b:k:h:g:u:o:dDeiqtQ46")) != -1) { + while ((opt = getopt(ac, av, "f:p:b:k:h:g:u:o:dDeiqrtQR46")) != -1) { switch (opt) { case '4': IPv4or6 = AF_INET; @@ -860,6 +954,13 @@ main(int ac, char **av) case 'i': inetd_flag = 1; break; + case 'r': + rexec_flag = 0; + break; + case 'R': + rexeced_flag = 1; + inetd_flag = 1; + break; case 'Q': /* ignored */ break; @@ -923,6 +1024,15 @@ main(int ac, char **av) break; } } + if (rexeced_flag || inetd_flag) + rexec_flag = 0; + if (rexec_flag && (av[0] == NULL || *av[0] != '/')) + fatal("sshd re-exec requires execution with an absolute path"); + if (rexeced_flag) + closefrom(REEXEC_MIN_FREE_FD); + else + closefrom(REEXEC_DEVCRYPTO_RESERVED_FD); + SSLeay_add_all_algorithms(); channel_set_af(IPv4or6); @@ -945,7 +1055,7 @@ main(int ac, char **av) unsetenv("KRB5CCNAME"); #endif /* _AIX */ #ifdef _UNICOS - /* Cray can define user privs drop all prives now! + /* Cray can define user privs drop all privs now! * Not needed on PRIV_SU systems! */ drop_cray_privs(); @@ -953,8 +1063,23 @@ main(int ac, char **av) seed_rng(); - /* Read server configuration options from the configuration file. */ - read_server_config(&options, config_file_name); + sensitive_data.server_key = NULL; + sensitive_data.ssh1_host_key = NULL; + sensitive_data.have_ssh1_key = 0; + sensitive_data.have_ssh2_key = 0; + + /* Fetch our configuration */ + buffer_init(&cfg); + if (rexeced_flag) + recv_rexec_state(REEXEC_CONFIG_PASS_FD, &cfg); + else + load_server_config(config_file_name, &cfg); + + parse_server_config(&options, + rexeced_flag ? "rexec" : config_file_name, &cfg); + + if (!rexec_flag) + buffer_free(&cfg); /* Fill in default values for those options not explicitly set. */ fill_default_server_options(&options); @@ -972,10 +1097,6 @@ main(int ac, char **av) sizeof(Key *)); for (i = 0; i < options.num_host_key_files; i++) sensitive_data.host_keys[i] = NULL; - sensitive_data.server_key = NULL; - sensitive_data.ssh1_host_key = NULL; - sensitive_data.have_ssh1_key = 0; - sensitive_data.have_ssh2_key = 0; for (i = 0; i < options.num_host_key_files; i++) { key = key_load_private(options.host_key_files[i], "", NULL); @@ -1077,6 +1198,16 @@ main(int ac, char **av) if (setgroups(0, NULL) < 0) debug("setgroups() failed: %.200s", strerror(errno)); + if (rexec_flag) { + rexec_argv = xmalloc(sizeof(char *) * (rexec_argc + 2)); + for (i = 0; i < rexec_argc; i++) { + debug("rexec_argv[%d]='%s'", i, saved_argv[i]); + rexec_argv[i] = saved_argv[i]; + } + rexec_argv[rexec_argc] = "-R"; + rexec_argv[rexec_argc + 1] = NULL; + } + /* Initialize the log (it is reinitialized below in case we forked). */ if (debug_flag && !inetd_flag) log_stderr = 1; @@ -1118,19 +1249,34 @@ main(int ac, char **av) /* Start listening for a socket, unless started from inetd. */ if (inetd_flag) { - int s1; - s1 = dup(0); /* Make sure descriptors 0, 1, and 2 are in use. */ - dup(s1); - sock_in = dup(0); - sock_out = dup(1); + int fd; + startup_pipe = -1; + if (rexeced_flag) { + close(REEXEC_CONFIG_PASS_FD); + sock_in = sock_out = dup(STDIN_FILENO); + if (!debug_flag) { + startup_pipe = dup(REEXEC_STARTUP_PIPE_FD); + close(REEXEC_STARTUP_PIPE_FD); + } + } else { + sock_in = dup(STDIN_FILENO); + sock_out = dup(STDOUT_FILENO); + } /* * We intentionally do not close the descriptors 0, 1, and 2 - * as our code for setting the descriptors won\'t work if + * as our code for setting the descriptors won't work if * ttyfd happens to be one of those. */ + if ((fd = open(_PATH_DEVNULL, O_RDWR, 0)) != -1) { + dup2(fd, STDIN_FILENO); + dup2(fd, STDOUT_FILENO); + if (fd > STDOUT_FILENO) + close(fd); + } debug("inetd sockets after dupping: %d, %d", sock_in, sock_out); - if (options.protocol & SSH_PROTO_1) + if ((options.protocol & SSH_PROTO_1) && + sensitive_data.server_key == NULL) generate_ephemeral_server_key(); } else { for (ai = options.listen_addrs; ai; ai = ai->ai_next) { @@ -1153,8 +1299,7 @@ main(int ac, char **av) verbose("socket: %.100s", strerror(errno)); continue; } - if (fcntl(listen_sock, F_SETFL, O_NONBLOCK) < 0) { - error("listen_sock O_NONBLOCK: %s", strerror(errno)); + if (set_nonblock(listen_sock) == -1) { close(listen_sock); continue; } @@ -1297,8 +1442,7 @@ main(int ac, char **av) error("accept: %.100s", strerror(errno)); continue; } - if (fcntl(newsock, F_SETFL, 0) < 0) { - error("newsock del O_NONBLOCK: %s", strerror(errno)); + if (unset_nonblock(newsock) == -1) { close(newsock); continue; } @@ -1312,6 +1456,16 @@ main(int ac, char **av) continue; } + if (rexec_flag && socketpair(AF_UNIX, + SOCK_STREAM, 0, config_s) == -1) { + error("reexec socketpair: %s", + strerror(errno)); + close(newsock); + close(startup_p[0]); + close(startup_p[1]); + continue; + } + for (j = 0; j < options.max_startups; j++) if (startup_pipes[j] == -1) { startup_pipes[j] = startup_p[0]; @@ -1335,8 +1489,15 @@ main(int ac, char **av) close_listen_socks(); sock_in = newsock; sock_out = newsock; + close(startup_p[0]); + close(startup_p[1]); startup_pipe = -1; pid = getpid(); + if (rexec_flag) { + send_rexec_state(config_s[0], + &cfg); + close(config_s[0]); + } break; } else { /* @@ -1358,6 +1519,7 @@ main(int ac, char **av) sock_in = newsock; sock_out = newsock; log_init(__progname, options.log_level, options.log_facility, log_stderr); + close(config_s[0]); break; } } @@ -1370,6 +1532,12 @@ main(int ac, char **av) close(startup_p[1]); + if (rexec_flag) { + send_rexec_state(config_s[0], &cfg); + close(config_s[0]); + close(config_s[1]); + } + /* Mark that the key has been used (it was "given" to the child). */ if ((options.protocol & SSH_PROTO_1) && key_used == 0) { @@ -1408,6 +1576,46 @@ main(int ac, char **av) error("setsid: %.100s", strerror(errno)); #endif + if (rexec_flag) { + int fd; + + debug("rexec start in %d out %d newsock %d pipe %d sock %d", + sock_in, sock_out, newsock, startup_pipe, config_s[0]); + dup2(newsock, STDIN_FILENO); + dup2(STDIN_FILENO, STDOUT_FILENO); + if (startup_pipe == -1) + close(REEXEC_STARTUP_PIPE_FD); + else + dup2(startup_pipe, REEXEC_STARTUP_PIPE_FD); + + dup2(config_s[1], REEXEC_CONFIG_PASS_FD); + close(config_s[1]); + if (startup_pipe != -1) + close(startup_pipe); + + execv(rexec_argv[0], rexec_argv); + + /* Reexec has failed, fall back and continue */ + error("rexec of %s failed: %s", rexec_argv[0], strerror(errno)); + recv_rexec_state(REEXEC_CONFIG_PASS_FD, NULL); + log_init(__progname, options.log_level, + options.log_facility, log_stderr); + + /* Clean up fds */ + startup_pipe = REEXEC_STARTUP_PIPE_FD; + close(config_s[1]); + close(REEXEC_CONFIG_PASS_FD); + newsock = sock_out = sock_in = dup(STDIN_FILENO); + if ((fd = open(_PATH_DEVNULL, O_RDWR, 0)) != -1) { + dup2(fd, STDIN_FILENO); + dup2(fd, STDOUT_FILENO); + if (fd > STDERR_FILENO) + close(fd); + } + debug("rexec cleanup in %d out %d newsock %d pipe %d sock %d", + sock_in, sock_out, newsock, startup_pipe, config_s[0]); + } + /* * Disable the key regeneration alarm. We will not regenerate the * key since we are no longer in a position to give it to anyone. We @@ -1438,7 +1646,7 @@ main(int ac, char **av) #ifdef LIBWRAP /* Check whether logins are denied from this host. */ - { + if (packet_connection_is_on_socket()) { struct request_info req; request_init(&req, RQ_DAEMON, __progname, RQ_FILE, sock_in, 0); @@ -1493,6 +1701,9 @@ main(int ac, char **av) if (privsep_preauth(authctxt) == 1) goto authenticated; + /* prepare buffer to collect messages to display to user after login */ + buffer_init(&loginmsg); + /* perform the key exchange */ /* authenticate user and start session */ if (compat20) { @@ -1708,9 +1919,10 @@ do_ssh1_kex(void) BN_bn2bin(session_key_int, session_key + sizeof(session_key) - len); - compute_session_id(session_id, cookie, + derive_ssh1_session_id( sensitive_data.ssh1_host_key->rsa->n, - sensitive_data.server_key->rsa->n); + sensitive_data.server_key->rsa->n, + cookie, session_id); /* * Xor the first 16 bytes of the session key with the * session id. @@ -1832,6 +2044,7 @@ do_ssh2_kex(void) /* start key exchange */ kex = kex_setup(myproposal); kex->kex[KEX_DH_GRP1_SHA1] = kexdh_server; + kex->kex[KEX_DH_GRP14_SHA1] = kexdh_server; kex->kex[KEX_DH_GEX_SHA1] = kexgex_server; #ifdef GSSAPI kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_server; diff --git a/openssh/sshd_config b/openssh/sshd_config index a81532e..8e3a753 100644 --- a/openssh/sshd_config +++ b/openssh/sshd_config @@ -1,4 +1,4 @@ -# $OpenBSD: sshd_config,v 1.68 2003/12/29 16:39:50 millert Exp $ +# $OpenBSD: sshd_config,v 1.69 2004/05/23 23:59:53 dtucker Exp $ # This is the sshd server system-wide configuration file. See # sshd_config(5) for more information. @@ -35,6 +35,7 @@ #LoginGraceTime 2m #PermitRootLogin yes #StrictModes yes +#MaxAuthTries 6 #RSAAuthentication yes #PubkeyAuthentication yes @@ -72,9 +73,14 @@ #GSSAPIAuthentication yes #GSSAPICleanupCredentials yes -# Set this to 'yes' to enable PAM authentication (via challenge-response) -# and session processing. Depending on your PAM configuration, this may -# bypass the setting of 'PasswordAuthentication' and 'PermitEmptyPasswords' +# Set this to 'yes' to enable PAM authentication, account processing, +# and session processing. If this is enabled, PAM authentication will +# be allowed through the ChallengeResponseAuthentication mechanism. +# Depending on your PAM configuration, this may bypass the setting of +# PasswordAuthentication, PermitEmptyPasswords, and +# "PermitRootLogin without-password". If you just want the PAM account and +# session checks to run without PAM authentication, then enable this but set +# ChallengeResponseAuthentication=no #UsePAM no #AllowTcpForwarding yes diff --git a/openssh/sshd_config.5 b/openssh/sshd_config.5 index c53480d..b7ba7f0 100644 --- a/openssh/sshd_config.5 +++ b/openssh/sshd_config.5 @@ -34,7 +34,7 @@ .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.\" $OpenBSD: sshd_config.5,v 1.29 2004/03/08 10:18:57 dtucker Exp $ +.\" $OpenBSD: sshd_config.5,v 1.35 2004/06/26 09:14:40 jmc Exp $ .Dd September 25, 1999 .Dt SSHD_CONFIG 5 .Os @@ -61,6 +61,28 @@ The possible keywords and their meanings are as follows (note that keywords are case-insensitive and arguments are case-sensitive): .Bl -tag -width Ds +.It Cm AcceptEnv +Specifies what environment variables sent by the client will be copied into +the session's +.Xr environ 7 . +See +.Cm SendEnv +in +.Xr ssh_config 5 +for how to configure the client. +Note that environment passing is only supported for protocol 2. +Variables are specified by name, which may contain the wildcard characters +.Ql \&* +and +.Ql \&? . +Multiple environment variables may be separated by whitespace or spread +across multiple +.Cm AcceptEnv +directives. +Be warned that some environment variables could be used to bypass restricted +user environments. +For this reason, care should be taken in the use of this directive. +The default is not to accept any environment variables. .It Cm AllowGroups This keyword can be followed by a list of group name patterns, separated by spaces. @@ -73,7 +95,6 @@ can be used as wildcards in the patterns. Only group names are valid; a numerical group ID is not recognized. By default, login is allowed for all groups. -.Pp .It Cm AllowTcpForwarding Specifies whether TCP forwarding is permitted. The default is @@ -81,7 +102,6 @@ The default is Note that disabling TCP forwarding does not improve security unless users are also denied shell access, as they can always install their own forwarders. -.Pp .It Cm AllowUsers This keyword can be followed by a list of user name patterns, separated by spaces. @@ -97,7 +117,6 @@ By default, login is allowed for all users. If the pattern takes the form USER@HOST then USER and HOST are separately checked, restricting logins to particular users from particular hosts. -.Pp .It Cm AuthorizedKeysFile Specifies the file that contains the public keys that can be used for user authentication. @@ -120,7 +139,6 @@ The contents of the specified file are sent to the remote user before authentication is allowed. This option is only available for protocol version 2. By default, no banner is displayed. -.Pp .It Cm ChallengeResponseAuthentication Specifies whether challenge response authentication is allowed. All authentication styles from @@ -131,8 +149,19 @@ The default is .It Cm Ciphers Specifies the ciphers allowed for protocol version 2. Multiple ciphers must be comma-separated. +The supported ciphers are +.Dq 3des-cbc , +.Dq aes128-cbc , +.Dq aes192-cbc , +.Dq aes256-cbc , +.Dq aes128-ctr , +.Dq aes192-ctr , +.Dq aes256-ctr , +.Dq arcfour , +.Dq blowfish-cbc , +and +.Dq cast128-cbc . The default is -.Pp .Bd -literal ``aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,arcfour, aes192-cbc,aes256-cbc,aes128-ctr,aes192-ctr,aes256-ctr'' @@ -193,7 +222,6 @@ can be used as wildcards in the patterns. Only group names are valid; a numerical group ID is not recognized. By default, login is allowed for all groups. -.Pp .It Cm DenyUsers This keyword can be followed by a list of user name patterns, separated by spaces. @@ -398,6 +426,12 @@ for data integrity protection. Multiple algorithms must be comma-separated. The default is .Dq hmac-md5,hmac-sha1,hmac-ripemd160,hmac-sha1-96,hmac-md5-96 . +.It Cm MaxAuthTries +Specifies the maximum number of authentication attempts permitted per +connection. +Once the number of failures reaches half this value, +additional failures are logged. +The default is 6. .It Cm MaxStartups Specifies the maximum number of concurrent unauthenticated connections to the .Nm sshd @@ -620,12 +654,25 @@ If .Cm UsePrivilegeSeparation is specified, it will be disabled after authentication. .It Cm UsePAM -Enables PAM authentication (via challenge-response) and session set up. -If you enable this, you should probably disable -.Cm PasswordAuthentication . -If you enable -.CM UsePAM -then you will not be able to run sshd as a non-root user. The default is +Enables the Pluggable Authentication Module interface. +If set to +.Dq yes +this will enable PAM authentication using +.Cm ChallengeResponseAuthentication +and PAM account and session module processing for all authentication types. +.Pp +Because PAM challenge-response authentication usually serves an equivalent +role to password authentication, you should disable either +.Cm PasswordAuthentication +or +.Cm ChallengeResponseAuthentication. +.Pp +If +.Cm UsePAM +is enabled, you will not be able to run +.Xr sshd 8 +as a non-root user. +The default is .Dq no . .It Cm UsePrivilegeSeparation Specifies whether diff --git a/openssh/sshtty.h b/openssh/sshtty.h deleted file mode 100644 index 7ba4a26..0000000 --- a/openssh/sshtty.h +++ /dev/null @@ -1,48 +0,0 @@ -/* $OpenBSD: sshtty.h,v 1.2 2001/06/26 17:27:25 markus Exp $ */ -/* - * Author: Tatu Ylonen - * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland - * All rights reserved - * - * As far as I am concerned, the code I have written for this software - * can be used freely for any purpose. Any derived versions of this - * software must be clearly marked as such, and if the derived work is - * incompatible with the protocol description in the RFC file, it must be - * called by a name other than "ssh" or "Secure Shell". - */ -/* - * Copyright (c) 2001 Markus Friedl. All rights reserved. - * Copyright (c) 2001 Kevin Steves. 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. - */ - -#ifndef SSHTTY_H -#define SSHTTY_H - -#include - -int in_raw_mode(void); -struct termios get_saved_tio(void); -void leave_raw_mode(void); -void enter_raw_mode(void); - -#endif diff --git a/openssh/tildexpand.h b/openssh/tildexpand.h deleted file mode 100644 index f5e7e40..0000000 --- a/openssh/tildexpand.h +++ /dev/null @@ -1,15 +0,0 @@ -/* $OpenBSD: tildexpand.h,v 1.4 2001/06/26 17:27:25 markus Exp $ */ - -/* - * Author: Tatu Ylonen - * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland - * All rights reserved - * - * As far as I am concerned, the code I have written for this software - * can be used freely for any purpose. Any derived versions of this - * software must be clearly marked as such, and if the derived work is - * incompatible with the protocol description in the RFC file, it must be - * called by a name other than "ssh" or "Secure Shell". - */ - -char *tilde_expand_filename(const char *, uid_t); diff --git a/openssh/version.h b/openssh/version.h index 85c0c61..0bbf9e9 100644 --- a/openssh/version.h +++ b/openssh/version.h @@ -1,4 +1,4 @@ -/* $OpenBSD: version.h,v 1.41 2004/03/20 10:40:59 markus Exp $ */ +/* $OpenBSD: version.h,v 1.42 2004/08/16 08:17:01 markus Exp $ */ #ifdef GSI #define GSI_VERSION " GSI" @@ -18,6 +18,6 @@ #define MGLUE_VERSION "" #endif -#define SSH_VERSION "OpenSSH_3.8.1p1" \ - " NCSA_GSSAPI_20040713" \ +#define SSH_VERSION "OpenSSH_3.9p1" \ + " NCSA_GSSAPI_20040818" \ GSI_VERSION KRB5_VERSION MGLUE_VERSION -- 2.45.1