From 350391c57ace69c4fab6461c695428489f6a4376 Mon Sep 17 00:00:00 2001 From: jbasney Date: Sat, 18 May 2002 02:43:53 +0000 Subject: [PATCH] merged trunk with OpenSSH 3.2.2p1 from vendor branch (OPENSSH_PORTABLE_DIST) --- openssh/Makefile.in | 23 +- openssh/acconfig.h | 46 ++- openssh/auth-krb5.c | 27 +- openssh/auth-pam.c | 10 +- openssh/auth-pam.h | 2 +- openssh/auth.h | 40 ++- openssh/auth2.c | 115 ++++--- openssh/cipher.c | 75 ++++- openssh/compat.c | 28 +- openssh/compat.h | 6 +- openssh/configure.ac | 526 ++++++++++++++++++------------- openssh/contrib/aix/buildbff.sh | 37 ++- openssh/contrib/aix/inventory.sh | 2 +- openssh/includes.h | 123 +++++--- openssh/kex.c | 36 ++- openssh/kex.h | 3 +- openssh/key.c | 45 ++- openssh/key.h | 3 +- openssh/servconf.c | 21 +- openssh/servconf.h | 3 +- openssh/session.c | 171 +++++----- openssh/session.h | 40 ++- openssh/ssh-rand-helper.c | 80 ++++- openssh/sshconnect1.c | 6 +- openssh/sshconnect2.c | 79 ++++- openssh/sshd.8 | 72 +++-- openssh/sshd.c | 350 +++++++++++++++++--- 27 files changed, 1408 insertions(+), 561 deletions(-) diff --git a/openssh/Makefile.in b/openssh/Makefile.in index 679e9c4..0061f93 100644 --- a/openssh/Makefile.in +++ b/openssh/Makefile.in @@ -1,5 +1,10 @@ # $Id$ +# uncomment if you run a non bourne compatable shell. Ie. csh +#SHELL = @SH@ + +AUTORECONF=autoreconf + prefix=@prefix@ exec_prefix=@exec_prefix@ bindir=@bindir@ @@ -18,12 +23,14 @@ VPATH=@srcdir@ SSH_PROGRAM=@bindir@/ssh ASKPASS_PROGRAM=$(libexecdir)/ssh-askpass SFTP_SERVER=$(libexecdir)/sftp-server +PRIVSEP_PATH=@PRIVSEP_PATH@ PATHS= -DSSHDIR=\"$(sysconfdir)\" \ -D_PATH_SSH_PROGRAM=\"$(SSH_PROGRAM)\" \ -D_PATH_SSH_ASKPASS_DEFAULT=\"$(ASKPASS_PROGRAM)\" \ -D_PATH_SFTP_SERVER=\"$(SFTP_SERVER)\" \ -D_PATH_SSH_PIDDIR=\"$(piddir)\" \ + -D_PATH_PRIVSEP_CHROOT_DIR=\"$(PRIVSEP_PATH)\" \ -DSSH_RAND_HELPER=\"$(libexecdir)/ssh-rand-helper\" CC=@CC@ @@ -50,20 +57,21 @@ INSTALL_SSH_RAND_HELPER=@INSTALL_SSH_RAND_HELPER@ TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) ssh-add$(EXEEXT) ssh-keygen$(EXEEXT) ssh-keyscan${EXEEXT} ssh-agent$(EXEEXT) scp$(EXEEXT) ssh-rand-helper${EXEEXT} $(SFTP_PROGS) -LIBSSH_OBJS=atomicio.o authfd.o authfile.o bufaux.o buffer.o canohost.o channels.o cipher.o compat.o compress.o crc32.o deattack.o dh.o dispatch.o fatal.o mac.o hostfile.o key.o kex.o kexdh.o kexgex.o log.o match.o misc.o mpaux.o nchan.o packet.o radix.o rijndael.o entropy.o readpass.o rsa.o scard.o ssh-dss.o ssh-rsa.o tildexpand.o ttymodes.o uidswap.o uuencode.o xmalloc.o kexgss.o gss-genr.o +LIBSSH_OBJS=atomicio.o authfd.o authfile.o bufaux.o buffer.o canohost.o channels.o cipher.o compat.o compress.o crc32.o deattack.o dh.o dispatch.o fatal.o mac.o hostfile.o key.o kex.o kexdh.o kexgex.o log.o match.o misc.o mpaux.o nchan.o packet.o radix.o rijndael.o entropy.o readpass.o rsa.o scard.o scard-opensc.o ssh-dss.o ssh-rsa.o tildexpand.o ttymodes.o uidswap.o uuencode.o xmalloc.o monitor_wrap.o monitor_fdpass.o kexgss.o gss-genr.o SSHOBJS= ssh.o sshconnect.o sshconnect1.o sshconnect2.o sshtty.o readconf.o clientloop.o -SSHDOBJS= sshd.o auth.o auth1.o auth2.o auth-chall.o auth2-chall.o auth-rhosts.o auth-options.o auth-krb4.o auth-krb5.o auth-pam.o auth2-pam.o auth-passwd.o auth-rsa.o auth-rh-rsa.o auth-sia.o sshpty.o sshlogin.o loginrec.o servconf.o serverloop.o md5crypt.o session.o groupaccess.o auth-skey.o auth-bsdauth.o gss-serv.o +SSHDOBJS= sshd.o auth.o auth1.o auth2.o auth-chall.o auth2-chall.o auth-rhosts.o auth-options.o auth-krb4.o auth-krb5.o auth-pam.o auth2-pam.o auth-passwd.o auth-rsa.o auth-rh-rsa.o auth-sia.o sshpty.o sshlogin.o loginrec.o servconf.o serverloop.o md5crypt.o session.o groupaccess.o auth-skey.o auth-bsdauth.o monitor_mm.o monitor.o gss-serv.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 -MANPAGES_IN = scp.1 ssh-add.1 ssh-agent.1 ssh-keygen.1 ssh-keyscan.1 ssh.1 sshd.8 sftp-server.8 sftp.1 +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 +MANPAGES_IN = scp.1 ssh-add.1 ssh-agent.1 ssh-keygen.1 ssh-keyscan.1 ssh.1 sshd.8 sftp-server.8 sftp.1 ssh-rand-helper.8 MANTYPE = @MANTYPE@ CONFIGFILES=sshd_config.out ssh_config.out moduli.out CONFIGFILES_IN=sshd_config ssh_config moduli PATHSUBS = \ + -D/etc/ssh/ssh_prng_cmds=$(sysconfdir)/ssh_prng_cmds \ -D/etc/ssh/ssh_config=$(sysconfdir)/ssh_config \ -D/etc/ssh/ssh_known_hosts=$(sysconfdir)/ssh_known_hosts \ -D/etc/ssh/sshd_config=$(sysconfdir)/sshd_config \ @@ -76,6 +84,7 @@ PATHSUBS = \ -D/etc/ssh/moduli=$(sysconfdir)/moduli \ -D/etc/ssh/sshrc=$(sysconfdir)/sshrc \ -D/usr/X11R6/bin/xauth=$(XAUTH_PATH) \ + -D/var/empty=$(PRIVSEP_PATH) \ -D/usr/bin:/bin:/usr/sbin:/sbin=@user_path@ FIXPATHSCMD = $(PERL) $(srcdir)/fixpaths $(PATHSUBS) @@ -180,7 +189,7 @@ catman-do: done distprep: catman-do - autoreconf + $(AUTORECONF) (cd scard && $(MAKE) -f Makefile.in distprep) install: $(CONFIGFILES) $(MANPAGES) $(TARGETS) install-files host-key @@ -216,6 +225,9 @@ install-files: scard-install $(INSTALL) -m 644 ssh-keygen.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-keygen.1 $(INSTALL) -m 644 ssh-keyscan.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-keyscan.1 $(INSTALL) -m 644 sshd.8.out $(DESTDIR)$(mandir)/$(mansubdir)8/sshd.8 + if [ ! -z "$(INSTALL_SSH_PRNG_CMDS)" ]; then \ + $(INSTALL) -m 644 ssh-rand-helper.8.out $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-rand-helper.8 ; \ + fi @NO_SFTP@$(INSTALL) -m 644 sftp.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/sftp.1 @NO_SFTP@$(INSTALL) -m 644 sftp-server.8.out $(DESTDIR)$(mandir)/$(mansubdir)8/sftp-server.8 -rm -f $(DESTDIR)$(bindir)/slogin @@ -309,5 +321,6 @@ uninstall: -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/sftp.1 -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-keyscan.1 -rm -f $(DESTDIR)$(mandir)/$(mansubdir)8/sshd.8 + -rm -f $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-rand-helper.8 -rm -f $(DESTDIR)$(mandir)/$(mansubdir)8/sftp-server.8 -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/slogin.1 diff --git a/openssh/acconfig.h b/openssh/acconfig.h index 3a39d09..ee854e9 100644 --- a/openssh/acconfig.h +++ b/openssh/acconfig.h @@ -14,10 +14,9 @@ /* SCO workaround */ #undef BROKEN_SYS_TERMIO_H -#undef HAVE_BOGUS_SYS_QUEUE_H -/* Define if you have SCO protected password database */ -#undef HAVE_SCO_PROTECTED_PW +/* Define if you have SecureWare-based protected password database */ +#undef HAVE_SECUREWARE /* If your header files don't define LOGIN_PROGRAM, then use this (detected) */ /* from environment and PATH */ @@ -32,6 +31,12 @@ /* Define if your password has a pw_change field */ #undef HAVE_PW_CHANGE_IN_PASSWD +/* Define if your system uses access rights style file descriptor passing */ +#undef HAVE_ACCRIGHTS_IN_MSGHDR + +/* Define if your system uses ancillary data style file descriptor passing */ +#undef HAVE_CONTROL_IN_MSGHDR + /* Define if you system's inet_ntoa is busted (e.g. Irix gcc issue) */ #undef BROKEN_INET_NTOA @@ -95,6 +100,9 @@ /* Builtin PRNG command timeout */ #undef ENTROPY_TIMEOUT_MSEC +/* non-privileged user for privilege separation */ +#undef SSH_PRIVSEP_USER + /* Define if you want to install preformatted manpages.*/ #undef MANTYPE @@ -157,6 +165,9 @@ /* Some versions of /bin/login need the TERM supplied on the commandline */ #undef LOGIN_NEEDS_TERM +/* Define if your login program cannot handle end of options ("--") */ +#undef LOGIN_NO_ENDOPT + /* Define if you want to specify the path to your lastlog file */ #undef CONF_LASTLOG_FILE @@ -178,6 +189,12 @@ /* Define if libc defines __progname */ #undef HAVE___PROGNAME +/* Define if compiler implements __FUNCTION__ */ +#undef HAVE___FUNCTION__ + +/* Define if compiler implements __func__ */ +#undef HAVE___func__ + /* Define this is you want GSSAPI support in the version 2 protocol */ #undef GSSAPI @@ -232,9 +249,6 @@ /* Define if you have getpwanam(3) [SunOS 4.x] */ #undef HAVE_GETPWANAM -/* Defined if in_systm.h needs to be included with netinet/ip.h (HPUX - ) */ -#undef NEED_IN_SYSTM_H - /* Define if you have an old version of PAM which takes only one argument */ /* to pam_strerror */ #undef HAVE_OLD_PAM @@ -287,9 +301,6 @@ /* Use IPv4 for connection by default, IPv6 can still if explicity asked */ #undef IPV4_DEFAULT -/* If you have no atexit() but xatexit(), and want to use xatexit() */ -#undef HAVE_XATEXIT - /* getaddrinfo is broken (if present) */ #undef BROKEN_GETADDRINFO @@ -332,13 +343,26 @@ /* Define if you want smartcard support */ #undef SMARTCARD +/* Define if you want smartcard support using sectok */ +#undef USE_SECTOK + +/* Define if you want smartcard support using OpenSC */ +#undef USE_OPENSC + /* Define if you want to use OpenSSL's internally seeded PRNG only */ #undef OPENSSL_PRNG_ONLY +/* Define if you shouldn't strip 'tty' from your ttyname in [uw]tmp */ +#undef WITH_ABBREV_NO_TTY + +/* Define if you want a different $PATH for the superuser */ +#undef SUPERUSER_PATH + +/* Path that unprivileged child will chroot() to in privep mode */ +#undef PRIVSEP_PATH + @BOTTOM@ /* ******************* Shouldn't need to edit below this line ************** */ -#include "defines.h" - #endif /* _CONFIG_H */ diff --git a/openssh/auth-krb5.c b/openssh/auth-krb5.c index d1b8d45..76c2419 100644 --- a/openssh/auth-krb5.c +++ b/openssh/auth-krb5.c @@ -1,11 +1,34 @@ /* * Kerberos v5 authentication and ticket-passing routines. - * + * * $FreeBSD: src/crypto/openssh/auth-krb5.c,v 1.6 2001/02/13 16:58:04 assar Exp $ */ +/* + * Copyright (c) 2002 Daniel Kouril. 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. + */ #include "includes.h" -RCSID("$OpenBSD: auth-krb5.c,v 1.6 2002/03/04 17:27:39 stevesk Exp $"); +RCSID("$OpenBSD: auth-krb5.c,v 1.8 2002/03/19 10:49:35 markus Exp $"); #include "ssh.h" #include "ssh1.h" diff --git a/openssh/auth-pam.c b/openssh/auth-pam.c index 1ff3c3c..eb4c616 100644 --- a/openssh/auth-pam.c +++ b/openssh/auth-pam.c @@ -28,6 +28,7 @@ #include "ssh.h" #include "xmalloc.h" #include "log.h" +#include "auth.h" #include "auth-pam.h" #include "servconf.h" #include "canohost.h" @@ -199,10 +200,11 @@ void do_pam_cleanup_proc(void *context) } /* Attempt password authentation using PAM */ -int auth_pam_password(struct passwd *pw, const char *password) +int auth_pam_password(Authctxt *authctxt, const char *password) { extern ServerOptions options; int pam_retval; + struct passwd *pw = authctxt->pw; do_pam_set_conv(&conv); @@ -247,15 +249,18 @@ int do_pam_account(char *username, char *remote_user) } pam_retval = pam_acct_mgmt(__pamh, 0); + debug2("pam_acct_mgmt() = %d", pam_retval); switch (pam_retval) { case PAM_SUCCESS: /* This is what we want */ break; +#if 0 case PAM_NEW_AUTHTOK_REQD: message_cat(&__pam_msg, NEW_AUTHTOK_MSG); /* flag that password change is necessary */ password_change_required = 1; break; +#endif default: log("PAM rejected by account configuration[%d]: " "%.200s", pam_retval, PAM_STRERROR(__pamh, @@ -294,6 +299,9 @@ void do_pam_setcred(int init) { int pam_retval; + if (__pamh == NULL) + return; + do_pam_set_conv(&conv); debug("PAM establishing creds"); diff --git a/openssh/auth-pam.h b/openssh/auth-pam.h index de27b83..71996d9 100644 --- a/openssh/auth-pam.h +++ b/openssh/auth-pam.h @@ -7,7 +7,7 @@ void start_pam(const char *user); void finish_pam(void); -int auth_pam_password(struct passwd *pw, const char *password); +int auth_pam_password(Authctxt *authctxt, const char *password); char **fetch_pam_environment(void); int do_pam_authenticate(int flags); int do_pam_account(char *username, char *remote_user); diff --git a/openssh/auth.h b/openssh/auth.h index cbf282c..6627f80 100644 --- a/openssh/auth.h +++ b/openssh/auth.h @@ -1,4 +1,4 @@ -/* $OpenBSD: auth.h,v 1.29 2002/03/04 17:27:39 stevesk Exp $ */ +/* $OpenBSD: auth.h,v 1.37 2002/05/13 20:44:58 markus Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. @@ -89,14 +89,21 @@ struct KbdintDevice void (*free_ctx)(void *ctx); }; -int auth_rhosts(struct passwd *, const char *); +int auth_rhosts(struct passwd *, const char *); int auth_rhosts2(struct passwd *, const char *, const char *, const char *); -int auth_rhosts_rsa(struct passwd *, const char *, Key *); +int auth_rhosts_rsa(struct passwd *, char *, Key *); int auth_password(Authctxt *, const char *); int auth_rsa(struct passwd *, BIGNUM *); -int auth_rsa_challenge_dialog(RSA *); +int auth_rsa_challenge_dialog(Key *); +BIGNUM *auth_rsa_generate_challenge(Key *); +int auth_rsa_verify_response(Key *, BIGNUM *, u_char[]); +int auth_rsa_key_allowed(struct passwd *, BIGNUM *, Key **); + +int auth_rhosts_rsa_key_allowed(struct passwd *, char *, char *, Key *); +int hostbased_key_allowed(struct passwd *, const char *, char *, Key *); +int user_key_allowed(struct passwd *, Key *); #ifdef KRB4 #include @@ -122,18 +129,27 @@ void krb5_cleanup_proc(void *authctxt); #include "auth-pam.h" #include "auth2-pam.h" -void do_authentication(void); -void do_authentication2(void); +Authctxt *do_authentication(void); +Authctxt *do_authentication2(void); Authctxt *authctxt_new(void); void auth_log(Authctxt *, int, char *, char *); void userauth_finish(Authctxt *, int, char *); int auth_root_allowed(char *); +char *auth2_read_banner(void); + +void privsep_challenge_enable(void); + int auth2_challenge(Authctxt *, char *); void auth2_challenge_stop(Authctxt *); +int bsdauth_query(void *, char **, char **, u_int *, char ***, u_int **); +int bsdauth_respond(void *, u_int, char **); +int skey_query(void *, char **, char **, u_int *, char ***, u_int **); +int skey_respond(void *, u_int, char **); int allowed_user(struct passwd *); +struct passwd * getpwnamallow(const char *user); char *get_challenge(Authctxt *); int verify_response(Authctxt *, const char *); @@ -151,8 +167,20 @@ HostStatus check_key_in_hostfiles(struct passwd *, Key *, const char *, const char *, const char *); +/* hostkey handling */ +Key *get_hostkey_by_index(int); +Key *get_hostkey_by_type(int); +int get_hostkey_index(Key *); +int ssh1_session_key(BIGNUM *); + +/* debug messages during authentication */ +void auth_debug_add(const char *fmt,...) __attribute__((format(printf, 1, 2))); +void auth_debug_send(void); +void auth_debug_reset(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: " #endif diff --git a/openssh/auth2.c b/openssh/auth2.c index 1be3d9e..6b1af53 100644 --- a/openssh/auth2.c +++ b/openssh/auth2.c @@ -23,7 +23,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: auth2.c,v 1.85 2002/02/24 19:14:59 markus Exp $"); +RCSID("$OpenBSD: auth2.c,v 1.91 2002/05/13 02:37:39 itojun Exp $"); #include @@ -47,10 +47,11 @@ RCSID("$OpenBSD: auth2.c,v 1.85 2002/02/24 19:14:59 markus Exp $"); #include "pathnames.h" #include "uidswap.h" #include "auth-options.h" -#include "misc.h" #include "hostfile.h" #include "canohost.h" #include "match.h" +#include "monitor_wrap.h" +#include "atomicio.h" #ifdef GSSAPI #include "ssh-gss.h" @@ -61,7 +62,7 @@ extern ServerOptions options; extern u_char *session_id2; extern int session_id2_len; -static Authctxt *x_authctxt = NULL; +Authctxt *x_authctxt = NULL; static int one = 1; typedef struct Authmethod Authmethod; @@ -79,8 +80,8 @@ static void input_userauth_request(int, u_int32_t, void *); /* helper */ static Authmethod *authmethod_lookup(const char *); static char *authmethods_get(void); -static int user_key_allowed(struct passwd *, Key *); -static int hostbased_key_allowed(struct passwd *, const char *, char *, Key *); +int user_key_allowed(struct passwd *, Key *); +int hostbased_key_allowed(struct passwd *, const char *, char *, Key *); /* auth */ static void userauth_banner(void); @@ -126,7 +127,7 @@ Authmethod authmethods[] = { * loop until authctxt->success == TRUE */ -void +Authctxt * do_authentication2(void) { Authctxt *authctxt = authctxt_new(); @@ -138,11 +139,14 @@ do_authentication2(void) options.kbd_interactive_authentication = 1; if (options.pam_authentication_via_kbd_int) options.kbd_interactive_authentication = 1; + if (use_privsep) + options.pam_authentication_via_kbd_int = 0; dispatch_init(&dispatch_protocol_error); dispatch_set(SSH2_MSG_SERVICE_REQUEST, &input_service_request); dispatch_run(DISPATCH_BLOCK, &authctxt->success, authctxt); - do_authenticated(authctxt); + + return (authctxt); } static void @@ -200,25 +204,26 @@ input_userauth_request(int type, u_int32_t seq, void *ctxt) if (authctxt->attempt++ == 0) { /* setup auth context */ - struct passwd *pw = NULL; - pw = getpwnam(user); - if (pw && allowed_user(pw) && strcmp(service, "ssh-connection")==0) { - authctxt->pw = pwcopy(pw); + authctxt->pw = PRIVSEP(getpwnamallow(user)); + if (authctxt->pw && strcmp(service, "ssh-connection")==0) { authctxt->valid = 1; debug2("input_userauth_request: setting up authctxt for %s", user); #ifdef USE_PAM - start_pam(pw->pw_name); + PRIVSEP(start_pam(authctxt->pw->pw_name)); #endif } else { log("input_userauth_request: illegal user %s", user); #ifdef USE_PAM - start_pam("NOUSER"); + PRIVSEP(start_pam("NOUSER")); #endif } - setproctitle("%s", pw ? user : "unknown"); + setproctitle("%s%s", authctxt->pw ? user : "unknown", + use_privsep ? " [net]" : ""); authctxt->user = xstrdup(user); authctxt->service = xstrdup(service); authctxt->style = style ? xstrdup(style) : NULL; + if (use_privsep) + mm_inform_authserv(service, style); } else if (strcmp(user, authctxt->user) != 0 || strcmp(service, authctxt->service) != 0) { packet_disconnect("Change of username or service not allowed: " @@ -227,14 +232,13 @@ input_userauth_request(int type, u_int32_t seq, void *ctxt) } /* reset state */ auth2_challenge_stop(authctxt); + authctxt->postponed = 0; #ifdef GSSAPI dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL); dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, NULL); #endif - authctxt->postponed = 0; - /* try to authenticate user */ m = authmethod_lookup(method); if (m != NULL) { @@ -263,8 +267,8 @@ userauth_finish(Authctxt *authctxt, int authenticated, char *method) authenticated = 0; #ifdef USE_PAM - if (authenticated && authctxt->user && !do_pam_account(authctxt->user, - NULL)) + if (!use_privsep && authenticated && authctxt->user && + !do_pam_account(authctxt->user, NULL)) authenticated = 0; #endif /* USE_PAM */ @@ -302,25 +306,45 @@ userauth_finish(Authctxt *authctxt, int authenticated, char *method) } } -static void -userauth_banner(void) +char * +auth2_read_banner(void) { struct stat st; char *banner = NULL; off_t len, n; int fd; - if (options.banner == NULL || (datafellows & SSH_BUG_BANNER)) - return; - if ((fd = open(options.banner, O_RDONLY)) < 0) - return; - if (fstat(fd, &st) < 0) - goto done; + if ((fd = open(options.banner, O_RDONLY)) == -1) + return (NULL); + if (fstat(fd, &st) == -1) { + close(fd); + return (NULL); + } len = st.st_size; banner = xmalloc(len + 1); - if ((n = read(fd, banner, len)) < 0) - goto done; + n = atomicio(read, fd, banner, len); + close(fd); + + if (n != len) { + free(banner); + return (NULL); + } banner[n] = '\0'; + + return (banner); +} + +static void +userauth_banner(void) +{ + char *banner = NULL; + + if (options.banner == NULL || (datafellows & SSH_BUG_BANNER)) + return; + + if ((banner = PRIVSEP(auth2_read_banner())) == NULL) + goto done; + packet_start(SSH2_MSG_USERAUTH_BANNER); packet_put_cstring(banner); packet_put_cstring(""); /* language, unused */ @@ -329,7 +353,6 @@ userauth_banner(void) done: if (banner) xfree(banner); - close(fd); return; } @@ -350,13 +373,7 @@ userauth_none(Authctxt *authctxt) if (check_nt_auth(1, authctxt->pw) == 0) return(0); #endif -#ifdef USE_PAM - return auth_pam_password(authctxt->pw, ""); -#elif defined(HAVE_OSF_SIA) - return 0; -#else /* !HAVE_OSF_SIA && !USE_PAM */ - return auth_password(authctxt, ""); -#endif /* USE_PAM */ + return PRIVSEP(auth_password(authctxt, "")); } static int @@ -375,13 +392,7 @@ userauth_passwd(Authctxt *authctxt) #ifdef HAVE_CYGWIN check_nt_auth(1, authctxt->pw) && #endif -#ifdef USE_PAM - auth_pam_password(authctxt->pw, password) == 1) -#elif defined(HAVE_OSF_SIA) - auth_sia_password(authctxt->user, password) == 1) -#else /* !USE_PAM && !HAVE_OSF_SIA */ - auth_password(authctxt, password) == 1) -#endif /* USE_PAM */ + PRIVSEP(auth_password(authctxt, password)) == 1) authenticated = 1; memset(password, 0, len); xfree(password); @@ -490,8 +501,10 @@ userauth_pubkey(Authctxt *authctxt) buffer_dump(&b); #endif /* test for correct signature */ - if (user_key_allowed(authctxt->pw, key) && - key_verify(key, sig, slen, buffer_ptr(&b), buffer_len(&b)) == 1) + authenticated = 0; + if (PRIVSEP(user_key_allowed(authctxt->pw, key)) && + PRIVSEP(key_verify(key, sig, slen, buffer_ptr(&b), + buffer_len(&b))) == 1) authenticated = 1; buffer_clear(&b); xfree(sig); @@ -507,7 +520,7 @@ userauth_pubkey(Authctxt *authctxt) * if a user is not allowed to login. is this an * issue? -markus */ - if (user_key_allowed(authctxt->pw, key)) { + if (PRIVSEP(user_key_allowed(authctxt->pw, key))) { packet_start(SSH2_MSG_USERAUTH_PK_OK); packet_put_string(pkalg, alen); packet_put_string(pkblob, blen); @@ -595,8 +608,10 @@ userauth_hostbased(Authctxt *authctxt) buffer_dump(&b); #endif /* test for allowed key and correct signature */ - if (hostbased_key_allowed(authctxt->pw, cuser, chost, key) && - key_verify(key, sig, slen, buffer_ptr(&b), buffer_len(&b)) == 1) + authenticated = 0; + if (PRIVSEP(hostbased_key_allowed(authctxt->pw, cuser, chost, key)) && + PRIVSEP(key_verify(key, sig, slen, buffer_ptr(&b), + buffer_len(&b))) == 1) authenticated = 1; buffer_clear(&b); @@ -753,7 +768,7 @@ user_key_allowed2(struct passwd *pw, Key *key, char *file) } /* check whether given key is in .ssh/authorized_keys* */ -static int +int user_key_allowed(struct passwd *pw, Key *key) { int success; @@ -773,7 +788,7 @@ user_key_allowed(struct passwd *pw, Key *key) } /* return 1 if given hostkey is allowed */ -static int +int hostbased_key_allowed(struct passwd *pw, const char *cuser, char *chost, Key *key) { diff --git a/openssh/cipher.c b/openssh/cipher.c index 821543a..86d9234 100644 --- a/openssh/cipher.c +++ b/openssh/cipher.c @@ -35,7 +35,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: cipher.c,v 1.54 2002/03/19 10:49:35 markus Exp $"); +RCSID("$OpenBSD: cipher.c,v 1.55 2002/04/03 09:26:11 markus Exp $"); #include "xmalloc.h" #include "log.h" @@ -44,6 +44,11 @@ RCSID("$OpenBSD: cipher.c,v 1.54 2002/03/19 10:49:35 markus Exp $"); #include #include "rijndael.h" +#if OPENSSL_VERSION_NUMBER < 0x00906000L +#define SSH_OLD_EVP +#define EVP_CIPHER_CTX_get_app_data(e) ((e)->app_data) +#endif + static EVP_CIPHER *evp_ssh1_3des(void); static EVP_CIPHER *evp_ssh1_bf(void); static EVP_CIPHER *evp_rijndael(void); @@ -67,6 +72,8 @@ struct Cipher { { "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 }, { NULL, SSH_CIPHER_ILLEGAL, 0, 0, NULL } }; @@ -176,7 +183,11 @@ cipher_init(CipherContext *cc, Cipher *cipher, int encrypt) { static int dowarn = 1; +#ifdef SSH_OLD_EVP + EVP_CIPHER *type; +#else const EVP_CIPHER *type; +#endif int klen; if (cipher->number == SSH_CIPHER_DES) { @@ -201,6 +212,15 @@ cipher_init(CipherContext *cc, Cipher *cipher, type = (*cipher->evptype)(); EVP_CIPHER_CTX_init(&cc->evp); +#ifdef SSH_OLD_EVP + if (type->key_len > 0 && type->key_len != keylen) { + debug("cipher_init: set keylen (%d -> %d)", + type->key_len, keylen); + type->key_len = keylen; + } + EVP_CipherInit(&cc->evp, type, (u_char *)key, (u_char *)iv, + (encrypt == CIPHER_ENCRYPT)); +#else if (EVP_CipherInit(&cc->evp, type, NULL, (u_char *)iv, (encrypt == CIPHER_ENCRYPT)) == 0) fatal("cipher_init: EVP_CipherInit failed for %s", @@ -215,6 +235,7 @@ cipher_init(CipherContext *cc, Cipher *cipher, if (EVP_CipherInit(&cc->evp, NULL, (u_char *)key, NULL, -1) == 0) fatal("cipher_init: EVP_CipherInit: set key failed for %s", cipher->name); +#endif } void @@ -222,15 +243,23 @@ cipher_crypt(CipherContext *cc, u_char *dest, const u_char *src, u_int len) { if (len % cc->cipher->block_size) fatal("cipher_encrypt: bad plaintext length %d", len); +#ifdef SSH_OLD_EVP + EVP_Cipher(&cc->evp, dest, (u_char *)src, len); +#else if (EVP_Cipher(&cc->evp, dest, (u_char *)src, len) == 0) fatal("evp_crypt: EVP_Cipher failed"); +#endif } void cipher_cleanup(CipherContext *cc) { +#ifdef SSH_OLD_EVP + EVP_CIPHER_CTX_cleanup(&cc->evp); +#else if (EVP_CIPHER_CTX_cleanup(&cc->evp) == 0) error("cipher_cleanup: EVP_CIPHER_CTX_cleanup failed"); +#endif } /* @@ -301,6 +330,11 @@ ssh1_3des_init(EVP_CIPHER_CTX *ctx, const u_char *key, const u_char *iv, EVP_CIPHER_CTX_init(&c->k1); EVP_CIPHER_CTX_init(&c->k2); EVP_CIPHER_CTX_init(&c->k3); +#ifdef SSH_OLD_EVP + EVP_CipherInit(&c->k1, EVP_des_cbc(), k1, NULL, enc); + EVP_CipherInit(&c->k2, EVP_des_cbc(), k2, NULL, !enc); + EVP_CipherInit(&c->k3, EVP_des_cbc(), k3, NULL, enc); +#else if (EVP_CipherInit(&c->k1, EVP_des_cbc(), k1, NULL, enc) == 0 || EVP_CipherInit(&c->k2, EVP_des_cbc(), k2, NULL, !enc) == 0 || EVP_CipherInit(&c->k3, EVP_des_cbc(), k3, NULL, enc) == 0) { @@ -309,6 +343,7 @@ ssh1_3des_init(EVP_CIPHER_CTX *ctx, const u_char *key, const u_char *iv, EVP_CIPHER_CTX_set_app_data(ctx, NULL); return (0); } +#endif return (1); } static int @@ -320,10 +355,16 @@ ssh1_3des_cbc(EVP_CIPHER_CTX *ctx, u_char *dest, const u_char *src, u_int len) error("ssh1_3des_cbc: no context"); return (0); } +#ifdef SSH_OLD_EVP + EVP_Cipher(&c->k1, dest, (u_char *)src, len); + EVP_Cipher(&c->k2, dest, dest, len); + EVP_Cipher(&c->k3, dest, dest, len); +#else if (EVP_Cipher(&c->k1, dest, (u_char *)src, len) == 0 || EVP_Cipher(&c->k2, dest, dest, len) == 0 || EVP_Cipher(&c->k3, dest, dest, len) == 0) return (0); +#endif return (1); } static int @@ -351,7 +392,9 @@ evp_ssh1_3des(void) ssh1_3des.init = ssh1_3des_init; ssh1_3des.cleanup = ssh1_3des_cleanup; ssh1_3des.do_cipher = ssh1_3des_cbc; +#ifndef SSH_OLD_EVP ssh1_3des.flags = EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH; +#endif return (&ssh1_3des); } @@ -499,8 +542,10 @@ evp_rijndael(void) rijndal_cbc.init = ssh_rijndael_init; rijndal_cbc.cleanup = ssh_rijndael_cleanup; rijndal_cbc.do_cipher = ssh_rijndael_cbc; +#ifndef SSH_OLD_EVP rijndal_cbc.flags = EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH | EVP_CIPH_ALWAYS_CALL_INIT; +#endif return (&rijndal_cbc); } @@ -538,15 +583,15 @@ cipher_get_keyiv(CipherContext *cc, u_char *iv, u_int len) if (evplen == 0) return; if (evplen != len) - fatal("cipher_get_keyiv: wrong iv length %d != %d", + fatal("%s: wrong iv length %d != %d", __FUNCTION__, evplen, len); - if (strncmp(c->name, "aes", 3) == 0) { + if (c->evptype == evp_rijndael) { struct ssh_rijndael_ctx *aesc; aesc = EVP_CIPHER_CTX_get_app_data(&cc->evp); if (aesc == NULL) - fatal("cipher_get_keyiv: no rijndael context"); + fatal("%s: no rijndael context", __FUNCTION__); civ = aesc->r_iv; } else { civ = cc->evp.iv; @@ -555,18 +600,18 @@ cipher_get_keyiv(CipherContext *cc, u_char *iv, u_int len) case SSH_CIPHER_3DES: { struct ssh1_3des_ctx *desc; if (len != 24) - fatal("cipher_get_keyiv: bad 3des iv length: %d", len); + fatal("%s: bad 3des iv length: %d", __FUNCTION__, len); desc = EVP_CIPHER_CTX_get_app_data(&cc->evp); if (desc == NULL) - fatal("cipher_get_keyiv: no 3des context"); - debug3("cipher_get_keyiv: Copying 3DES IV"); + fatal("%s: no 3des context", __FUNCTION__); + debug3("%s: Copying 3DES IV", __FUNCTION__); memcpy(iv, desc->k1.iv, 8); memcpy(iv + 8, desc->k2.iv, 8); memcpy(iv + 16, desc->k3.iv, 8); return; } default: - fatal("cipher_get_keyiv: bad cipher %d", c->number); + fatal("%s: bad cipher %d", __FUNCTION__, c->number); } memcpy(iv, civ, len); } @@ -586,12 +631,12 @@ cipher_set_keyiv(CipherContext *cc, u_char *iv) if (evplen == 0) return; - if (strncmp(c->name, "aes", 3) == 0) { + if (c->evptype == evp_rijndael) { struct ssh_rijndael_ctx *aesc; aesc = EVP_CIPHER_CTX_get_app_data(&cc->evp); if (aesc == NULL) - fatal("cipher_set_keyiv: no rijndael context"); + fatal("%s: no rijndael context", __FUNCTION__); div = aesc->r_iv; }else { div = cc->evp.iv; @@ -601,15 +646,15 @@ cipher_set_keyiv(CipherContext *cc, u_char *iv) struct ssh1_3des_ctx *desc; desc = EVP_CIPHER_CTX_get_app_data(&cc->evp); if (desc == NULL) - fatal("cipher_set_keyiv: no 3des context"); - debug3("cipher_set_keyiv: Installed 3DES IV"); + fatal("%s: no 3des context", __FUNCTION__); + debug3("%s: Installed 3DES IV", __FUNCTION__); memcpy(desc->k1.iv, iv, 8); memcpy(desc->k2.iv, iv + 8, 8); memcpy(desc->k3.iv, iv + 16, 8); return; } default: - fatal("cipher_set_keyiv: bad cipher %d", c->number); + fatal("%s: bad cipher %d", __FUNCTION__, c->number); } memcpy(div, iv, evplen); } @@ -632,7 +677,7 @@ cipher_get_keycontext(CipherContext *cc, u_char *dat) struct ssh1_3des_ctx *desc; desc = EVP_CIPHER_CTX_get_app_data(&cc->evp); if (desc == NULL) - fatal("cipher_get_keycontext: no 3des context"); + fatal("%s: no 3des context", __FUNCTION__); plen = EVP_X_STATE_LEN(desc->k1); if (dat == NULL) return (3*plen); @@ -661,7 +706,7 @@ cipher_set_keycontext(CipherContext *cc, u_char *dat) struct ssh1_3des_ctx *desc; desc = EVP_CIPHER_CTX_get_app_data(&cc->evp); if (desc == NULL) - fatal("cipher_set_keycontext: no 3des context"); + fatal("%s: no 3des context", __FUNCTION__); plen = EVP_X_STATE_LEN(desc->k1); memcpy(EVP_X_STATE(desc->k1), dat, plen); memcpy(EVP_X_STATE(desc->k2), dat + plen, plen); diff --git a/openssh/compat.c b/openssh/compat.c index 8387278..8229033 100644 --- a/openssh/compat.c +++ b/openssh/compat.c @@ -23,7 +23,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: compat.c,v 1.61 2002/03/06 00:24:39 markus Exp $"); +RCSID("$OpenBSD: compat.c,v 1.63 2002/04/10 08:21:47 markus Exp $"); #include "buffer.h" #include "packet.h" @@ -61,21 +61,25 @@ compat_datafellows(const char *version) "OpenSSH-2.1*," "OpenSSH_2.1*," "OpenSSH_2.2*", SSH_OLD_SESSIONID|SSH_BUG_BANNER| - SSH_OLD_DHGEX|SSH_BUG_NOREKEY }, + SSH_OLD_DHGEX|SSH_BUG_NOREKEY| + SSH_BUG_EXTEOF}, { "OpenSSH_2.3.0*", SSH_BUG_BANNER|SSH_BUG_BIGENDIANAES| - SSH_OLD_DHGEX|SSH_BUG_NOREKEY}, + SSH_OLD_DHGEX|SSH_BUG_NOREKEY| + SSH_BUG_EXTEOF}, { "OpenSSH_2.3.*", SSH_BUG_BIGENDIANAES|SSH_OLD_DHGEX| - SSH_BUG_NOREKEY}, + SSH_BUG_NOREKEY|SSH_BUG_EXTEOF}, { "OpenSSH_2.5.0p1*," "OpenSSH_2.5.1p1*", SSH_BUG_BIGENDIANAES|SSH_OLD_DHGEX| - SSH_BUG_NOREKEY|SSH_OLD_GSSAPI }, + SSH_BUG_NOREKEY|SSH_OLD_GSSAPI| + SSH_BUG_EXTEOF}, { "OpenSSH_2.5.0*," "OpenSSH_2.5.1*," - "OpenSSH_2.5.2*", SSH_OLD_DHGEX|SSH_BUG_NOREKEY }, - { "OpenSSH_2.5.3*", SSH_BUG_NOREKEY }, + "OpenSSH_2.5.2*", SSH_OLD_DHGEX|SSH_BUG_NOREKEY| + SSH_BUG_EXTEOF}, + { "OpenSSH_2.5.3*", SSH_BUG_NOREKEY|SSH_BUG_EXTEOF}, { "OpenSSH_2.9p*", SSH_OLD_GSSAPI }, - { "Sun_SSH_1.0*", SSH_BUG_NOREKEY }, + { "Sun_SSH_1.0*", SSH_BUG_NOREKEY|SSH_BUG_EXTEOF}, { "OpenSSH*", 0 }, { "*MindTerm*", 0 }, { "2.1.0*", SSH_BUG_SIGBLOB|SSH_BUG_HMAC| @@ -122,8 +126,12 @@ compat_datafellows(const char *version) "1.2.19*," "1.2.20*," "1.2.21*," - "1.2.22*", SSH_BUG_IGNOREMSG }, - { "1.3.2*", SSH_BUG_IGNOREMSG }, /* f-secure */ + "1.2.22*", SSH_BUG_IGNOREMSG|SSH_BUG_K5USER }, + { "1.3.2*", /* F-Secure */ + SSH_BUG_IGNOREMSG|SSH_BUG_K5USER }, + { "1.2.1*," + "1.2.2*," + "1.2.3*", SSH_BUG_K5USER }, { "*SSH Compatible Server*", /* Netscreen */ SSH_BUG_PASSWORDPAD }, { "*OSU_0*," diff --git a/openssh/compat.h b/openssh/compat.h index 9dae030..cebf306 100644 --- a/openssh/compat.h +++ b/openssh/compat.h @@ -1,4 +1,4 @@ -/* $OpenBSD: compat.h,v 1.30 2002/03/04 17:27:39 stevesk Exp $ */ +/* $OpenBSD: compat.h,v 1.32 2002/04/10 08:21:47 markus Exp $ */ /* * Copyright (c) 1999, 2000, 2001 Markus Friedl. All rights reserved. @@ -52,7 +52,9 @@ #define SSH_BUG_OPENFAILURE 0x00020000 #define SSH_BUG_DERIVEKEY 0x00040000 #define SSH_BUG_DUMMYCHAN 0x00100000 -#define SSH_OLD_GSSAPI 0x00200000 +#define SSH_BUG_EXTEOF 0x00200000 +#define SSH_BUG_K5USER 0x00400000 +#define SSH_OLD_GSSAPI 0x00800000 void enable_compat13(void); void enable_compat20(void); diff --git a/openssh/configure.ac b/openssh/configure.ac index 124f9d1..81f0a59 100644 --- a/openssh/configure.ac +++ b/openssh/configure.ac @@ -21,6 +21,7 @@ AC_PATH_PROGS(FILEPRIV, filepriv, true, /sbin:/usr/sbin) 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) # System features AC_SYS_LARGEFILE @@ -57,10 +58,22 @@ case "$host" in CPPFLAGS="$CPPFLAGS -I/usr/local/include" LDFLAGS="$LDFLAGS -L/usr/local/lib" if (test "$LD" != "gcc" && test -z "$blibpath"); then - blibpath="/usr/lib:/lib:/usr/local/lib" + AC_MSG_CHECKING([if linkage editor ($LD) accepts -blibpath]) + saved_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS -blibpath:/usr/lib:/lib:/usr/local/lib" + AC_TRY_LINK([], + [], + [ + AC_MSG_RESULT(yes) + blibpath="/usr/lib:/lib:/usr/local/lib" + ], + [ AC_MSG_RESULT(no) ] + ) + LDFLAGS="$saved_LDFLAGS" fi AC_CHECK_FUNC(authenticate, [AC_DEFINE(WITH_AIXAUTHENTICATE)]) AC_DEFINE(BROKEN_GETADDRINFO) + AC_DEFINE(BROKEN_REALPATH) dnl AIX handles lastlog as part of its login message AC_DEFINE(DISABLE_LASTLOG) AC_DEFINE(HAVE_BOGUS_SYS_QUEUE_H) @@ -80,6 +93,22 @@ case "$host" in *-*-darwin*) AC_DEFINE(BROKEN_GETADDRINFO) ;; +*-*-hpux10.26) + if test -z "$GCC"; then + CFLAGS="$CFLAGS -Ae" + fi + CPPFLAGS="$CPPFLAGS -D_HPUX_SOURCE -D_XOPEN_SOURCE -D_XOPEN_SOURCE_EXTENDED=1" + IPADDR_IN_DISPLAY=yes + AC_DEFINE(HAVE_SECUREWARE) + AC_DEFINE(USE_PIPES) + AC_DEFINE(LOGIN_NO_ENDOPT) + AC_DEFINE(LOGIN_NEEDS_UTMPX) + AC_DEFINE(DISABLE_SHADOW) + AC_DEFINE(DISABLE_UTMP) + AC_DEFINE(SPT_TYPE,SPT_PSTAT) + LIBS="$LIBS -lxnet -lsec -lsecpw" + disable_ptmx_check=yes + ;; *-*-hpux10*) if test -z "$GCC"; then CFLAGS="$CFLAGS -Ae" @@ -87,6 +116,8 @@ case "$host" in CPPFLAGS="$CPPFLAGS -D_HPUX_SOURCE -D_XOPEN_SOURCE -D_XOPEN_SOURCE_EXTENDED=1" IPADDR_IN_DISPLAY=yes AC_DEFINE(USE_PIPES) + AC_DEFINE(LOGIN_NO_ENDOPT) + AC_DEFINE(LOGIN_NEEDS_UTMPX) AC_DEFINE(DISABLE_SHADOW) AC_DEFINE(DISABLE_UTMP) AC_DEFINE(SPT_TYPE,SPT_PSTAT) @@ -97,6 +128,8 @@ case "$host" in IPADDR_IN_DISPLAY=yes AC_DEFINE(PAM_SUN_CODEBASE) AC_DEFINE(USE_PIPES) + AC_DEFINE(LOGIN_NO_ENDOPT) + AC_DEFINE(LOGIN_NEEDS_UTMPX) AC_DEFINE(DISABLE_SHADOW) AC_DEFINE(DISABLE_UTMP) AC_DEFINE(SPT_TYPE,SPT_PSTAT) @@ -107,6 +140,7 @@ case "$host" in LDFLAGS="$LDFLAGS" PATH="$PATH:/usr/etc" AC_DEFINE(BROKEN_INET_NTOA) + AC_DEFINE(WITH_ABBREV_NO_TTY) ;; *-*-irix6*) CPPFLAGS="$CPPFLAGS -I/usr/local/include" @@ -117,6 +151,7 @@ case "$host" in AC_DEFINE(WITH_IRIX_AUDIT) AC_CHECK_FUNC(jlimit_startjob, [AC_DEFINE(WITH_IRIX_JOBS)]) AC_DEFINE(BROKEN_INET_NTOA) + AC_DEFINE(WITH_ABBREV_NO_TTY) ;; *-*-linux*) no_dev_ptmx=1 @@ -129,9 +164,6 @@ case "$host" in mips-sony-bsd|mips-sony-newsos4) AC_DEFINE(HAVE_NEWS4) SONY=1 - AC_CHECK_LIB(iberty, xatexit, AC_DEFINE(HAVE_XATEXIT), - AC_MSG_ERROR([*** libiberty missing - please install first or check config.log ***]) - ) ;; *-*-netbsd*) need_dash_r=1 @@ -175,7 +207,6 @@ mips-sony-bsd|mips-sony-newsos4) CPPFLAGS="$CPPFLAGS -DSUNOS4" AC_CHECK_FUNCS(getpwanam) AC_DEFINE(PAM_SUN_CODEBASE) - AC_DEFINE(HAVE_BOGUS_SYS_QUEUE_H) conf_utmp_location=/etc/utmp conf_wtmp_location=/var/adm/wtmp conf_lastlog_location=/var/adm/lastlog @@ -185,7 +216,6 @@ mips-sony-bsd|mips-sony-newsos4) CPPFLAGS="$CPPFLAGS -I/usr/local/include" LDFLAGS="$LDFLAGS -L/usr/local/lib" LIBS="$LIBS -lc89" - AC_DEFINE(HAVE_BOGUS_SYS_QUEUE_H) AC_DEFINE(USE_PIPES) ;; *-sni-sysv*) @@ -195,7 +225,6 @@ mips-sony-bsd|mips-sony-newsos4) IPADDR_IN_DISPLAY=yes AC_DEFINE(USE_PIPES) AC_DEFINE(IP_TOS_IS_BROKEN) - AC_DEFINE(HAVE_BOGUS_SYS_QUEUE_H) # /usr/ucblib/libucb.a no longer needed on ReliantUNIX # Attention: always take care to bind libsocket and libnsl before libc, # otherwise you will find lots of "SIOCGPGRP errno 22" on syslog @@ -225,9 +254,8 @@ mips-sony-bsd|mips-sony-newsos4) no_dev_ptmx=1 AC_DEFINE(BROKEN_SYS_TERMIO_H) AC_DEFINE(USE_PIPES) - AC_DEFINE(HAVE_SCO_PROTECTED_PW) + AC_DEFINE(HAVE_SECUREWARE) AC_DEFINE(DISABLE_SHADOW) - AC_DEFINE(HAVE_BOGUS_SYS_QUEUE_H) AC_DEFINE(BROKEN_SAVED_UIDS) AC_CHECK_FUNCS(getluid setluid) MANTYPE=man @@ -240,9 +268,8 @@ mips-sony-bsd|mips-sony-newsos4) no_dev_ptmx=1 rsh_path="/usr/bin/rcmd" AC_DEFINE(USE_PIPES) - AC_DEFINE(HAVE_SCO_PROTECTED_PW) + AC_DEFINE(HAVE_SECUREWARE) AC_DEFINE(DISABLE_SHADOW) - AC_DEFINE(HAVE_BOGUS_SYS_QUEUE_H) AC_CHECK_FUNCS(getluid setluid) MANTYPE=man ;; @@ -324,12 +351,12 @@ AC_ARG_WITH(libs, AC_CHECK_HEADERS(bstring.h crypt.h endian.h floatingpoint.h \ getopt.h glob.h lastlog.h limits.h login.h \ login_cap.h maillock.h netdb.h netgroup.h \ - netinet/in_systm.h paths.h poll.h pty.h \ - security/pam_appl.h shadow.h stddef.h stdint.h \ + netinet/in_systm.h paths.h pty.h readpassphrase.h \ + rpc/types.h security/pam_appl.h shadow.h stddef.h stdint.h \ strings.h sys/bitypes.h sys/bsdtty.h sys/cdefs.h \ - sys/poll.h sys/queue.h sys/select.h sys/stat.h \ + sys/mman.h sys/select.h sys/stat.h \ sys/stropts.h sys/sysmacros.h sys/time.h \ - sys/ttcompat.h sys/un.h time.h ttyent.h usersec.h \ + sys/un.h time.h ttyent.h usersec.h \ util.h utime.h utmp.h utmpx.h) # Checks for libraries. @@ -651,16 +678,16 @@ AC_ARG_WITH(tcp-wrappers, ) dnl Checks for library functions. -AC_CHECK_FUNCS(arc4random atexit b64_ntop bcopy bindresvport_sa \ +AC_CHECK_FUNCS(arc4random b64_ntop bcopy bindresvport_sa \ clock fchmod fchown freeaddrinfo futimes gai_strerror \ getaddrinfo getcwd getgrouplist getnameinfo getopt \ getrlimit getrusage getttyent glob inet_aton inet_ntoa \ inet_ntop innetgr login_getcapbool md5_crypt memmove \ - mkdtemp on_exit openpty readpassphrase realpath \ - rresvport_af setdtablesize setegid setenv seteuid \ - setlogin setproctitle setresgid setreuid setrlimit \ - setsid setvbuf sigaction sigvec snprintf strerror \ - strlcat strlcpy strmode strsep sysconf tcgetpgrp utimes \ + mkdtemp mmap ngetaddrinfo openpty ogetaddrinfo readpassphrase \ + realpath recvmsg rresvport_af sendmsg setdtablesize setegid \ + setenv seteuid setlogin setproctitle setresgid setreuid setrlimit \ + setsid setvbuf sigaction sigvec snprintf socketpair strerror \ + strlcat strlcpy strmode strsep sysconf tcgetpgrp truncate utimes \ vhangup vsnprintf waitpid __b64_ntop _getpty) dnl IRIX and Solaris 2.5.1 have dirname() in libgen @@ -767,7 +794,6 @@ AC_ARG_WITH(pam, else LIBPAM="-lpam" fi - AC_SUBST(LIBPAM) fi ] @@ -792,179 +818,65 @@ if test "x$PAM_MSG" = "xyes" ; then ) fi -# The big search for OpenSSL +# Search for OpenSSL +saved_CPPFLAGS="$CPPFLAGS" +saved_LDFLAGS="$LDFLAGS" AC_ARG_WITH(ssl-dir, [ --with-ssl-dir=PATH Specify path to OpenSSL installation ], [ if test "x$withval" != "xno" ; then - tryssldir=$withval - fi - ] -) - -saved_LIBS="$LIBS" -saved_LDFLAGS="$LDFLAGS" -saved_CPPFLAGS="$CPPFLAGS" -if test "x$globus_flavor_type" != "xno" ; then -LIBS="$saved_LIBS -lglobus_ssl_utils_${globus_flavor_type} -lssl_${globus_flavor_type} -lcrypto_${globus_flavor_type}" -LDFLAGS="$saved_LDFLAGS" -CPPFLAGS="$saved_CPPFLAGS" -else -if test "x$prefix" != "xNONE" ; then - tryssldir="$tryssldir $prefix" -fi -AC_CACHE_CHECK([for OpenSSL directory], ac_cv_openssldir, [ - for ssldir in $tryssldir "" /usr/local/openssl /usr/lib/openssl /usr/local/ssl /usr/lib/ssl /usr/local /usr/pkg /opt /opt/openssl ; do - CPPFLAGS="$saved_CPPFLAGS" - LDFLAGS="$saved_LDFLAGS" - LIBS="$saved_LIBS -lcrypto" - - # Skip directories if they don't exist - if test ! -z "$ssldir" -a ! -d "$ssldir" ; then - continue; - fi - if test ! -z "$ssldir" -a "x$ssldir" != "x/usr"; then - # Try to use $ssldir/lib if it exists, otherwise - # $ssldir - if test -d "$ssldir/lib" ; then - LDFLAGS="-L$ssldir/lib $saved_LDFLAGS" - if test ! -z "$need_dash_r" ; then - LDFLAGS="-R$ssldir/lib $LDFLAGS" + if test -d "$withval/lib"; then + if test -n "${need_dash_r}"; then + LDFLAGS="-L${withval}/lib -R${withval}/lib ${LDFLAGS}" + else + LDFLAGS="-L${withval}/lib ${LDFLAGS}" fi else - LDFLAGS="-L$ssldir $saved_LDFLAGS" - if test ! -z "$need_dash_r" ; then - LDFLAGS="-R$ssldir $LDFLAGS" + if test -n "${need_dash_r}"; then + LDFLAGS="-L${withval} -R${withval} ${LDFLAGS}" + else + LDFLAGS="-L${withval} ${LDFLAGS}" fi fi - # Try to use $ssldir/include if it exists, otherwise - # $ssldir - if test -d "$ssldir/include" ; then - CPPFLAGS="-I$ssldir/include $saved_CPPFLAGS" + if test -d "$withval/include"; then + CPPFLAGS="-I${withval}/include ${CPPFLAGS}" else - CPPFLAGS="-I$ssldir $saved_CPPFLAGS" + CPPFLAGS="-I${withval} ${CPPFLAGS}" fi fi + ] +) - # Basic test to check for compatible version and correct linking - # *does not* test for RSA - that comes later. - AC_TRY_RUN( - [ -#include -#include -int main(void) -{ - char a[2048]; - memset(a, 0, sizeof(a)); - RAND_add(a, sizeof(a), sizeof(a)); - return(RAND_status() <= 0); -} - ], - [ - found_crypto=1 - break; - ], [] - ) - - if test ! -z "$found_crypto" ; then - break; - fi - done - - if test -z "$found_crypto" ; then - AC_MSG_ERROR([Could not find working OpenSSL library, please install or check config.log]) - fi - if test -z "$ssldir" ; then - ssldir="(system)" - fi - - ac_cv_openssldir=$ssldir -]) - -if (test ! -z "$ac_cv_openssldir" && test "x$ac_cv_openssldir" != "x(system)") ; then - AC_DEFINE(HAVE_OPENSSL) - dnl Need to recover ssldir - test above runs in subshell - ssldir=$ac_cv_openssldir - if test ! -z "$ssldir" -a "x$ssldir" != "x/usr"; then - # Try to use $ssldir/lib if it exists, otherwise - # $ssldir - if test -d "$ssldir/lib" ; then - LDFLAGS="-L$ssldir/lib $saved_LDFLAGS" - if test ! -z "$need_dash_r" ; then - LDFLAGS="-R$ssldir/lib $LDFLAGS" - fi - else - LDFLAGS="-L$ssldir $saved_LDFLAGS" - if test ! -z "$need_dash_r" ; then - LDFLAGS="-R$ssldir $LDFLAGS" - fi - fi - # Try to use $ssldir/include if it exists, otherwise - # $ssldir - if test -d "$ssldir/include" ; then - CPPFLAGS="-I$ssldir/include $saved_CPPFLAGS" - else - CPPFLAGS="-I$ssldir $saved_CPPFLAGS" - fi - fi -fi -if test "x$gsi_path" == "xno" ; then -LIBS="$saved_LIBS -lcrypto" +# Patch up SSL libraries for GSI authentication as needed +if test "x$globus_flavor_type" != "xno" ; then + # For Globus 2, always link with the static libraries + LIBS="$LIBS ${gsi_path}/libglobus_ssl_utils_${globus_flavor_type}.a ${gsi_path}/libssl_${globus_flavor_type}.a ${gsi_path}/libcrypto_${globus_flavor_type}.a" else -LIBS="$saved_LIBS -lssl -lcrypto" -fi + if test "x$gsi_path" != "xno" ; then + # Older GSI needs -lssl too + LIBS="$LIBS -lssl -lcrypto" + else # if no GSI authentication (i.e., OpenSSL default) + LIBS="$LIBS -lcrypto" + fi fi # globus_flavor_type -# Now test RSA support -saved_LIBS="$LIBS" -AC_MSG_CHECKING([for RSA support]) -for WANTS_RSAREF in "" 1 ; do - if test -z "$WANTS_RSAREF" ; then - LIBS="$saved_LIBS" - else - LIBS="$saved_LIBS -lRSAglue -lrsaref" - fi - AC_TRY_RUN([ -#include -#include -#include -#include -#include -int main(void) -{ - int num; RSA *key; static unsigned char p_in[] = "blahblah"; - unsigned char c[256], p[256]; - memset(c, 0, sizeof(c)); RAND_add(c, sizeof(c), sizeof(c)); - if ((key=RSA_generate_key(512, 3, NULL, NULL))==NULL) return(1); - num = RSA_public_encrypt(sizeof(p_in) - 1, p_in, c, key, RSA_PKCS1_PADDING); - return(-1 == RSA_private_decrypt(num, c, p, key, RSA_PKCS1_PADDING)); -} - ], +AC_TRY_LINK_FUNC(RAND_add, AC_DEFINE(HAVE_OPENSSL), [ - rsa_works=1 - break; - ], []) -done -LIBS="$saved_LIBS" - -if test ! -z "$no_rsa" ; then - AC_MSG_RESULT(disabled) - RSA_MSG="disabled" -else - if test -z "$rsa_works" ; then - AC_MSG_WARN([*** No RSA support found *** ]) - RSA_MSG="no" - else - if test -z "$WANTS_RSAREF" ; then - AC_MSG_RESULT(yes) - RSA_MSG="yes" + dnl Check default openssl install dir + if test -n "${need_dash_r}"; then + LDFLAGS="-L/usr/local/ssl/lib -R/usr/local/ssl/lib ${saved_LDFLAGS}" else - RSA_MSG="yes (using RSAref)" - AC_MSG_RESULT(using RSAref) - LIBS="$LIBS -lcrypto -lRSAglue -lrsaref" + LDFLAGS="-L/usr/local/ssl/lib ${saved_LDFLAGS}" fi - fi -fi + CPPFLAGS="-I/usr/local/ssl/include ${saved_CPPFLAGS}" + AC_TRY_LINK_FUNC(RAND_add, AC_DEFINE(HAVE_OPENSSL), + [ + AC_MSG_ERROR([*** Can't find recent OpenSSL libcrypto (see config.log for details) ***]) + ] + ) + ] +) + # Sanity check OpenSSL headers AC_MSG_CHECKING([whether OpenSSL's headers match the library]) @@ -1127,9 +1039,33 @@ AC_ARG_WITH(entropy-timeout, fi ] ) - AC_DEFINE_UNQUOTED(ENTROPY_TIMEOUT_MSEC, $entropy_timeout) +ssh_privsep_user=sshd +AC_ARG_WITH(privsep-user, + [ --with-privsep-user=user Specify non-privileged user for privilege separation], + [ + if test -n "$withval"; then + ssh_privsep_user=$withval + fi + ] +) +AC_DEFINE_UNQUOTED(SSH_PRIVSEP_USER, "$ssh_privsep_user") + +# We do this little dance with the search path to insure +# that programs that we select for use by installed programs +# (which may be run by the super-user) come from trusted +# locations before they come from the user's private area. +# This should help avoid accidentally configuring some +# random version of a program in someone's personal bin. + +OPATH=$PATH +PATH=/bin:/usr/bin +test -h /bin 2> /dev/null && PATH=/usr/bin +test -d /sbin && PATH=$PATH:/sbin +test -d /usr/sbin && PATH=$PATH:/usr/sbin +PATH=$PATH:/etc:$OPATH + # These programs are used by the command hashing source to gather entropy OSSH_PATH_ENTROPY_PROG(PROG_LS, ls) OSSH_PATH_ENTROPY_PROG(PROG_NETSTAT, netstat) @@ -1147,6 +1083,8 @@ OSSH_PATH_ENTROPY_PROG(PROG_VMSTAT, vmstat) OSSH_PATH_ENTROPY_PROG(PROG_UPTIME, uptime) OSSH_PATH_ENTROPY_PROG(PROG_IPCS, ipcs) OSSH_PATH_ENTROPY_PROG(PROG_TAIL, tail) +# restore PATH +PATH=$OPATH # Where does ssh-rand-helper get its randomness from? INSTALL_SSH_PRNG_CMDS="" @@ -1176,6 +1114,11 @@ AC_CHECK_SIZEOF(int, 4) AC_CHECK_SIZEOF(long int, 4) AC_CHECK_SIZEOF(long long int, 8) +# Sanity check long long for some platforms (AIX) +if test "x$ac_cv_sizeof_long_long_int" = "x4" ; then + ac_cv_sizeof_long_long_int=0 +fi + # More checks for data types AC_CACHE_CHECK([for u_int type], ac_cv_have_u_int, [ AC_TRY_COMPILE( @@ -1684,6 +1627,40 @@ if test "x$ac_cv_have_pw_change_in_struct_passwd" = "xyes" ; then AC_DEFINE(HAVE_PW_CHANGE_IN_PASSWD) fi +AC_CACHE_CHECK([for msg_accrights field in struct msghdr], + ac_cv_have_accrights_in_msghdr, [ + AC_TRY_COMPILE( + [ +#include +#include +#include + ], + [ struct msghdr m; m.msg_accrights = 0; ], + [ ac_cv_have_accrights_in_msghdr="yes" ], + [ ac_cv_have_accrights_in_msghdr="no" ] + ) +]) +if test "x$ac_cv_have_accrights_in_msghdr" = "xyes" ; then + AC_DEFINE(HAVE_ACCRIGHTS_IN_MSGHDR) +fi + +AC_CACHE_CHECK([for msg_control field in struct msghdr], + ac_cv_have_control_in_msghdr, [ + AC_TRY_COMPILE( + [ +#include +#include +#include + ], + [ struct msghdr m; m.msg_control = 0; ], + [ ac_cv_have_control_in_msghdr="yes" ], + [ ac_cv_have_control_in_msghdr="no" ] + ) +]) +if test "x$ac_cv_have_control_in_msghdr" = "xyes" ; then + AC_DEFINE(HAVE_CONTROL_IN_MSGHDR) +fi + AC_CACHE_CHECK([if libc defines __progname], ac_cv_libc_defines___progname, [ AC_TRY_LINK([], [ extern char *__progname; printf("%s", __progname); ], @@ -1695,6 +1672,32 @@ if test "x$ac_cv_libc_defines___progname" = "xyes" ; then AC_DEFINE(HAVE___PROGNAME) fi +AC_CACHE_CHECK([whether $CC implements __FUNCTION__], ac_cv_cc_implements___FUNCTION__, [ + AC_TRY_LINK([ +#include +], + [ printf("%s", __FUNCTION__); ], + [ ac_cv_cc_implements___FUNCTION__="yes" ], + [ ac_cv_cc_implements___FUNCTION__="no" ] + ) +]) +if test "x$ac_cv_cc_implements___FUNCTION__" = "xyes" ; then + AC_DEFINE(HAVE___FUNCTION__) +fi + +AC_CACHE_CHECK([whether $CC implements __func__], ac_cv_cc_implements___func__, [ + AC_TRY_LINK([ +#include +], + [ printf("%s", __func__); ], + [ ac_cv_cc_implements___func__="yes" ], + [ ac_cv_cc_implements___func__="no" ] + ) +]) +if test "x$ac_cv_cc_implements___func__" = "xyes" ; then + AC_DEFINE(HAVE___func__) +fi + AC_CACHE_CHECK([whether getopt has optreset support], ac_cv_have_getopt_optreset, [ AC_TRY_LINK( @@ -1733,11 +1736,11 @@ if test "x$ac_cv_libc_defines_sys_nerr" = "xyes" ; then AC_DEFINE(HAVE_SYS_NERR) fi - -# Check whether user wants Kerberos support SCARD_MSG="no" -AC_ARG_WITH(smartcard, - [ --with-smartcard Enable smartcard support], + +# Check whether user wants sectok support +AC_ARG_WITH(sectok, + [ --with-sectok Enable smartcard support using libsectok], [ if test "x$withval" != "xno" ; then if test "x$withval" != "xyes" ; then @@ -1759,12 +1762,33 @@ AC_ARG_WITH(smartcard, AC_MSG_ERROR(Can't find libsectok) fi AC_DEFINE(SMARTCARD) - SCARD_MSG="yes" + AC_DEFINE(USE_SECTOK) + SCARD_MSG="yes, using sectok" fi ] ) +# Check whether user wants OpenSC support +AC_ARG_WITH(opensc, + AC_HELP_STRING([--with-opensc=PFX], + [Enable smartcard support using OpenSC]), + opensc_config_prefix="$withval", opensc_config_prefix="") +if test x$opensc_config_prefix != x ; then + OPENSC_CONFIG=$opensc_config_prefix/bin/opensc-config + AC_PATH_PROG(OPENSC_CONFIG, opensc-config, no) + if test "$OPENSC_CONFIG" != "no"; then + LIBOPENSC_CFLAGS=`$OPENSC_CONFIG --cflags` + LIBOPENSC_LIBS=`$OPENSC_CONFIG --libs` + CPPFLAGS="$CPPFLAGS $LIBOPENSC_CFLAGS" + LDFLAGS="$LDFLAGS $LIBOPENSC_LIBS" + AC_DEFINE(SMARTCARD) + AC_DEFINE(USE_OPENSC) + SCARD_MSG="yes, using OpenSC" + fi +fi + # Check whether user wants Kerberos 5 support +KRB5_MSG="no" AC_ARG_WITH(kerberos5, [ --with-kerberos5=PATH Enable Kerberos 5 support], [ @@ -1777,6 +1801,7 @@ AC_ARG_WITH(kerberos5, CPPFLAGS="$CPPFLAGS -I${KRB5ROOT}/include" LDFLAGS="$LDFLAGS -L${KRB5ROOT}/lib" AC_DEFINE(KRB5) + KRB5_MSG="yes" AC_MSG_CHECKING(whether we are using Heimdal) AC_TRY_COMPILE([ #include ], [ char *tmp = heimdal_version; ], @@ -1920,6 +1945,17 @@ AC_ARG_WITH(rsh, ] ) +PRIVSEP_PATH=/var/empty +AC_ARG_WITH(privsep-path, + [ --with-privsep-path=xxx Path for privilege seperation chroot ], + [ + if test "x$withval" != "$no" ; then + PRIVSEP_PATH=$withval + fi + ] +) +AC_SUBST(PRIVSEP_PATH) + AC_ARG_WITH(xauth, [ --with-xauth=PATH Specify path to xauth program ], [ @@ -1954,12 +1990,14 @@ if test ! -z "$MAIL" ; then fi if test -z "$no_dev_ptmx" ; then - AC_CHECK_FILE("/dev/ptmx", - [ - AC_DEFINE_UNQUOTED(HAVE_DEV_PTMX) - have_dev_ptmx=1 - ] - ) + if test "x$disable_ptmx_check" != "xyes" ; then + AC_CHECK_FILE("/dev/ptmx", + [ + AC_DEFINE_UNQUOTED(HAVE_DEV_PTMX) + have_dev_ptmx=1 + ] + ) + fi fi AC_CHECK_FILE("/dev/ptc", [ @@ -2059,17 +2097,28 @@ else ) fi +dnl BSD systems use /etc/login.conf so --with-default-path= has no effect +if test $ac_cv_func_login_getcapbool = "yes" -a \ + $ac_cv_header_login_cap_h = "yes" ; then + USES_LOGIN_CONF=yes +fi # Whether to mess with the default path SERVER_PATH_MSG="(default)" AC_ARG_WITH(default-path, - [ --with-default-path=PATH Specify default \$PATH environment for server], + [ --with-default-path= Specify default \$PATH environment for server], [ - if test "x$withval" != "xno" ; then + if test "$USES_LOGIN_CONF" = "yes" ; then + AC_MSG_WARN([ +--with-default-path=PATH has no effect on this system. +Edit /etc/login.conf instead.]) + elif test "x$withval" != "xno" ; then user_path="$withval" SERVER_PATH_MSG="$withval" fi ], - [ + [ if test "$USES_LOGIN_CONF" = "yes" ; then + AC_MSG_WARN([Make sure the path to scp is in /etc/login.conf]) + else AC_TRY_RUN( [ /* find out what STDPATH is */ @@ -2119,10 +2168,25 @@ main() AC_MSG_RESULT(Adding $t_bindir to USER_PATH so scp will work) fi fi + fi ] +) +if test "$USES_LOGIN_CONF" != "yes" ; then + AC_DEFINE_UNQUOTED(USER_PATH, "$user_path") + AC_SUBST(user_path) +fi + +# Set superuser path separately to user path +MD5_MSG="no" +AC_ARG_WITH(superuser-path, + [ --with-superuser-path= Specify different path for super-user], + [ + if test "x$withval" != "xno" ; then + AC_DEFINE_UNQUOTED(SUPERUSER_PATH, "$withval") + superuser_path=$withval + fi ] ) -AC_DEFINE_UNQUOTED(USER_PATH, "$user_path") -AC_SUBST(user_path) + # Whether to force IPv4 by default (needed on broken glibc Linux) IPV4_HACK_MSG="no" @@ -2192,23 +2256,26 @@ AC_SUBST(SSHMODE) # Where to place sshd.pid piddir=/var/run +# make sure the directory exists +if test ! -d $piddir ; then + piddir=`eval echo ${sysconfdir}` + case $piddir in + NONE/*) piddir=`echo $piddir | sed "s~NONE~$ac_default_prefix~"` ;; + esac +fi + AC_ARG_WITH(pid-dir, [ --with-pid-dir=PATH Specify location of ssh.pid file], [ if test "x$withval" != "xno" ; then piddir=$withval + if test ! -d $piddir ; then + AC_MSG_WARN([** no $piddir directory on this system **]) + fi fi ] ) -# make sure the directory exists -if test ! -d $piddir ; then - piddir=`eval echo ${sysconfdir}` - case $piddir in - NONE/*) piddir=`echo $piddir | sed "s~NONE~$ac_default_prefix~"` ;; - esac -fi - AC_DEFINE_UNQUOTED(_PATH_SSH_PIDDIR, "$piddir") AC_SUBST(piddir) @@ -2460,32 +2527,43 @@ D=`eval echo ${sysconfdir}` ; D=`eval echo ${D}` E=`eval echo ${libexecdir}/ssh-askpass` ; E=`eval echo ${E}` F=`eval echo ${mandir}/${mansubdir}X` ; F=`eval echo ${F}` G=`eval echo ${piddir}` ; G=`eval echo ${G}` -H=`eval echo ${user_path}` ; H=`eval echo ${H}` +H=`eval echo ${PRIVSEP_PATH}` ; H=`eval echo ${H}` +I=`eval echo ${user_path}` ; I=`eval echo ${I}` +J=`eval echo ${superuser_path}` ; J=`eval echo ${J}` echo "" echo "OpenSSH has been configured with the following options:" -echo " User binaries: $B" -echo " System binaries: $C" -echo " Configuration files: $D" -echo " Askpass program: $E" -echo " Manual pages: $F" -echo " PID file: $G" -echo " sshd default user PATH: $H" -echo " Manpage format: $MANTYPE" -echo " PAM support: ${PAM_MSG}" -echo " KerberosIV support: $KRB4_MSG" -echo " Smartcard support: $SCARD_MSG" -echo " AFS support: $AFS_MSG" -echo " S/KEY support: $SKEY_MSG" -echo " TCP Wrappers support: $TCPW_MSG" -echo " MD5 password support: $MD5_MSG" -echo " IP address in \$DISPLAY hack: $DISPLAY_HACK_MSG" -echo " Use IPv4 by default hack: $IPV4_HACK_MSG" -echo " Translate v4 in v6 hack: $IPV4_IN6_HACK_MSG" -echo " BSD Auth support: $BSD_AUTH_MSG" -echo " Random number source: $RAND_MSG" +echo " User binaries: $B" +echo " System binaries: $C" +echo " Configuration files: $D" +echo " Askpass program: $E" +echo " Manual pages: $F" +echo " PID file: $G" +echo " Privilege separation chroot path: $H" +if test "$USES_LOGIN_CONF" = "yes" ; then +echo " At runtime, sshd will use the path defined in /etc/login.conf" +else +echo " sshd default user PATH: $I" +fi +if test ! -z "$superuser_path" ; then +echo " sshd superuser user PATH: $J" +fi +echo " Manpage format: $MANTYPE" +echo " PAM support: ${PAM_MSG}" +echo " KerberosIV support: $KRB4_MSG" +echo " KerberosV support: $KRB5_MSG" +echo " Smartcard support: $SCARD_MSG" +echo " AFS support: $AFS_MSG" +echo " S/KEY support: $SKEY_MSG" +echo " TCP Wrappers support: $TCPW_MSG" +echo " MD5 password support: $MD5_MSG" +echo " IP address in \$DISPLAY hack: $DISPLAY_HACK_MSG" +echo " Use IPv4 by default hack: $IPV4_HACK_MSG" +echo " Translate v4 in v6 hack: $IPV4_IN6_HACK_MSG" +echo " BSD Auth support: $BSD_AUTH_MSG" +echo " Random number source: $RAND_MSG" if test ! -z "$USE_RAND_HELPER" ; then - echo " ssh-rand-helper collects from: $RAND_HELPER_MSG" +echo " ssh-rand-helper collects from: $RAND_HELPER_MSG" fi echo "" diff --git a/openssh/contrib/aix/buildbff.sh b/openssh/contrib/aix/buildbff.sh index 6c7aaf4..4095884 100755 --- a/openssh/contrib/aix/buildbff.sh +++ b/openssh/contrib/aix/buildbff.sh @@ -11,21 +11,14 @@ umask 022 PKGNAME=openssh +PKGDIR=package -PATH=$PATH:`pwd` # set path for external tools +PATH=`pwd`:$PATH # set path for external tools export PATH -## 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/\"$//'` -BFFVERSION=`echo $VERSION | sed 's/p/./g'` - -echo "Building BFF for $PKGNAME $VERSION (package version $BFFVERSION)" -PKGDIR=package - -# Clean build directory and package file +# Clean build directory rm -rf $PKGDIR mkdir $PKGDIR -rm -f $PKGNAME-$VERSION.bff if [ ! -f ../../Makefile ] then @@ -40,6 +33,29 @@ FAKE_ROOT=$START/$PKGDIR cd ../.. make install-nokeys DESTDIR=$FAKE_ROOT +if [ $? -gt 0 ] +then + echo "Fake root install failed, stopping." + exit 1 +fi + +# +# Extract common info requires for the 'info' part of the package. +# AIX requires 4-part version numbers +# +VERSION=`./ssh -V 2>&1 | sed -e 's/,.*//' | cut -f 2 -d _` +MAJOR=`echo $VERSION | cut -f 1 -d p | cut -f 1 -d .` +MINOR=`echo $VERSION | cut -f 1 -d p | cut -f 2 -d .` +PATCH=`echo $VERSION | cut -f 1 -d p | cut -f 3 -d .` +PORTABLE=`echo $VERSION | cut -f 2 -d p` +if [ "$PATCH" = "" ] +then + PATCH=0 +fi +BFFVERSION=`printf "%d.%d.%d.%d" $MAJOR $MINOR $PATCH $PORTABLE` + +echo "Building BFF for $PKGNAME $VERSION (package version $BFFVERSION)" + # # Fill in some details, like prefix and sysconfdir # the eval also expands variables like sysconfdir=${prefix}/etc @@ -175,6 +191,7 @@ mv ../lpp_name . # file list on the fly and feed it to backup using -i # echo Creating $PKGNAME-$VERSION.bff with backup... +rm -f $PKGNAME-$VERSION.bff ( echo "./lpp_name" find . ! -name lpp_name -a ! -name . -print diff --git a/openssh/contrib/aix/inventory.sh b/openssh/contrib/aix/inventory.sh index aa44ab9..78df0d1 100755 --- a/openssh/contrib/aix/inventory.sh +++ b/openssh/contrib/aix/inventory.sh @@ -52,7 +52,7 @@ find . ! -name . -print | perl -ne '{ } elsif ( -f $_ ) { # Entry is File print "\ttype=FILE\n"; - print "\tsize=VOLATILE\n"; + print "\tsize=$sz\n"; print "\tchecksum=VOLATILE\n"; } elsif ( -d $_ ) { # Entry is Directory diff --git a/openssh/includes.h b/openssh/includes.h index 6320c61..e20d7a5 100644 --- a/openssh/includes.h +++ b/openssh/includes.h @@ -21,21 +21,10 @@ static /**/const char *const rcsid[] = { (char *)rcsid, "\100(#)" msg } #include "config.h" -#include "openbsd-compat/bsd-nextstep.h" - -#include -#include -#include -#include -#include - -#include -#include - #include #include #include -#include +#include /* For O_NONBLOCK */ #include #include #include @@ -46,19 +35,11 @@ static /**/const char *const rcsid[] = { (char *)rcsid, "\100(#)" msg } #include #ifdef HAVE_LIMITS_H -# include +# include /* For PATH_MAX */ #endif #ifdef HAVE_GETOPT_H # include #endif -#ifndef HAVE_GETOPT_OPTRESET -#define getopt(ac, av, o) BSDgetopt(ac, av, o) -#define opterr BSDopterr -#define optind BSDoptind -#define optopt BSDoptopt -#define optreset BSDoptreset -#define optarg BSDoptarg -#endif #ifdef HAVE_BSTRING_H # include #endif @@ -75,37 +56,105 @@ static /**/const char *const rcsid[] = { (char *)rcsid, "\100(#)" msg } #ifdef HAVE_ENDIAN_H # include #endif -#ifdef HAVE_SYS_SELECT_H -# include +#ifdef HAVE_TTYENT_H +# include +#endif +#ifdef HAVE_UTIME_H +# include +#endif +#ifdef HAVE_MAILLOCK_H +# include /* For _PATH_MAILDIR */ +#endif +#ifdef HAVE_NEXT +# include +#endif +#include /* For STDIN_FILENO, etc */ +#include /* Struct winsize */ + +/* + *-*-nto-qnx needs these headers for strcasecmp and LASTLOG_FILE respectively + */ +#ifdef HAVE_STRINGS_H +# include +#endif +#ifdef HAVE_LOGIN_H +# include +#endif + +#ifdef HAVE_UTMP_H +# include +#endif +#ifdef HAVE_UTMPX_H +# ifdef HAVE_TV_IN_UTMPX +# include +# endif +# include +#endif +#ifdef HAVE_LASTLOG_H +# include #endif +#ifdef HAVE_PATHS_H +# include /* For _PATH_XXX */ +#endif + +#include +#include +#include +#include #ifdef HAVE_SYS_TIME_H -# include +# include /* For timersub */ +#endif +#include +#ifdef HAVE_SYS_SELECT_H +# include #endif #ifdef HAVE_SYS_BSDTTY_H # include #endif -#ifdef HAVE_TTYENT_H -# include +#include /* For MAXPATHLEN and roundup() */ +#ifdef HAVE_SYS_UN_H +# include /* For sockaddr_un */ #endif -#ifdef USE_PAM -# include +#ifdef HAVE_SYS_BITYPES_H +# include /* For u_intXX_t */ +#endif +#ifdef HAVE_SYS_CDEFS_H +# include /* For __P() */ #endif -#ifdef HAVE_POLL_H -# include -#else -# ifdef HAVE_SYS_POLL_H -# include -# endif +#ifdef HAVE_SYS_STAT_H +# include /* For S_* constants and macros */ #endif #ifdef HAVE_SYS_SYSMACROS_H -# include +# include /* For MIN, MAX, etc */ #endif -#ifdef HAVE_UTIME_H -# include +#ifdef HAVE_SYS_MMAN_H +#include /* for MAP_ANONYMOUS */ +#endif + +#include /* For typedefs */ +#include /* For IPv6 macros */ +#include /* For IPTOS macros */ +#include +#include +#ifdef HAVE_RPC_TYPES_H +# include /* For INADDR_LOOPBACK */ #endif +#ifdef USE_PAM +# include +#endif +#ifdef HAVE_READPASSPHRASE_H +# include +#endif + +#include /* For OPENSSL_VERSION_NUMBER */ + +#include "defines.h" + #include "version.h" #include "openbsd-compat/openbsd-compat.h" #include "openbsd-compat/bsd-cygwin_util.h" +#include "openbsd-compat/bsd-nextstep.h" + #include "entropy.h" #endif /* INCLUDES_H */ diff --git a/openssh/kex.c b/openssh/kex.c index 480d51a..b90d750 100644 --- a/openssh/kex.c +++ b/openssh/kex.c @@ -23,7 +23,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: kex.c,v 1.47 2002/02/28 15:46:33 markus Exp $"); +RCSID("$OpenBSD: kex.c,v 1.50 2002/05/15 15:47:49 mouring Exp $"); #include @@ -40,6 +40,7 @@ RCSID("$OpenBSD: kex.c,v 1.47 2002/02/28 15:46:33 markus Exp $"); #include "mac.h" #include "match.h" #include "dispatch.h" +#include "monitor.h" #ifdef GSSAPI #include "ssh-gss.h" @@ -47,6 +48,11 @@ RCSID("$OpenBSD: kex.c,v 1.47 2002/02/28 15:46:33 markus Exp $"); #define KEX_COOKIE_LEN 16 +/* Use privilege separation for sshd */ +int use_privsep; +struct monitor *pmonitor; + + /* prototype */ static void kex_kexinit_finish(Kex *); static void kex_choose_conf(Kex *); @@ -55,16 +61,15 @@ static void kex_choose_conf(Kex *); static void kex_prop2buf(Buffer *b, char *proposal[PROPOSAL_MAX]) { - u_int32_t rand = 0; int i; buffer_clear(b); - for (i = 0; i < KEX_COOKIE_LEN; i++) { - if (i % 4 == 0) - rand = arc4random(); - buffer_put_char(b, rand & 0xff); - rand >>= 8; - } + /* + * add a dummy cookie, the cookie will be overwritten by + * kex_send_kexinit(), each time a kexinit is set + */ + for (i = 0; i < KEX_COOKIE_LEN; i++) + buffer_put_char(b, 0); for (i = 0; i < PROPOSAL_MAX; i++) buffer_put_cstring(b, proposal[i]); buffer_put_char(b, 0); /* first_kex_packet_follows */ @@ -150,6 +155,10 @@ kex_finish(Kex *kex) void kex_send_kexinit(Kex *kex) { + u_int32_t rand = 0; + u_char *cookie; + int i; + if (kex == NULL) { error("kex_send_kexinit: no kex, cannot rekey"); return; @@ -159,6 +168,17 @@ kex_send_kexinit(Kex *kex) return; } kex->done = 0; + + /* generate a random cookie */ + if (buffer_len(&kex->my) < KEX_COOKIE_LEN) + fatal("kex_send_kexinit: kex proposal too short"); + cookie = buffer_ptr(&kex->my); + for (i = 0; i < KEX_COOKIE_LEN; i++) { + if (i % 4 == 0) + rand = arc4random(); + cookie[i] = rand; + rand >>= 8; + } packet_start(SSH2_MSG_KEXINIT); packet_put_raw(buffer_ptr(&kex->my), buffer_len(&kex->my)); packet_send(); diff --git a/openssh/kex.h b/openssh/kex.h index a9bc978..db39545 100644 --- a/openssh/kex.h +++ b/openssh/kex.h @@ -1,4 +1,4 @@ -/* $OpenBSD: kex.h,v 1.29 2002/02/14 23:41:01 markus Exp $ */ +/* $OpenBSD: kex.h,v 1.30 2002/03/18 17:50:31 provos Exp $ */ /* * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. @@ -118,6 +118,7 @@ struct Kex { char *server_version_string; int (*verify_host_key)(Key *); Key *(*load_host_key)(int); + int (*host_key_index)(Key *); struct KexOptions options; }; diff --git a/openssh/key.c b/openssh/key.c index c3f6452..077c517 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.41 2002/02/28 15:46:33 markus Exp $"); +RCSID("$OpenBSD: key.c,v 1.43 2002/03/19 10:49:35 markus Exp $"); #include @@ -803,3 +803,46 @@ key_verify( break; } } + +/* Converts a private to a public key */ + +Key * +key_demote(Key *k) +{ + Key *pk; + + pk = xmalloc(sizeof(*pk)); + pk->type = k->type; + pk->flags = k->flags; + pk->dsa = NULL; + pk->rsa = NULL; + + switch (k->type) { + case KEY_RSA1: + case KEY_RSA: + if ((pk->rsa = RSA_new()) == NULL) + fatal("key_demote: RSA_new failed"); + if ((pk->rsa->e = BN_dup(k->rsa->e)) == NULL) + fatal("key_demote: BN_dup failed"); + if ((pk->rsa->n = BN_dup(k->rsa->n)) == NULL) + fatal("key_demote: BN_dup failed"); + break; + case KEY_DSA: + if ((pk->dsa = DSA_new()) == NULL) + fatal("key_demote: DSA_new failed"); + if ((pk->dsa->p = BN_dup(k->dsa->p)) == NULL) + fatal("key_demote: BN_dup failed"); + if ((pk->dsa->q = BN_dup(k->dsa->q)) == NULL) + fatal("key_demote: BN_dup failed"); + if ((pk->dsa->g = BN_dup(k->dsa->g)) == NULL) + fatal("key_demote: BN_dup failed"); + if ((pk->dsa->pub_key = BN_dup(k->dsa->pub_key)) == NULL) + fatal("key_demote: BN_dup failed"); + break; + default: + fatal("key_free: bad key type %d", k->type); + break; + } + + return (pk); +} diff --git a/openssh/key.h b/openssh/key.h index 7b4d1c2..957dab2 100644 --- a/openssh/key.h +++ b/openssh/key.h @@ -1,4 +1,4 @@ -/* $OpenBSD: key.h,v 1.18 2002/02/24 19:14:59 markus Exp $ */ +/* $OpenBSD: key.h,v 1.19 2002/03/18 17:23:31 markus Exp $ */ /* * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. @@ -59,6 +59,7 @@ struct Key { Key *key_new(int); Key *key_new_private(int); void key_free(Key *); +Key *key_demote(Key *); int key_equal(Key *, Key *); char *key_fingerprint(Key *, enum fp_type, enum fp_rep); char *key_type(Key *); diff --git a/openssh/servconf.c b/openssh/servconf.c index adad372..a8f6cfe 100644 --- a/openssh/servconf.c +++ b/openssh/servconf.c @@ -10,7 +10,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: servconf.c,v 1.101 2002/02/04 12:15:25 markus Exp $"); +RCSID("$OpenBSD: servconf.c,v 1.109 2002/05/15 21:02:52 markus Exp $"); #if defined(KRB4) #include @@ -45,6 +45,8 @@ static void add_one_listen_addr(ServerOptions *, char *, u_short); /* AF_UNSPEC or AF_INET or AF_INET6 */ extern int IPv4or6; +/* Use of privilege separation or not */ +extern int use_privsep; /* Initializes the server options to their default values. */ @@ -125,6 +127,9 @@ initialize_server_options(ServerOptions *options) options->client_alive_count_max = -1; options->authorized_keys_file = NULL; options->authorized_keys_file2 = NULL; + + /* Needs to be accessable in many places */ + use_privsep = -1; } void @@ -211,7 +216,7 @@ fill_default_server_options(ServerOptions *options) #endif #if defined(KRB4) || defined(KRB5) if (options->kerberos_authentication == -1) - options->kerberos_authentication = (access(KEYFILE, R_OK) == 0); + options->kerberos_authentication = 0; if (options->kerberos_or_local_passwd == -1) options->kerberos_or_local_passwd = 1; if (options->kerberos_ticket_cleanup == -1) @@ -223,7 +228,7 @@ fill_default_server_options(ServerOptions *options) #endif #ifdef AFS if (options->afs_token_passing == -1) - options->afs_token_passing = k_hasafs(); + options->afs_token_passing = 0; #endif if (options->password_authentication == -1) options->password_authentication = 1; @@ -260,6 +265,10 @@ fill_default_server_options(ServerOptions *options) } if (options->authorized_keys_file == NULL) options->authorized_keys_file = _PATH_SSH_USER_PERMITTED_KEYS; + + /* Turn privilege separation _off_ by default */ + if (use_privsep == -1) + use_privsep = 0; } /* Keyword tokens. */ @@ -295,6 +304,7 @@ typedef enum { sBanner, sVerifyReverseMapping, sHostbasedAuthentication, sHostbasedUsesNameFromPacketOnly, sClientAliveInterval, sClientAliveCountMax, sAuthorizedKeysFile, sAuthorizedKeysFile2, + sUsePrivilegeSeparation, sDeprecated } ServerOpCodes; @@ -377,6 +387,7 @@ static struct { { "clientalivecountmax", sClientAliveCountMax }, { "authorizedkeysfile", sAuthorizedKeysFile }, { "authorizedkeysfile2", sAuthorizedKeysFile2 }, + { "useprivilegeseparation", sUsePrivilegeSeparation}, { NULL, sBadOption } }; @@ -767,6 +778,10 @@ parse_flag: intptr = &options->allow_tcp_forwarding; goto parse_flag; + case sUsePrivilegeSeparation: + intptr = &use_privsep; + goto parse_flag; + case sAllowUsers: while ((arg = strdelim(&cp)) && *arg != '\0') { if (options->num_allow_users >= MAX_ALLOW_USERS) diff --git a/openssh/servconf.h b/openssh/servconf.h index ecb3f18..0973882 100644 --- a/openssh/servconf.h +++ b/openssh/servconf.h @@ -1,4 +1,4 @@ -/* $OpenBSD: servconf.h,v 1.54 2002/03/04 17:27:39 stevesk Exp $ */ +/* $OpenBSD: servconf.h,v 1.57 2002/03/20 19:12:25 stevesk Exp $ */ /* * Author: Tatu Ylonen @@ -137,7 +137,6 @@ typedef struct { char *authorized_keys_file; /* File containing public keys */ char *authorized_keys_file2; int pam_authentication_via_kbd_int; - } ServerOptions; void initialize_server_options(ServerOptions *); diff --git a/openssh/session.c b/openssh/session.c index efed43b..290d91c 100644 --- a/openssh/session.c +++ b/openssh/session.c @@ -33,7 +33,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: session.c,v 1.128 2002/02/16 00:51:44 markus Exp $"); +RCSID("$OpenBSD: session.c,v 1.134 2002/03/29 18:59:31 markus Exp $"); #include "ssh.h" #include "ssh1.h" @@ -56,6 +56,7 @@ RCSID("$OpenBSD: session.c,v 1.128 2002/02/16 00:51:44 markus Exp $"); #include "serverloop.h" #include "canohost.h" #include "session.h" +#include "monitor_wrap.h" #ifdef GSSAPI #include "ssh-gss.h" @@ -67,39 +68,11 @@ RCSID("$OpenBSD: session.c,v 1.128 2002/02/16 00:51:44 markus Exp $"); #define is_winnt (GetVersion() < 0x80000000) #endif -/* types */ - -#define TTYSZ 64 -typedef struct Session Session; -struct Session { - int used; - int self; - struct passwd *pw; - Authctxt *authctxt; - pid_t pid; - /* tty */ - char *term; - int ptyfd, ttyfd, ptymaster; - int row, col, xpixel, ypixel; - char tty[TTYSZ]; - /* X11 */ - int display_number; - char *display; - int screen; - char *auth_display; - char *auth_proto; - char *auth_data; - int single_connection; - /* proto 2 */ - int chanid; - int is_subsystem; -}; - /* func */ Session *session_new(void); void session_set_fds(Session *, int, int, int); -static void session_pty_cleanup(void *); +void session_pty_cleanup(void *); void session_proctitle(Session *); int session_setup_x11fwd(Session *); void do_exec_pty(Session *, const char *); @@ -116,7 +89,6 @@ int check_quietlogin(Session *, const char *); static void do_authenticated1(Authctxt *); static void do_authenticated2(Authctxt *); -static void session_close(Session *); static int session_pty_req(Session *); /* import */ @@ -140,7 +112,7 @@ char *aixloginmsg; #endif /* WITH_AIXAUTHENTICATE */ #ifdef HAVE_LOGIN_CAP -static login_cap_t *lc; +login_cap_t *lc; #endif void @@ -155,18 +127,6 @@ do_authenticated(Authctxt *authctxt) close(startup_pipe); startup_pipe = -1; } -#if defined(HAVE_LOGIN_CAP) && defined(HAVE_PW_CLASS_IN_PASSWD) - if ((lc = login_getclass(authctxt->pw->pw_class)) == NULL) { - error("unable to get login class"); - return; - } -#ifdef BSD_AUTH - if (auth_approval(NULL, lc, authctxt->pw->pw_name, "ssh") <= 0) { - packet_disconnect("Approval failure for %s", - authctxt->pw->pw_name); - } -#endif -#endif #ifdef WITH_AIXAUTHENTICATE /* We don't have a pty yet, so just label the line as "ssh" */ if (loginsuccess(authctxt->user, @@ -675,10 +635,8 @@ void do_login(Session *s, const char *command) { char *time_string; - char hostname[MAXHOSTNAMELEN]; socklen_t fromlen; struct sockaddr_storage from; - time_t last_login_time; struct passwd * pw = s->pw; pid_t pid = getpid(); @@ -696,17 +654,12 @@ do_login(Session *s, const char *command) } } - /* Get the time and hostname when the user last logged in. */ - if (options.print_lastlog) { - hostname[0] = '\0'; - last_login_time = get_last_login_time(pw->pw_uid, pw->pw_name, - hostname, sizeof(hostname)); - } - /* Record that there was a login on that tty from the remote host. */ - record_login(pid, s->tty, pw->pw_name, pw->pw_uid, - get_remote_name_or_ip(utmp_len, options.verify_reverse_mapping), - (struct sockaddr *)&from); + if (!use_privsep) + record_login(pid, s->tty, pw->pw_name, pw->pw_uid, + get_remote_name_or_ip(utmp_len, + options.verify_reverse_mapping), + (struct sockaddr *)&from); #ifdef USE_PAM /* @@ -731,14 +684,15 @@ do_login(Session *s, const char *command) printf("%s\n", aixloginmsg); #endif /* WITH_AIXAUTHENTICATE */ - if (options.print_lastlog && last_login_time != 0) { - time_string = ctime(&last_login_time); + 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(hostname, "") == 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, hostname); + printf("Last login: %s from %s\r\n", time_string, + s->hostname); } do_motd(); @@ -922,6 +876,7 @@ do_setup_env(Session *s, const char *shell) * the childs environment as they see fit */ ssh_gssapi_do_child(&env,&envsize); + copy_environment(environ, &env, &envsize); #endif if (!options.use_login) { @@ -940,7 +895,12 @@ do_setup_env(Session *s, const char *shell) * needed for loading shared libraries. So the path better * remains intact here. */ +# ifdef SUPERUSER_PATH + child_set_env(&env, &envsize, "PATH", + s->pw->pw_uid == 0 ? SUPERUSER_PATH : _PATH_STDPATH); +# else child_set_env(&env, &envsize, "PATH", _PATH_STDPATH); +# endif /* SUPERUSER_PATH */ # endif /* HAVE_CYGWIN */ #endif /* HAVE_LOGIN_CAP */ @@ -1122,7 +1082,7 @@ do_nologin(struct passwd *pw) } /* Set login name, uid, gid, and groups. */ -static void +void do_setusercontext(struct passwd *pw) { #ifdef HAVE_CYGWIN @@ -1177,6 +1137,27 @@ do_setusercontext(struct passwd *pw) fatal("Failed to set uids to %u.", (u_int) pw->pw_uid); } +static void +launch_login(struct passwd *pw, const char *hostname) +{ + /* Launch login(1). */ + + execl("/usr/bin/login", "login", "-h", hostname, +#ifdef xxxLOGIN_NEEDS_TERM + (s->term ? s->term : "unknown"), +#endif /* LOGIN_NEEDS_TERM */ +#ifdef LOGIN_NO_ENDOPT + "-p", "-f", pw->pw_name, (char *)NULL); +#else + "-p", "-f", "--", pw->pw_name, (char *)NULL); +#endif + + /* Login couldn't be executed, die. */ + + perror("login"); + exit(1); +} + /* * Performs common processing for the child, such as setting up the * environment, closing extra file descriptors, setting the user and group @@ -1302,18 +1283,8 @@ do_child(Session *s, const char *command) signal(SIGPIPE, SIG_DFL); if (options.use_login) { - /* Launch login(1). */ - - execl(LOGIN_PROGRAM, "login", "-h", hostname, -#ifdef LOGIN_NEEDS_TERM - (s->term ? s->term : "unknown"), -#endif /* LOGIN_NEEDS_TERM */ - "-p", "-f", "--", pw->pw_name, (char *)NULL); - - /* Login couldn't be executed, die. */ - - perror("login"); - exit(1); + launch_login(pw, hostname); + /* NEVERREACHED */ } /* Get the last component of the shell name. */ @@ -1423,6 +1394,22 @@ session_open(Authctxt *authctxt, int chanid) return 1; } +Session * +session_by_tty(char *tty) +{ + int i; + for (i = 0; i < MAX_SESSIONS; i++) { + Session *s = &sessions[i]; + if (s->used && s->ttyfd != -1 && strcmp(s->tty, tty) == 0) { + debug("session_by_tty: session %d tty %s", i, tty); + return s; + } + } + debug("session_by_tty: unknown tty %.100s", tty); + session_dump(); + return NULL; +} + static Session * session_by_channel(int id) { @@ -1480,6 +1467,12 @@ 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); @@ -1500,7 +1493,7 @@ session_pty_req(Session *s) /* Allocate a pty and open it. */ debug("Allocating pty."); - if (!pty_allocate(&s->ptyfd, &s->ttyfd, s->tty, sizeof(s->tty))) { + if (!PRIVSEP(pty_allocate(&s->ptyfd, &s->ttyfd, s->tty, sizeof(s->tty)))) { if (s->term) xfree(s->term); s->term = NULL; @@ -1521,7 +1514,8 @@ session_pty_req(Session *s) * time in case we call fatal() (e.g., the connection gets closed). */ fatal_add_cleanup(session_pty_cleanup, (void *)s); - pty_setowner(s->pw, s->tty); + if (!use_privsep) + pty_setowner(s->pw, s->tty); /* Set window size from the packet. */ pty_change_window_size(s->ptyfd, s->row, s->col, s->xpixel, s->ypixel); @@ -1684,8 +1678,8 @@ session_set_fds(Session *s, int fdin, int fdout, int fderr) * Function to perform pty cleanup. Also called if we get aborted abnormally * (e.g., due to a dropped connection). */ -static void -session_pty_cleanup(void *session) +void +session_pty_cleanup2(void *session) { Session *s = session; @@ -1703,7 +1697,8 @@ session_pty_cleanup(void *session) record_logout(s->pid, s->tty, s->pw->pw_name); /* Release the pseudo-tty. */ - pty_release(s->tty); + if (getuid() == 0) + pty_release(s->tty); /* * Close the server side of the socket pairs. We must do this after @@ -1711,12 +1706,18 @@ session_pty_cleanup(void *session) * while we're still cleaning up. */ if (close(s->ptymaster) < 0) - error("close(s->ptymaster): %s", strerror(errno)); + error("close(s->ptymaster/%d): %s", s->ptymaster, strerror(errno)); /* unlink pty from session */ s->ttyfd = -1; } +void +session_pty_cleanup(void *session) +{ + PRIVSEP(session_pty_cleanup2(session)); +} + static void session_exit_message(Session *s, int status) { @@ -1762,7 +1763,7 @@ session_exit_message(Session *s, int status) s->chanid = -1; } -static void +void session_close(Session *s) { debug("session_close: session %d pid %d", s->self, s->pid); @@ -1829,13 +1830,17 @@ session_close_by_channel(int id, void *arg) } void -session_destroy_all(void) +session_destroy_all(void (*closefunc)(Session *)) { int i; for (i = 0; i < MAX_SESSIONS; i++) { Session *s = &sessions[i]; - if (s->used) - session_close(s); + if (s->used) { + if (closefunc != NULL) + closefunc(s); + else + session_close(s); + } } } diff --git a/openssh/session.h b/openssh/session.h index b83a57a..befb7c1 100644 --- a/openssh/session.h +++ b/openssh/session.h @@ -1,4 +1,4 @@ -/* $OpenBSD: session.h,v 1.14 2002/02/03 17:53:25 markus Exp $ */ +/* $OpenBSD: session.h,v 1.17 2002/03/29 18:59:32 markus Exp $ */ /* * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. @@ -26,13 +26,49 @@ #ifndef SESSION_H #define SESSION_H +#define TTYSZ 64 +typedef struct Session Session; +struct Session { + int used; + int self; + struct passwd *pw; + Authctxt *authctxt; + pid_t pid; + /* tty */ + char *term; + int ptyfd, ttyfd, ptymaster; + int row, col, xpixel, ypixel; + char tty[TTYSZ]; + /* last login */ + char hostname[MAXHOSTNAMELEN]; + time_t last_login_time; + /* X11 */ + int display_number; + char *display; + int screen; + char *auth_display; + char *auth_proto; + char *auth_data; + int single_connection; + /* proto 2 */ + int chanid; + int is_subsystem; +}; + void do_authenticated(Authctxt *); int session_open(Authctxt*, int); int session_input_channel_req(Channel *, const char *); void session_close_by_pid(pid_t, int); void session_close_by_channel(int, void *); -void session_destroy_all(void); +void session_destroy_all(void (*)(Session *)); +void session_pty_cleanup2(void *); + +Session *session_new(void); +Session *session_by_tty(char *); +void session_close(Session *); +void do_setusercontext(struct passwd *); + void child_set_env(char ***envp, u_int *envsizep, const char *name, const char *value); #endif diff --git a/openssh/ssh-rand-helper.c b/openssh/ssh-rand-helper.c index 28ea659..72a818f 100644 --- a/openssh/ssh-rand-helper.c +++ b/openssh/ssh-rand-helper.c @@ -747,38 +747,88 @@ prng_read_commands(char *cmdfilename) return cur_cmd < MIN_ENTROPY_SOURCES ? -1 : 0; } +void +usage(void) +{ + fprintf(stderr, "Usage: %s [options]\n", __progname); + fprintf(stderr, " -v Verbose; display verbose debugging messages.\n"); + fprintf(stderr, " Multiple -v increases verbosity.\n"); + fprintf(stderr, " -x Force output in hexidecimal (for debugging)\n"); + fprintf(stderr, " -X Force output in binary\n"); + fprintf(stderr, " -b bytes Number of bytes to output (default %d)\n", + OUTPUT_SEED_SIZE); +} + int main(int argc, char **argv) { - unsigned char buf[OUTPUT_SEED_SIZE]; - int ret; + unsigned char *buf; + int ret, ch, debug_level, output_hex, bytes; + extern char *optarg; + LogLevel ll; __progname = get_progname(argv[0]); - /* XXX: need some debugging mode */ log_init(argv[0], SYSLOG_LEVEL_INFO, SYSLOG_FACILITY_USER, 1); + ll = SYSLOG_LEVEL_INFO; + debug_level = output_hex = 0; + bytes = OUTPUT_SEED_SIZE; + + /* Don't write binary data to a tty, unless we are forced to */ + if (isatty(STDOUT_FILENO)) + output_hex = 1; + + while ((ch = getopt(argc, argv, "vxXhb:")) != -1) { + switch (ch) { + case 'v': + if (debug_level < 3) + ll = SYSLOG_LEVEL_DEBUG1 + debug_level++; + break; + case 'x': + output_hex = 1; + break; + case 'X': + output_hex = 0; + break; + case 'b': + if ((bytes = atoi(optarg)) <= 0) + fatal("Invalid number of output bytes"); + break; + case 'h': + usage(); + exit(0); + default: + error("Invalid commandline option"); + usage(); + } + } + + log_init(argv[0], ll, SYSLOG_FACILITY_USER, 1); + #ifdef USE_SEED_FILES prng_read_seedfile(); #endif + buf = xmalloc(bytes); + /* * Seed the RNG from wherever we can */ /* Take whatever is on the stack, but don't credit it */ - RAND_add(buf, sizeof(buf), 0); + RAND_add(buf, bytes, 0); debug("Seeded RNG with %i bytes from system calls", (int)stir_from_system()); #ifdef PRNGD_PORT - if (get_random_bytes_prngd(buf, sizeof(buf), PRNGD_PORT, NULL) == -1) + if (get_random_bytes_prngd(buf, bytes, PRNGD_PORT, NULL) == -1) fatal("Entropy collection failed"); - RAND_add(buf, sizeof(buf), sizeof(buf)); + RAND_add(buf, bytes, bytes); #elif defined(PRNGD_SOCKET) - if (get_random_bytes_prngd(buf, sizeof(buf), 0, PRNGD_SOCKET) == -1) + if (get_random_bytes_prngd(buf, bytes, 0, PRNGD_SOCKET) == -1) fatal("Entropy collection failed"); - RAND_add(buf, sizeof(buf), sizeof(buf)); + RAND_add(buf, bytes, bytes); #else /* Read in collection commands */ if (prng_read_commands(SSH_PRNG_COMMAND_FILE) == -1) @@ -798,12 +848,18 @@ main(int argc, char **argv) if (!RAND_status()) fatal("Not enough entropy in RNG"); - RAND_bytes(buf, sizeof(buf)); + RAND_bytes(buf, bytes); - ret = atomicio(write, STDOUT_FILENO, buf, sizeof(buf)); + if (output_hex) { + for(ret = 0; ret < bytes; ret++) + printf("%02x", (unsigned char)(buf[ret])); + printf("\n"); + } else + ret = atomicio(write, STDOUT_FILENO, buf, bytes); - memset(buf, '\0', sizeof(buf)); + memset(buf, '\0', bytes); + xfree(buf); - return ret == sizeof(buf) ? 0 : 1; + return ret == bytes ? 0 : 1; } diff --git a/openssh/sshconnect1.c b/openssh/sshconnect1.c index 05fa7d5..d2024a2 100644 --- a/openssh/sshconnect1.c +++ b/openssh/sshconnect1.c @@ -13,7 +13,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: sshconnect1.c,v 1.48 2002/02/11 16:15:46 markus Exp $"); +RCSID("$OpenBSD: sshconnect1.c,v 1.50 2002/04/21 16:25:06 stevesk Exp $"); #include #include @@ -462,6 +462,8 @@ try_krb4_authentication(void) /* Get server's response. */ reply = packet_get_string((u_int *) &auth.length); + if (auth.length >= MAX_KTXT_LEN) + fatal("Kerberos v4: Malformed response from server"); memcpy(auth.dat, reply, auth.length); xfree(reply); @@ -889,7 +891,7 @@ try_challenge_response_authentication(void) error("Permission denied, please try again."); if (options.cipher == SSH_CIPHER_NONE) log("WARNING: Encryption is disabled! " - "Reponse will be transmitted in clear text."); + "Response will be transmitted in clear text."); response = read_passphrase(prompt, 0); if (strcmp(response, "") == 0) { xfree(response); diff --git a/openssh/sshconnect2.c b/openssh/sshconnect2.c index d98ec2e..6f3d26b 100644 --- a/openssh/sshconnect2.c +++ b/openssh/sshconnect2.c @@ -23,7 +23,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: sshconnect2.c,v 1.97 2002/02/25 16:33:27 markus Exp $"); +RCSID("$OpenBSD: sshconnect2.c,v 1.99 2002/03/26 15:58:46 markus Exp $"); #include "ssh.h" #include "ssh2.h" @@ -210,6 +210,7 @@ void input_userauth_banner(int, u_int32_t, void *); void input_userauth_error(int, u_int32_t, void *); void input_userauth_info_req(int, u_int32_t, void *); void input_userauth_pk_ok(int, u_int32_t, void *); +void input_userauth_passwd_changereq(int, u_int32_t, void *); int userauth_none(Authctxt *); int userauth_pubkey(Authctxt *); @@ -455,7 +456,7 @@ input_userauth_pk_ok(int type, u_int32_t seq, void *ctxt) debug("no key from blob. pkalg %s", pkalg); break; } - if (key->type != pktype) { + if (key->type != pktype) { error("input_userauth_pk_ok: type mismatch " "for decoded key (received %d, expected %d)", key->type, pktype); @@ -651,7 +652,7 @@ int userauth_passwd(Authctxt *authctxt) { static int attempt = 0; - char prompt[80]; + char prompt[150]; char *password; if (attempt++ >= options.number_of_password_prompts) @@ -673,13 +674,85 @@ userauth_passwd(Authctxt *authctxt) xfree(password); packet_add_padding(64); packet_send(); + + dispatch_set(SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ, + &input_userauth_passwd_changereq); + return 1; } +/* + * parse PASSWD_CHANGEREQ, prompt user and send SSH2_MSG_USERAUTH_REQUEST + */ +void +input_userauth_passwd_changereq(int type, u_int32_t seqnr, void *ctxt) +{ + Authctxt *authctxt = ctxt; + char *info, *lang, *password = NULL, *retype = NULL; + char prompt[150]; + + debug2("input_userauth_passwd_changereq"); + + if (authctxt == NULL) + fatal("input_userauth_passwd_changereq: " + "no authentication context"); + + info = packet_get_string(NULL); + lang = packet_get_string(NULL); + if (strlen(info) > 0) + log("%s", info); + xfree(info); + xfree(lang); + packet_start(SSH2_MSG_USERAUTH_REQUEST); + packet_put_cstring(authctxt->server_user); + packet_put_cstring(authctxt->service); + packet_put_cstring(authctxt->method->name); + packet_put_char(1); /* additional info */ + snprintf(prompt, sizeof(prompt), + "Enter %.30s@%.128s's old password: ", + authctxt->server_user, authctxt->host); + password = read_passphrase(prompt, 0); + packet_put_cstring(password); + memset(password, 0, strlen(password)); + xfree(password); + password = NULL; + while (password == NULL) { + snprintf(prompt, sizeof(prompt), + "Enter %.30s@%.128s's new password: ", + authctxt->server_user, authctxt->host); + password = read_passphrase(prompt, RP_ALLOW_EOF); + if (password == NULL) { + /* bail out */ + return; + } + snprintf(prompt, sizeof(prompt), + "Retype %.30s@%.128s's new password: ", + authctxt->server_user, authctxt->host); + retype = read_passphrase(prompt, 0); + if (strcmp(password, retype) != 0) { + memset(password, 0, strlen(password)); + xfree(password); + log("Mismatch; try again, EOF to quit."); + password = NULL; + } + memset(retype, 0, strlen(retype)); + xfree(retype); + } + packet_put_cstring(password); + memset(password, 0, strlen(password)); + xfree(password); + packet_add_padding(64); + packet_send(); + + dispatch_set(SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ, + &input_userauth_passwd_changereq); +} static void clear_auth_state(Authctxt *authctxt) { /* XXX clear authentication state */ + dispatch_set(SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ, NULL); + if (authctxt->last_key != NULL && authctxt->last_key_hint == -1) { debug3("clear_auth_state: key_free %p", authctxt->last_key); key_free(authctxt->last_key); diff --git a/openssh/sshd.8 b/openssh/sshd.8 index b17a07b..25398eb 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.170 2002/02/28 20:46:10 stevesk Exp $ +.\" $OpenBSD: sshd.8,v 1.181 2002/05/15 21:02:53 markus Exp $ .Dd September 25, 1999 .Dt SSHD 8 .Os @@ -116,14 +116,14 @@ Rhosts authentication is normally disabled because it is fundamentally insecure, but can be enabled in the server configuration file if desired. System security is not improved unless -.Xr rshd 8 , -.Xr rlogind 8 , +.Nm rshd , +.Nm rlogind , and -.Xr rexecd 8 +.Xr rexecd are disabled (thus completely disabling -.Xr rlogin 1 +.Xr rlogin and -.Xr rsh 1 +.Xr rsh into the machine). .Pp .Ss SSH protocol version 2 @@ -332,7 +332,7 @@ keywords are case-insensitive and arguments are case-sensitive): .It Cm AFSTokenPassing Specifies whether an AFS token may be forwarded to the server. Default is -.Dq yes . +.Dq no . .It Cm AllowGroups This keyword can be followed by a list of group name patterns, separated by spaces. @@ -390,6 +390,7 @@ may be relevant for getting legal protection. 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. @@ -589,7 +590,7 @@ the Kerberos KDC. To use this option, the server needs a Kerberos servtab which allows the verification of the KDC's identity. Default is -.Dq yes . +.Dq no . .It Cm KerberosOrLocalPasswd If set then if password authentication through Kerberos fails then the password will be validated via any additional local mechanism @@ -858,7 +859,19 @@ will be disabled because .Xr login 1 does not know how to handle .Xr xauth 1 -cookies. +cookies. If +.Cm UsePrivilegeSeparation +is specified, it will be disabled after authentication. +.It Cm UsePrivilegeSeparation +Specifies whether +.Nm +separated privileges by creating an unprivileged child process +to deal with incoming network traffic. After successful authentication, +another process will be created that has the privilege of the authenticated +user. The goal of privilege separation is to prevent privilege +escalation by containing any corruption within the unprivileged processes. +The default is +.Dq no . .It Cm VerifyReverseMapping Specifies whether .Nm @@ -1042,6 +1055,10 @@ or the .Pa id_rsa.pub file and edit it. .Pp +.Nm +enforces a minimum RSA key modulus size for protocol 1 +and protocol 2 keys of 768 bits. +.Pp The options (if present) consist of comma-separated option specifications. No spaces are permitted, except within double quotes. @@ -1326,13 +1343,17 @@ only by the user; it need not be readable by anyone else. .It Pa $HOME/.ssh/rc If this file exists, it is run with /bin/sh after reading the environment files but before starting the user's shell or command. -If X11 spoofing is in use, this will receive the "proto cookie" pair in -standard input (and +It must not produce any output on stdout; stderr must be used +instead. +If X11 forwarding is in use, it will receive the "proto cookie" pair in +its standard input (and .Ev DISPLAY -in environment). -This must call +in its environment). +The script must call .Xr xauth 1 -in that case. +because +.Nm +will not run xauth automatically to add X11 cookies. .Pp The primary purpose of this file is to run any initialization routines which may be needed before the user's home directory becomes @@ -1341,15 +1362,22 @@ accessible; AFS is a particular example of such an environment. This file will probably contain some initialization code followed by something similar to: .Bd -literal - if read proto cookie; then - echo add $DISPLAY $proto $cookie | xauth -q - +if read proto cookie && [ -n "$DISPLAY" ]; then + if [ `echo $DISPLAY | cut -c1-10` = 'localhost:' ]; then + # X11UseLocalhost=yes + xauth add unix:`echo $DISPLAY | + cut -c11-` $proto $cookie + else + # X11UseLocalhost=no + xauth add $DISPLAY $proto $cookie fi +fi .Ed .Pp If this file does not exist, .Pa /etc/ssh/sshrc is run, and if that -does not exist either, xauth is used to store the cookie. +does not exist either, xauth is used to add the cookie. .Pp This file should be writable only by the user, and need not be readable by anyone else. @@ -1369,6 +1397,8 @@ removed many bugs, re-added newer features and created OpenSSH. Markus Friedl contributed the support for SSH protocol versions 1.5 and 2.0. +Niels Provos and Markus Friedl contributed support +for privilege separation. .Sh SEE ALSO .Xr scp 1 , .Xr sftp 1 , @@ -1386,8 +1416,8 @@ protocol versions 1.5 and 2.0. .%A T. Rinne .%A S. Lehtinen .%T "SSH Protocol Architecture" -.%N draft-ietf-secsh-architecture-09.txt -.%D July 2001 +.%N draft-ietf-secsh-architecture-12.txt +.%D January 2002 .%O work in progress material .Re .Rs @@ -1395,7 +1425,7 @@ protocol versions 1.5 and 2.0. .%A N. Provos .%A W. A. Simpson .%T "Diffie-Hellman Group Exchange for the SSH Transport Layer Protocol" -.%N draft-ietf-secsh-dh-group-exchange-01.txt -.%D April 2001 +.%N draft-ietf-secsh-dh-group-exchange-02.txt +.%D January 2002 .%O work in progress material .Re diff --git a/openssh/sshd.c b/openssh/sshd.c index 9582122..fe2e63d 100644 --- a/openssh/sshd.c +++ b/openssh/sshd.c @@ -15,8 +15,10 @@ * called by a name other than "ssh" or "Secure Shell". * * SSH2 implementation: + * Privilege Separation: * - * Copyright (c) 2000 Markus Friedl. All rights reserved. + * Copyright (c) 2000, 2001, 2002 Markus Friedl. All rights reserved. + * Copyright (c) 2002 Niels Provos. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -40,11 +42,16 @@ */ #include "includes.h" -RCSID("$OpenBSD: sshd.c,v 1.228 2002/02/27 21:23:13 stevesk Exp $"); +RCSID("$OpenBSD: sshd.c,v 1.242 2002/05/15 15:47:49 mouring Exp $"); #include #include #include +#include +#ifdef HAVE_SECUREWARE +#include +#include +#endif #include "ssh.h" #include "ssh1.h" @@ -72,6 +79,11 @@ RCSID("$OpenBSD: sshd.c,v 1.228 2002/02/27 21:23:13 stevesk Exp $"); #include "misc.h" #include "dispatch.h" #include "channels.h" +#include "session.h" +#include "monitor_mm.h" +#include "monitor.h" +#include "monitor_wrap.h" +#include "monitor_fdpass.h" #ifdef GSSAPI #include "ssh-gss.h" @@ -193,8 +205,13 @@ u_int utmp_len = MAXHOSTNAMELEN; int *startup_pipes = NULL; int startup_pipe; /* in child */ +/* variables used for privilege separation */ +extern struct monitor *pmonitor; +extern int use_privsep; + /* Prototypes for various functions defined later in this file. */ void destroy_sensitive_data(void); +void demote_sensitive_data(void); static void do_ssh1_kex(void); static void do_ssh2_kex(void); @@ -267,10 +284,12 @@ sigterm_handler(int sig) static void main_sigchld_handler(int sig) { + pid_t pid; int save_errno = errno; int status; - while (waitpid(-1, &status, WNOHANG) > 0) + while ((pid = waitpid(-1, &status, WNOHANG)) > 0 || + (pid < 0 && errno == EINTR)) ; signal(SIGCHLD, main_sigchld_handler); @@ -481,6 +500,160 @@ destroy_sensitive_data(void) memset(sensitive_data.ssh1_cookie, 0, SSH_SESSION_KEY_LENGTH); } +/* Demote private to public keys for network child */ +void +demote_sensitive_data(void) +{ + Key *tmp; + int i; + + if (sensitive_data.server_key) { + tmp = key_demote(sensitive_data.server_key); + key_free(sensitive_data.server_key); + sensitive_data.server_key = tmp; + } + + for (i = 0; i < options.num_host_key_files; i++) { + if (sensitive_data.host_keys[i]) { + tmp = key_demote(sensitive_data.host_keys[i]); + key_free(sensitive_data.host_keys[i]); + sensitive_data.host_keys[i] = tmp; + if (tmp->type == KEY_RSA1) + sensitive_data.ssh1_host_key = tmp; + } + } + + /* We do not clear ssh1_host key and cookie. XXX - Okay Niels? */ +} + +static void +privsep_preauth_child(void) +{ + u_int32_t rand[256]; + int i; + struct passwd *pw; + + /* Enable challenge-response authentication for privilege separation */ + privsep_challenge_enable(); + + for (i = 0; i < 256; i++) + rand[i] = arc4random(); + RAND_seed(rand, sizeof(rand)); + + /* Demote the private keys to public keys. */ + demote_sensitive_data(); + + if ((pw = getpwnam(SSH_PRIVSEP_USER)) == NULL) + fatal("Privilege separation user %s does not exist", + SSH_PRIVSEP_USER); + memset(pw->pw_passwd, 0, strlen(pw->pw_passwd)); + endpwent(); + + /* Change our root directory*/ + if (chroot(_PATH_PRIVSEP_CHROOT_DIR) == -1) + fatal("chroot(\"%s\"): %s", _PATH_PRIVSEP_CHROOT_DIR, + strerror(errno)); + if (chdir("/") == -1) + fatal("chdir(\"/\"): %s", strerror(errno)); + + /* Drop our privileges */ + debug3("privsep user:group %u:%u", (u_int)pw->pw_uid, + (u_int)pw->pw_gid); + do_setusercontext(pw); +} + +static Authctxt* +privsep_preauth(void) +{ + Authctxt *authctxt = NULL; + int status; + pid_t pid; + + /* Set up unprivileged child process to deal with network data */ + pmonitor = monitor_init(); + /* Store a pointer to the kex for later rekeying */ + pmonitor->m_pkex = &xxx_kex; + + pid = fork(); + if (pid == -1) { + fatal("fork of unprivileged child failed"); + } else if (pid != 0) { + debug2("Network child is on pid %d", pid); + + close(pmonitor->m_recvfd); + authctxt = monitor_child_preauth(pmonitor); + close(pmonitor->m_sendfd); + + /* Sync memory */ + monitor_sync(pmonitor); + + /* Wait for the child's exit status */ + while (waitpid(pid, &status, 0) < 0) + if (errno != EINTR) + break; + return (authctxt); + } else { + /* child */ + + close(pmonitor->m_sendfd); + + /* Demote the child */ + if (getuid() == 0 || geteuid() == 0) + privsep_preauth_child(); + setproctitle("%s", "[net]"); + } + return (NULL); +} + +static void +privsep_postauth(Authctxt *authctxt) +{ + extern Authctxt *x_authctxt; + + /* XXX - Remote port forwarding */ + x_authctxt = authctxt; + + if (authctxt->pw->pw_uid == 0 || options.use_login) { + /* File descriptor passing is broken or root login */ + monitor_apply_keystate(pmonitor); + use_privsep = 0; + return; + } + + /* Authentication complete */ + alarm(0); + if (startup_pipe != -1) { + close(startup_pipe); + startup_pipe = -1; + } + + /* New socket pair */ + monitor_reinit(pmonitor); + + pmonitor->m_pid = fork(); + if (pmonitor->m_pid == -1) + fatal("fork of unprivileged child failed"); + else if (pmonitor->m_pid != 0) { + debug2("User child is on pid %d", pmonitor->m_pid); + close(pmonitor->m_recvfd); + monitor_child_postauth(pmonitor); + + /* NEVERREACHED */ + exit(0); + } + + close(pmonitor->m_sendfd); + + /* Demote the private keys to public keys. */ + demote_sensitive_data(); + + /* Drop privileges */ + do_setusercontext(authctxt->pw); + + /* It is safe now to apply the key state */ + monitor_apply_keystate(pmonitor); +} + static char * list_hostkey_types(void) { @@ -510,7 +683,7 @@ list_hostkey_types(void) return p; } -static Key * +Key * get_hostkey_by_type(int type) { int i; @@ -522,6 +695,25 @@ get_hostkey_by_type(int type) return NULL; } +Key * +get_hostkey_by_index(int ind) +{ + if (ind < 0 || ind >= options.num_host_key_files) + return (NULL); + return (sensitive_data.host_keys[ind]); +} + +int +get_hostkey_index(Key *key) +{ + int i; + for (i = 0; i < options.num_host_key_files; i++) { + if (key == sensitive_data.host_keys[i]) + return (i); + } + return (-1); +} + /* * returns 1 if connection should be dropped, 0 otherwise. * dropping starts at connection #max_startups_begin with a probability @@ -598,9 +790,13 @@ main(int ac, char **av) int listen_sock, maxfd; int startup_p[2]; int startups = 0; + Authctxt *authctxt; Key *key; int ret, key_used = 0; +#ifdef HAVE_SECUREWARE + (void)set_auth_parameters(ac, av); +#endif __progname = get_progname(av[0]); init_rng(); @@ -816,9 +1012,15 @@ main(int ac, char **av) if (test_flag) exit(0); -#ifdef HAVE_SCO_PROTECTED_PW - (void) set_auth_parameters(ac, av); -#endif + /* + * Clear out any supplemental groups we may have inherited. This + * prevents inadvertent creation of files with bad modes (in the + * portable version at least, it's certainly possible for PAM + * to create a file, and we can't control the code in every + * module which might be used). + */ + if (setgroups(0, NULL) < 0) + debug("setgroups() failed: %.200s", strerror(errno)); /* Initialize the log (it is reinitialized below in case we forked). */ if (debug_flag && !inetd_flag) @@ -1136,6 +1338,14 @@ main(int ac, char **av) /* This is the child processing a new connection. */ + /* + * Create a new session and process group since the 4.4BSD + * setlogin() affects the entire process group. We don't + * want the child to be able to affect the parent. + */ + if (setsid() < 0) + error("setsid: %.100s", strerror(errno)); + /* * 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 @@ -1238,15 +1448,43 @@ main(int ac, char **av) packet_set_nonblocking(); + if (use_privsep) + if ((authctxt = privsep_preauth()) != NULL) + goto authenticated; + /* perform the key exchange */ /* authenticate user and start session */ if (compat20) { do_ssh2_kex(); - do_authentication2(); + authctxt = do_authentication2(); } else { do_ssh1_kex(); - do_authentication(); + authctxt = do_authentication(); + } + /* + * If we use privilege separation, the unprivileged child transfers + * the current keystate and exits + */ + if (use_privsep) { + mm_send_keystate(pmonitor); + exit(0); + } + + authenticated: + /* + * In privilege separation, we fork another child and prepare + * file descriptor passing. + */ + if (use_privsep) { + privsep_postauth(authctxt); + /* the monitor process [priv] will not return */ + if (!compat20) + destroy_sensitive_data(); } + + /* Perform session preparation. */ + do_authenticated(authctxt); + /* The connection has been terminated. */ verbose("Closing connection to %.100s", remote_ip); @@ -1255,9 +1493,57 @@ main(int ac, char **av) #endif /* USE_PAM */ packet_close(); + + if (use_privsep) + mm_terminate(); + exit(0); } +/* + * Decrypt session_key_int using our private server key and private host key + * (key with larger modulus first). + */ +int +ssh1_session_key(BIGNUM *session_key_int) +{ + int rsafail = 0; + + if (BN_cmp(sensitive_data.server_key->rsa->n, sensitive_data.ssh1_host_key->rsa->n) > 0) { + /* Server key has bigger modulus. */ + if (BN_num_bits(sensitive_data.server_key->rsa->n) < + BN_num_bits(sensitive_data.ssh1_host_key->rsa->n) + SSH_KEY_BITS_RESERVED) { + fatal("do_connection: %s: server_key %d < host_key %d + SSH_KEY_BITS_RESERVED %d", + get_remote_ipaddr(), + BN_num_bits(sensitive_data.server_key->rsa->n), + BN_num_bits(sensitive_data.ssh1_host_key->rsa->n), + SSH_KEY_BITS_RESERVED); + } + if (rsa_private_decrypt(session_key_int, session_key_int, + sensitive_data.server_key->rsa) <= 0) + rsafail++; + if (rsa_private_decrypt(session_key_int, session_key_int, + sensitive_data.ssh1_host_key->rsa) <= 0) + rsafail++; + } else { + /* Host key has bigger modulus (or they are equal). */ + if (BN_num_bits(sensitive_data.ssh1_host_key->rsa->n) < + BN_num_bits(sensitive_data.server_key->rsa->n) + SSH_KEY_BITS_RESERVED) { + fatal("do_connection: %s: host_key %d < server_key %d + SSH_KEY_BITS_RESERVED %d", + get_remote_ipaddr(), + BN_num_bits(sensitive_data.ssh1_host_key->rsa->n), + BN_num_bits(sensitive_data.server_key->rsa->n), + SSH_KEY_BITS_RESERVED); + } + if (rsa_private_decrypt(session_key_int, session_key_int, + sensitive_data.ssh1_host_key->rsa) < 0) + rsafail++; + if (rsa_private_decrypt(session_key_int, session_key_int, + sensitive_data.server_key->rsa) < 0) + rsafail++; + } + return (rsafail); +} /* * SSH1 key exchange */ @@ -1373,43 +1659,9 @@ do_ssh1_kex(void) packet_set_protocol_flags(protocol_flags); packet_check_eom(); - /* - * Decrypt it using our private server key and private host key (key - * with larger modulus first). - */ - if (BN_cmp(sensitive_data.server_key->rsa->n, sensitive_data.ssh1_host_key->rsa->n) > 0) { - /* Server key has bigger modulus. */ - if (BN_num_bits(sensitive_data.server_key->rsa->n) < - BN_num_bits(sensitive_data.ssh1_host_key->rsa->n) + SSH_KEY_BITS_RESERVED) { - fatal("do_connection: %s: server_key %d < host_key %d + SSH_KEY_BITS_RESERVED %d", - get_remote_ipaddr(), - BN_num_bits(sensitive_data.server_key->rsa->n), - BN_num_bits(sensitive_data.ssh1_host_key->rsa->n), - SSH_KEY_BITS_RESERVED); - } - if (rsa_private_decrypt(session_key_int, session_key_int, - sensitive_data.server_key->rsa) <= 0) - rsafail++; - if (rsa_private_decrypt(session_key_int, session_key_int, - sensitive_data.ssh1_host_key->rsa) <= 0) - rsafail++; - } else { - /* Host key has bigger modulus (or they are equal). */ - if (BN_num_bits(sensitive_data.ssh1_host_key->rsa->n) < - BN_num_bits(sensitive_data.server_key->rsa->n) + SSH_KEY_BITS_RESERVED) { - fatal("do_connection: %s: host_key %d < server_key %d + SSH_KEY_BITS_RESERVED %d", - get_remote_ipaddr(), - BN_num_bits(sensitive_data.ssh1_host_key->rsa->n), - BN_num_bits(sensitive_data.server_key->rsa->n), - SSH_KEY_BITS_RESERVED); - } - if (rsa_private_decrypt(session_key_int, session_key_int, - sensitive_data.ssh1_host_key->rsa) < 0) - rsafail++; - if (rsa_private_decrypt(session_key_int, session_key_int, - sensitive_data.server_key->rsa) < 0) - rsafail++; - } + /* Decrypt session_key_int using host/server keys */ + rsafail = PRIVSEP(ssh1_session_key(session_key_int)); + /* * Extract session key from the decrypted integer. The key is in the * least significant 256 bits of the integer; the first byte of the @@ -1460,9 +1712,12 @@ do_ssh1_kex(void) for (i = 0; i < 16; i++) session_id[i] = session_key[i] ^ session_key[i + 16]; } - /* Destroy the private and public keys. They will no longer be needed. */ + /* Destroy the private and public keys. No longer. */ destroy_sensitive_data(); + if (use_privsep) + mm_ssh1_session_id(session_id); + /* Destroy the decrypted integer. It is no longer needed. */ BN_clear_free(session_key_int); @@ -1548,6 +1803,7 @@ do_ssh2_kex(void) kex->client_version_string=client_version_string; kex->server_version_string=server_version_string; kex->load_host_key=&get_hostkey_by_type; + kex->host_key_index=&get_hostkey_index; xxx_kex = kex; -- 2.45.2