diff --git a/crypto/openssh/acconfig.h b/crypto/openssh/acconfig.h index 713b094d6a0f..dc47bf52e964 100644 --- a/crypto/openssh/acconfig.h +++ b/crypto/openssh/acconfig.h @@ -1,365 +1,369 @@ /* $Id: acconfig.h,v 1.138 2002/06/12 16:57:15 mouring Exp $ */ +/* $FreeBSD$ */ #ifndef _CONFIG_H #define _CONFIG_H /* Generated automatically from acconfig.h by autoheader. */ /* Please make your changes there */ @TOP@ /* Define to a Set Process Title type if your system is */ /* supported by bsd-setproctitle.c */ #undef SPT_TYPE /* setgroups() NOOP allowed */ #undef SETGROUPS_NOOP /* SCO workaround */ #undef BROKEN_SYS_TERMIO_H /* 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 */ #undef LOGIN_PROGRAM_FALLBACK /* Define if your password has a pw_class field */ #undef HAVE_PW_CLASS_IN_PASSWD /* Define if your password has a pw_expire field */ #undef HAVE_PW_EXPIRE_IN_PASSWD /* 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 /* Define if your system defines sys_errlist[] */ #undef HAVE_SYS_ERRLIST /* Define if your system defines sys_nerr */ #undef HAVE_SYS_NERR /* Define if your system choked on IP TOS setting */ #undef IP_TOS_IS_BROKEN /* Define if you have the getuserattr function. */ #undef HAVE_GETUSERATTR /* Work around problematic Linux PAM modules handling of PAM_TTY */ #undef PAM_TTY_KLUDGE /* Use PIPES instead of a socketpair() */ #undef USE_PIPES /* Define if your snprintf is busted */ #undef BROKEN_SNPRINTF /* Define if you are on Cygwin */ #undef HAVE_CYGWIN /* Define if you have a broken realpath. */ #undef BROKEN_REALPATH /* Define if you are on NeXT */ #undef HAVE_NEXT /* Define if you are on NEWS-OS */ #undef HAVE_NEWS4 /* Define if you want to enable PAM support */ #undef USE_PAM /* Define if you want to enable AIX4's authenticate function */ #undef WITH_AIXAUTHENTICATE /* Define if you have/want arrays (cluster-wide session managment, not C arrays) */ #undef WITH_IRIX_ARRAY /* Define if you want IRIX project management */ #undef WITH_IRIX_PROJECT /* Define if you want IRIX audit trails */ #undef WITH_IRIX_AUDIT /* Define if you want IRIX kernel jobs */ #undef WITH_IRIX_JOBS /* Location of PRNGD/EGD random number socket */ #undef PRNGD_SOCKET /* Port number of PRNGD/EGD random number socket */ #undef PRNGD_PORT /* 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 /* Define if your ssl headers are included with #include */ #undef HAVE_OPENSSL /* Define if you are linking against RSAref. Used only to print the right * message at run-time. */ #undef RSAREF /* struct timeval */ #undef HAVE_STRUCT_TIMEVAL /* struct utmp and struct utmpx fields */ #undef HAVE_HOST_IN_UTMP #undef HAVE_HOST_IN_UTMPX #undef HAVE_ADDR_IN_UTMP #undef HAVE_ADDR_IN_UTMPX #undef HAVE_ADDR_V6_IN_UTMP #undef HAVE_ADDR_V6_IN_UTMPX #undef HAVE_SYSLEN_IN_UTMPX #undef HAVE_PID_IN_UTMP #undef HAVE_TYPE_IN_UTMP #undef HAVE_TYPE_IN_UTMPX #undef HAVE_TV_IN_UTMP #undef HAVE_TV_IN_UTMPX #undef HAVE_ID_IN_UTMP #undef HAVE_ID_IN_UTMPX #undef HAVE_EXIT_IN_UTMP #undef HAVE_TIME_IN_UTMP #undef HAVE_TIME_IN_UTMPX /* Define if you don't want to use your system's login() call */ #undef DISABLE_LOGIN /* Define if you don't want to use pututline() etc. to write [uw]tmp */ #undef DISABLE_PUTUTLINE /* Define if you don't want to use pututxline() etc. to write [uw]tmpx */ #undef DISABLE_PUTUTXLINE /* Define if you don't want to use lastlog */ #undef DISABLE_LASTLOG /* Define if you don't want to use utmp */ #undef DISABLE_UTMP /* Define if you don't want to use utmpx */ #undef DISABLE_UTMPX /* Define if you don't want to use wtmp */ #undef DISABLE_WTMP /* Define if you don't want to use wtmpx */ #undef DISABLE_WTMPX /* Some systems need a utmpx entry for /bin/login to work */ #undef LOGIN_NEEDS_UTMPX /* 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 /* Define if you want to specify the path to your utmp file */ #undef CONF_UTMP_FILE /* Define if you want to specify the path to your wtmp file */ #undef CONF_WTMP_FILE /* Define if you want to specify the path to your utmpx file */ #undef CONF_UTMPX_FILE /* Define if you want to specify the path to your wtmpx file */ #undef CONF_WTMPX_FILE /* Define if you want external askpass support */ #undef USE_EXTERNAL_ASKPASS /* 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 if you want Kerberos 5 support */ #undef KRB5 /* Define this if you are using the Heimdal version of Kerberos V5 */ #undef HEIMDAL /* Define if you want Kerberos 4 support */ #undef KRB4 /* Define if you want AFS support */ #undef AFS /* Define if you want S/Key support */ #undef SKEY +/* Define if you want OPIE support */ +#undef OPIE + /* Define if you want TCP Wrappers support */ #undef LIBWRAP /* Define if your libraries define login() */ #undef HAVE_LOGIN /* Define if your libraries define daemon() */ #undef HAVE_DAEMON /* Define if your libraries define getpagesize() */ #undef HAVE_GETPAGESIZE /* Define if xauth is found in your path */ #undef XAUTH_PATH /* Define if rsh is found in your path */ #undef RSH_PATH /* Define if you want to allow MD5 passwords */ #undef HAVE_MD5_PASSWORDS /* Define if you want to disable shadow passwords */ #undef DISABLE_SHADOW /* Define if you want to use shadow password expire field */ #undef HAS_SHADOW_EXPIRE /* Define if you have Digital Unix Security Integration Architecture */ #undef HAVE_OSF_SIA /* Define if you have getpwanam(3) [SunOS 4.x] */ #undef HAVE_GETPWANAM /* Define if you have an old version of PAM which takes only one argument */ /* to pam_strerror */ #undef HAVE_OLD_PAM /* Define if you are using Solaris-derived PAM which passes pam_messages */ /* to the conversation function with an extra level of indirection */ #undef PAM_SUN_CODEBASE /* Set this to your mail directory if you don't have maillock.h */ #undef MAIL_DIRECTORY /* Data types */ #undef HAVE_U_INT #undef HAVE_INTXX_T #undef HAVE_U_INTXX_T #undef HAVE_UINTXX_T #undef HAVE_INT64_T #undef HAVE_U_INT64_T #undef HAVE_U_CHAR #undef HAVE_SIZE_T #undef HAVE_SSIZE_T #undef HAVE_CLOCK_T #undef HAVE_MODE_T #undef HAVE_PID_T #undef HAVE_SA_FAMILY_T #undef HAVE_STRUCT_SOCKADDR_STORAGE #undef HAVE_STRUCT_ADDRINFO #undef HAVE_STRUCT_IN6_ADDR #undef HAVE_STRUCT_SOCKADDR_IN6 /* Fields in struct sockaddr_storage */ #undef HAVE_SS_FAMILY_IN_SS #undef HAVE___SS_FAMILY_IN_SS /* Define if you have /dev/ptmx */ #undef HAVE_DEV_PTMX /* Define if you have /dev/ptc */ #undef HAVE_DEV_PTS_AND_PTC /* Define if you need to use IP address instead of hostname in $DISPLAY */ #undef IPADDR_IN_DISPLAY /* Specify default $PATH */ #undef USER_PATH /* Specify location of ssh.pid */ #undef _PATH_SSH_PIDDIR /* Use IPv4 for connection by default, IPv6 can still if explicity asked */ #undef IPV4_DEFAULT /* getaddrinfo is broken (if present) */ #undef BROKEN_GETADDRINFO /* Workaround more Linux IPv6 quirks */ #undef DONT_TRY_OTHER_AF /* Detect IPv4 in IPv6 mapped addresses and treat as IPv4 */ #undef IPV4_IN_IPV6 /* Define if you have BSD auth support */ #undef BSD_AUTH /* Define if X11 doesn't support AF_UNIX sockets on that system */ #undef NO_X11_UNIX_SOCKETS /* Needed for SCO and NeXT */ #undef BROKEN_SAVED_UIDS /* Define if your system glob() function has the GLOB_ALTDIRFUNC extension */ #undef GLOB_HAS_ALTDIRFUNC /* Define if your system glob() function has gl_matchc options in glob_t */ #undef GLOB_HAS_GL_MATCHC /* Define in your struct dirent expects you to allocate extra space for d_name */ #undef BROKEN_ONE_BYTE_DIRENT_D_NAME /* Define if your getopt(3) defines and uses optreset */ #undef HAVE_GETOPT_OPTRESET /* Define on *nto-qnx systems */ #undef MISSING_NFDBITS /* Define on *nto-qnx systems */ #undef MISSING_HOWMANY /* Define on *nto-qnx systems */ #undef MISSING_FD_MASK /* 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 ************** */ #endif /* _CONFIG_H */ diff --git a/crypto/openssh/auth-skey.c b/crypto/openssh/auth-skey.c index eb13c5cc5203..886b2d2009f8 100644 --- a/crypto/openssh/auth-skey.c +++ b/crypto/openssh/auth-skey.c @@ -1,103 +1,112 @@ /* * Copyright (c) 2001 Markus Friedl. 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-skey.c,v 1.19 2002/06/19 00:27:55 deraadt Exp $"); +RCSID("$FreeBSD$"); #ifdef SKEY +#ifdef OPIE +#include +#define skey opie +#define skeychallenge(k, u, c) opiechallenge((k), (u), (c)) +#define skey_haskey(u) opie_haskey((u)) +#define skey_passcheck(u, r) opie_passverify((u), (r)) +#else #include +#endif #include "xmalloc.h" #include "auth.h" #include "monitor_wrap.h" static void * skey_init_ctx(Authctxt *authctxt) { return authctxt; } int skey_query(void *ctx, char **name, char **infotxt, u_int* numprompts, char ***prompts, u_int **echo_on) { Authctxt *authctxt = ctx; char challenge[1024], *p; int len; struct skey skey; if (skeychallenge(&skey, authctxt->user, challenge) == -1) return -1; *name = xstrdup(""); *infotxt = xstrdup(""); *numprompts = 1; *prompts = xmalloc(*numprompts * sizeof(char*)); *echo_on = xmalloc(*numprompts * sizeof(u_int)); (*echo_on)[0] = 0; len = strlen(challenge) + strlen(SKEY_PROMPT) + 1; p = xmalloc(len); strlcpy(p, challenge, len); strlcat(p, SKEY_PROMPT, len); (*prompts)[0] = p; return 0; } int skey_respond(void *ctx, u_int numresponses, char **responses) { Authctxt *authctxt = ctx; if (authctxt->valid && numresponses == 1 && skey_haskey(authctxt->pw->pw_name) == 0 && skey_passcheck(authctxt->pw->pw_name, responses[0]) != -1) return 0; return -1; } static void skey_free_ctx(void *ctx) { /* we don't have a special context */ } KbdintDevice skey_device = { "skey", skey_init_ctx, skey_query, skey_respond, skey_free_ctx }; KbdintDevice mm_skey_device = { "skey", skey_init_ctx, mm_skey_query, mm_skey_respond, skey_free_ctx }; #endif /* SKEY */ diff --git a/crypto/openssh/auth.h b/crypto/openssh/auth.h index d98547d02ab1..730b70d07fdb 100644 --- a/crypto/openssh/auth.h +++ b/crypto/openssh/auth.h @@ -1,192 +1,200 @@ /* $OpenBSD: auth.h,v 1.39 2002/05/31 11:35:15 markus Exp $ */ +/* $FreeBSD$ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef AUTH_H #define AUTH_H #include "key.h" #include "hostfile.h" #include #ifdef HAVE_LOGIN_CAP #include #endif #ifdef BSD_AUTH #include #endif #ifdef KRB5 #include #endif typedef struct Authctxt Authctxt; typedef struct Authmethod Authmethod; typedef struct KbdintDevice KbdintDevice; struct Authctxt { int success; int postponed; int valid; int attempt; int failures; char *user; char *service; struct passwd *pw; char *style; void *kbdintctxt; #ifdef BSD_AUTH auth_session_t *as; #endif #ifdef KRB4 char *krb4_ticket_file; #endif #ifdef KRB5 krb5_context krb5_ctx; krb5_auth_context krb5_auth_ctx; krb5_ccache krb5_fwd_ccache; krb5_principal krb5_user; char *krb5_ticket_file; #endif }; struct Authmethod { char *name; int (*userauth)(Authctxt *authctxt); int *enabled; }; /* * Keyboard interactive device: * init_ctx returns: non NULL upon success * query returns: 0 - success, otherwise failure * respond returns: 0 - success, 1 - need further interaction, * otherwise - failure */ struct KbdintDevice { const char *name; void* (*init_ctx)(Authctxt*); int (*query)(void *ctx, char **name, char **infotxt, u_int *numprompts, char ***prompts, u_int **echo_on); int (*respond)(void *ctx, u_int numresp, char **responses); void (*free_ctx)(void *ctx); }; int auth_rhosts(struct passwd *, const char *); int auth_rhosts2(struct passwd *, const char *, const char *, const char *); 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(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 int auth_krb4(Authctxt *, KTEXT, char **); int auth_krb4_password(Authctxt *, const char *); void krb4_cleanup_proc(void *); #ifdef AFS #include int auth_krb4_tgt(Authctxt *, const char *); int auth_afs_token(Authctxt *, const char *); #endif /* AFS */ #endif /* KRB4 */ #ifdef KRB5 int auth_krb5(Authctxt *authctxt, krb5_data *auth, char **client); int auth_krb5_tgt(Authctxt *authctxt, krb5_data *tgt); int auth_krb5_password(Authctxt *authctxt, const char *password); void krb5_cleanup_proc(void *authctxt); #endif /* KRB5 */ #include "auth-pam.h" #include "auth2-pam.h" 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 *); struct passwd * auth_get_user(void); char *expand_filename(const char *, struct passwd *); char *authorized_keys_file(struct passwd *); char *authorized_keys_file2(struct passwd *); int secure_filename(FILE *, const char *, struct passwd *, char *, size_t); 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" +#ifdef SKEY +#ifdef OPIE +#define SKEY_PROMPT "\nOPIE Password: " +#else #define SKEY_PROMPT "\nS/Key Password: " #endif +#endif + +#endif diff --git a/crypto/openssh/configure.ac b/crypto/openssh/configure.ac index 9daf3b007e44..b255486b123b 100644 --- a/crypto/openssh/configure.ac +++ b/crypto/openssh/configure.ac @@ -1,2437 +1,2478 @@ # $Id: configure.ac,v 1.67 2002/06/21 00:01:19 mouring Exp $ +# $FreeBSD$ AC_INIT AC_CONFIG_SRCDIR([ssh.c]) AC_CONFIG_HEADER(config.h) AC_PROG_CC AC_CANONICAL_HOST AC_C_BIGENDIAN # Checks for programs. AC_PROG_CPP AC_PROG_RANLIB AC_PROG_INSTALL AC_PATH_PROG(AR, ar) AC_PATH_PROGS(PERL, perl5 perl) AC_SUBST(PERL) AC_PATH_PROG(ENT, ent) AC_SUBST(ENT) 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 if test -z "$AR" ; then AC_MSG_ERROR([*** 'ar' missing, please install or fix your \$PATH ***]) fi # Use LOGIN_PROGRAM from environment if possible if test ! -z "$LOGIN_PROGRAM" ; then AC_DEFINE_UNQUOTED(LOGIN_PROGRAM_FALLBACK, "$LOGIN_PROGRAM") else # Search for login AC_PATH_PROG(LOGIN_PROGRAM_FALLBACK, login) if test ! -z "$LOGIN_PROGRAM_FALLBACK" ; then AC_DEFINE_UNQUOTED(LOGIN_PROGRAM_FALLBACK, "$LOGIN_PROGRAM_FALLBACK") fi fi if test -z "$LD" ; then LD=$CC fi AC_SUBST(LD) AC_C_INLINE if test "$GCC" = "yes" || test "$GCC" = "egcs"; then CFLAGS="$CFLAGS -Wall -Wpointer-arith -Wno-uninitialized" fi # Check for some target-specific stuff case "$host" in *-*-aix*) AFS_LIBS="-lld" CPPFLAGS="$CPPFLAGS -I/usr/local/include" LDFLAGS="$LDFLAGS -L/usr/local/lib" if (test "$LD" != "gcc" && test -z "$blibpath"); then 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) ;; *-*-cygwin*) LIBS="$LIBS /usr/lib/textmode.o" AC_DEFINE(HAVE_CYGWIN) AC_DEFINE(USE_PIPES) AC_DEFINE(DISABLE_SHADOW) AC_DEFINE(IPV4_DEFAULT) AC_DEFINE(IP_TOS_IS_BROKEN) AC_DEFINE(NO_X11_UNIX_SOCKETS) AC_DEFINE(SETGROUPS_NOOP) ;; *-*-dgux*) AC_DEFINE(IP_TOS_IS_BROKEN) ;; *-*-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" fi 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) LIBS="$LIBS -lxnet -lsec" ;; *-*-hpux11*) CPPFLAGS="$CPPFLAGS -D_HPUX_SOURCE -D_XOPEN_SOURCE -D_XOPEN_SOURCE_EXTENDED=1" 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) LIBS="$LIBS -lxnet -lsec" ;; *-*-irix5*) CPPFLAGS="$CPPFLAGS -I/usr/local/include" LDFLAGS="$LDFLAGS" PATH="$PATH:/usr/etc" AC_DEFINE(BROKEN_INET_NTOA) AC_DEFINE(WITH_ABBREV_NO_TTY) ;; *-*-irix6*) CPPFLAGS="$CPPFLAGS -I/usr/local/include" LDFLAGS="$LDFLAGS" PATH="$PATH:/usr/etc" AC_DEFINE(WITH_IRIX_ARRAY) AC_DEFINE(WITH_IRIX_PROJECT) 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 check_for_libcrypt_later=1 AC_DEFINE(DONT_TRY_OTHER_AF) AC_DEFINE(PAM_TTY_KLUDGE) inet6_default_4in6=yes ;; mips-sony-bsd|mips-sony-newsos4) AC_DEFINE(HAVE_NEWS4) SONY=1 ;; *-*-netbsd*) need_dash_r=1 ;; *-*-freebsd*) check_for_libcrypt_later=1 ;; *-next-*) conf_lastlog_location="/usr/adm/lastlog" conf_utmp_location=/etc/utmp conf_wtmp_location=/usr/adm/wtmp MAIL=/usr/spool/mail AC_DEFINE(HAVE_NEXT) AC_DEFINE(BROKEN_REALPATH) AC_DEFINE(USE_PIPES) AC_DEFINE(BROKEN_SAVED_UIDS) CPPFLAGS="$CPPFLAGS -I/usr/local/include" CFLAGS="$CFLAGS" ;; *-*-solaris*) CPPFLAGS="$CPPFLAGS -I/usr/local/include" LDFLAGS="$LDFLAGS -L/usr/local/lib -R/usr/local/lib" need_dash_r=1 AC_DEFINE(PAM_SUN_CODEBASE) AC_DEFINE(LOGIN_NEEDS_UTMPX) AC_DEFINE(LOGIN_NEEDS_TERM) AC_DEFINE(PAM_TTY_KLUDGE) # hardwire lastlog location (can't detect it on some versions) conf_lastlog_location="/var/adm/lastlog" AC_MSG_CHECKING(for obsolete utmp and wtmp in solaris2.x) sol2ver=`echo "$host"| sed -e 's/.*[[0-9]]\.//'` if test "$sol2ver" -ge 8; then AC_MSG_RESULT(yes) AC_DEFINE(DISABLE_UTMP) AC_DEFINE(DISABLE_WTMP) else AC_MSG_RESULT(no) fi ;; *-*-sunos4*) CPPFLAGS="$CPPFLAGS -DSUNOS4" AC_CHECK_FUNCS(getpwanam) AC_DEFINE(PAM_SUN_CODEBASE) conf_utmp_location=/etc/utmp conf_wtmp_location=/var/adm/wtmp conf_lastlog_location=/var/adm/lastlog AC_DEFINE(USE_PIPES) ;; *-ncr-sysv*) CPPFLAGS="$CPPFLAGS -I/usr/local/include" LDFLAGS="$LDFLAGS -L/usr/local/lib" LIBS="$LIBS -lc89" AC_DEFINE(USE_PIPES) ;; *-sni-sysv*) CPPFLAGS="$CPPFLAGS -I/usr/local/include" # /usr/ucblib MUST NOT be searched on ReliantUNIX LDFLAGS="$LDFLAGS -L/usr/local/lib" IPADDR_IN_DISPLAY=yes AC_DEFINE(USE_PIPES) AC_DEFINE(IP_TOS_IS_BROKEN) # /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 ;; *-*-sysv4.2*) CPPFLAGS="$CPPFLAGS -I/usr/local/include" LDFLAGS="$LDFLAGS -L/usr/local/lib" AC_DEFINE(USE_PIPES) ;; *-*-sysv5*) CPPFLAGS="$CPPFLAGS -I/usr/local/include" LDFLAGS="$LDFLAGS -L/usr/local/lib" AC_DEFINE(USE_PIPES) ;; *-*-sysv*) CPPFLAGS="$CPPFLAGS -I/usr/local/include" LDFLAGS="$LDFLAGS -L/usr/local/lib" ;; *-*-sco3.2v4*) CPPFLAGS="$CPPFLAGS -Dftruncate=chsize -I/usr/local/include" LDFLAGS="$LDFLAGS -L/usr/local/lib" LIBS="$LIBS -los -lprot -lx -ltinfo -lm" rsh_path="/usr/bin/rcmd" RANLIB=true no_dev_ptmx=1 AC_DEFINE(BROKEN_SYS_TERMIO_H) AC_DEFINE(USE_PIPES) AC_DEFINE(HAVE_SECUREWARE) AC_DEFINE(DISABLE_SHADOW) AC_DEFINE(BROKEN_SAVED_UIDS) AC_CHECK_FUNCS(getluid setluid) MANTYPE=man do_sco3_extra_lib_check=yes ;; *-*-sco3.2v5*) CPPFLAGS="$CPPFLAGS -I/usr/local/include" LDFLAGS="$LDFLAGS -L/usr/local/lib" LIBS="$LIBS -lprot -lx -ltinfo -lm" no_dev_ptmx=1 rsh_path="/usr/bin/rcmd" AC_DEFINE(USE_PIPES) AC_DEFINE(HAVE_SECUREWARE) AC_DEFINE(DISABLE_SHADOW) AC_CHECK_FUNCS(getluid setluid) MANTYPE=man ;; *-*-unicos*) no_libsocket=1 no_libnsl=1 AC_DEFINE(USE_PIPES) LDFLAGS="$LDFLAGS -Wl,-Dmsglevel=334:fatal,-L/usr/local/lib" LIBS="$LIBS -lgen -lrsc" ;; *-dec-osf*) AC_MSG_CHECKING(for Digital Unix SIA) no_osfsia="" AC_ARG_WITH(osfsia, [ --with-osfsia Enable Digital Unix SIA], [ if test "x$withval" = "xno" ; then AC_MSG_RESULT(disabled) no_osfsia=1 fi ], ) if test -z "$no_osfsia" ; then if test -f /etc/sia/matrix.conf; then AC_MSG_RESULT(yes) AC_DEFINE(HAVE_OSF_SIA) AC_DEFINE(DISABLE_LOGIN) LIBS="$LIBS -lsecurity -ldb -lm -laud" else AC_MSG_RESULT(no) fi fi ;; *-*-nto-qnx) AC_DEFINE(USE_PIPES) AC_DEFINE(NO_X11_UNIX_SOCKETS) AC_DEFINE(MISSING_NFDBITS) AC_DEFINE(MISSING_HOWMANY) AC_DEFINE(MISSING_FD_MASK) ;; esac # Allow user to specify flags AC_ARG_WITH(cflags, [ --with-cflags Specify additional flags to pass to compiler], [ if test "x$withval" != "xno" ; then CFLAGS="$CFLAGS $withval" fi ] ) AC_ARG_WITH(cppflags, [ --with-cppflags Specify additional flags to pass to preprocessor] , [ if test "x$withval" != "xno"; then CPPFLAGS="$CPPFLAGS $withval" fi ] ) AC_ARG_WITH(ldflags, [ --with-ldflags Specify additional flags to pass to linker], [ if test "x$withval" != "xno" ; then LDFLAGS="$LDFLAGS $withval" fi ] ) AC_ARG_WITH(libs, [ --with-libs Specify additional libraries to link with], [ if test "x$withval" != "xno" ; then LIBS="$LIBS $withval" fi ] ) # Checks for header files. 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 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/mman.h sys/select.h sys/stat.h \ sys/stropts.h sys/sysmacros.h sys/time.h \ sys/un.h time.h ttyent.h usersec.h \ util.h utime.h utmp.h utmpx.h) # Checks for libraries. AC_CHECK_FUNC(yp_match, , AC_CHECK_LIB(nsl, yp_match)) AC_CHECK_FUNC(setsockopt, , AC_CHECK_LIB(socket, setsockopt)) dnl SCO OS3 needs this for libwrap if test "x$with_tcp_wrappers" != "xno" ; then if test "x$do_sco3_extra_lib_check" = "xyes" ; then AC_CHECK_LIB(rpc, innetgr, LIBS="-lrpc -lyp -lrpc $LIBS" , , -lyp -lrpc) fi fi AC_CHECK_FUNC(getspnam, , AC_CHECK_LIB(gen, getspnam, LIBS="$LIBS -lgen")) AC_ARG_WITH(rpath, [ --without-rpath Disable auto-added -R linker paths], [ if test "x$withval" = "xno" ; then need_dash_r="" fi if test "x$withval" = "xyes" ; then need_dash_r=1 fi ] ) dnl zlib is required AC_ARG_WITH(zlib, [ --with-zlib=PATH Use zlib in PATH], [ if test "x$withval" = "xno" ; then AC_MSG_ERROR([*** zlib is required ***]) fi 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 if test -n "${need_dash_r}"; then LDFLAGS="-L${withval} -R${withval} ${LDFLAGS}" else LDFLAGS="-L${withval} ${LDFLAGS}" fi fi if test -d "$withval/include"; then CPPFLAGS="-I${withval}/include ${CPPFLAGS}" else CPPFLAGS="-I${withval} ${CPPFLAGS}" fi ] ) AC_CHECK_LIB(z, deflate, ,AC_MSG_ERROR([*** zlib missing - please install first or check config.log ***])) dnl UnixWare 2.x AC_CHECK_FUNC(strcasecmp, [], [ AC_CHECK_LIB(resolv, strcasecmp, LIBS="$LIBS -lresolv") ] ) AC_CHECK_FUNC(utimes, [], [ AC_CHECK_LIB(c89, utimes, LIBS="$LIBS -lc89") ] ) dnl Checks for libutil functions AC_CHECK_HEADERS(libutil.h) AC_SEARCH_LIBS(login, util bsd, [AC_DEFINE(HAVE_LOGIN)]) AC_CHECK_FUNCS(logout updwtmp logwtmp) AC_FUNC_STRFTIME # Check for ALTDIRFUNC glob() extension AC_MSG_CHECKING(for GLOB_ALTDIRFUNC support) AC_EGREP_CPP(FOUNDIT, [ #include #ifdef GLOB_ALTDIRFUNC FOUNDIT #endif ], [ AC_DEFINE(GLOB_HAS_ALTDIRFUNC) AC_MSG_RESULT(yes) ], [ AC_MSG_RESULT(no) ] ) # Check for g.gl_matchc glob() extension AC_MSG_CHECKING(for gl_matchc field in glob_t) AC_EGREP_CPP(FOUNDIT, [ #include int main(void){glob_t g; g.gl_matchc = 1;} ], [ AC_DEFINE(GLOB_HAS_GL_MATCHC) AC_MSG_RESULT(yes) ], [ AC_MSG_RESULT(no) ] ) AC_MSG_CHECKING([whether struct dirent allocates space for d_name]) AC_TRY_RUN( [ #include #include int main(void){struct dirent d;return(sizeof(d.d_name)<=sizeof(char));} ], [AC_MSG_RESULT(yes)], [ AC_MSG_RESULT(no) AC_DEFINE(BROKEN_ONE_BYTE_DIRENT_D_NAME) ] ) # Check whether user wants S/Key support SKEY_MSG="no" AC_ARG_WITH(skey, [ --with-skey[[=PATH]] Enable S/Key support (optionally in PATH)], [ if test "x$withval" != "xno" ; then if test "x$withval" != "xyes" ; then CPPFLAGS="$CPPFLAGS -I${withval}/include" LDFLAGS="$LDFLAGS -L${withval}/lib" fi AC_DEFINE(SKEY) LIBS="-lskey $LIBS" SKEY_MSG="yes" AC_MSG_CHECKING([for s/key support]) AC_TRY_RUN( [ #include #include int main() { char *ff = skey_keyinfo(""); ff=""; return 0; } ], [AC_MSG_RESULT(yes)], [ AC_MSG_RESULT(no) AC_MSG_ERROR([** Incomplete or missing s/key libraries.]) ]) fi ] ) +# Check whether user wants OPIE support +OPIE_MSG="no" +AC_ARG_WITH(opie, + [ --with-opie[[=PATH]] Enable OPIE support + (optionally in PATH)], + [ + if test "x$withval" != "xno" ; then + + if test "x$withval" != "xyes" ; then + CPPFLAGS="$CPPFLAGS -I${withval}/include" + LDFLAGS="$LDFLAGS -L${withval}/lib" + fi + + AC_DEFINE(SKEY) + AC_DEFINE(OPIE) + LIBS="-lopie $LIBS" + OPIE_MSG="yes" + + AC_MSG_CHECKING([for opie support]) + AC_TRY_RUN( + [ +#include +#include +#include +int main() { char *ff = opie_keyinfo(""); ff=""; return 0; } + ], + [AC_MSG_RESULT(yes)], + [ + AC_MSG_RESULT(no) + AC_MSG_ERROR([** Incomplete or missing opie libraries.]) + ]) + fi + ] +) + # Check whether user wants TCP wrappers support TCPW_MSG="no" AC_ARG_WITH(tcp-wrappers, [ --with-tcp-wrappers[[=PATH]] Enable tcpwrappers support (optionally in PATH)], [ if test "x$withval" != "xno" ; then saved_LIBS="$LIBS" saved_LDFLAGS="$LDFLAGS" saved_CPPFLAGS="$CPPFLAGS" if test -n "${withval}" -a "${withval}" != "yes"; then 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 if test -n "${need_dash_r}"; then LDFLAGS="-L${withval} -R${withval} ${LDFLAGS}" else LDFLAGS="-L${withval} ${LDFLAGS}" fi fi if test -d "${withval}/include"; then CPPFLAGS="-I${withval}/include ${CPPFLAGS}" else CPPFLAGS="-I${withval} ${CPPFLAGS}" fi fi LIBWRAP="-lwrap" LIBS="$LIBWRAP $LIBS" AC_MSG_CHECKING(for libwrap) AC_TRY_LINK( [ #include int deny_severity = 0, allow_severity = 0; ], [hosts_access(0);], [ AC_MSG_RESULT(yes) AC_DEFINE(LIBWRAP) AC_SUBST(LIBWRAP) TCPW_MSG="yes" ], [ AC_MSG_ERROR([*** libwrap missing]) ] ) LIBS="$saved_LIBS" fi ] ) dnl Checks for library functions. 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 mmap ngetaddrinfo openpty ogetaddrinfo readpassphrase \ realpath recvmsg rresvport_af sendmsg setdtablesize setegid \ setenv seteuid setgroups setlogin setproctitle setresgid setreuid \ setrlimit setsid setpcred 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 AC_CHECK_FUNCS(dirname, [AC_CHECK_HEADERS(libgen.h)] ,[ AC_CHECK_LIB(gen, dirname,[ AC_CACHE_CHECK([for broken dirname], ac_cv_have_broken_dirname, [ save_LIBS="$LIBS" LIBS="$LIBS -lgen" AC_TRY_RUN( [ #include #include int main(int argc, char **argv) { char *s, buf[32]; strncpy(buf,"/etc", 32); s = dirname(buf); if (!s || strncmp(s, "/", 32) != 0) { exit(1); } else { exit(0); } } ], [ ac_cv_have_broken_dirname="no" ], [ ac_cv_have_broken_dirname="yes" ] ) LIBS="$save_LIBS" ]) if test "x$ac_cv_have_broken_dirname" = "xno" ; then LIBS="$LIBS -lgen" AC_DEFINE(HAVE_DIRNAME) AC_CHECK_HEADERS(libgen.h) fi ]) ]) dnl Checks for time functions AC_CHECK_FUNCS(gettimeofday time) dnl Checks for utmp functions AC_CHECK_FUNCS(endutent getutent getutid getutline pututline setutent) AC_CHECK_FUNCS(utmpname) dnl Checks for utmpx functions AC_CHECK_FUNCS(endutxent getutxent getutxid getutxline pututxline ) AC_CHECK_FUNCS(setutxent utmpxname) AC_CHECK_FUNC(daemon, [AC_DEFINE(HAVE_DAEMON)], [AC_CHECK_LIB(bsd, daemon, [LIBS="$LIBS -lbsd"; AC_DEFINE(HAVE_DAEMON)])] ) AC_CHECK_FUNC(getpagesize, [AC_DEFINE(HAVE_GETPAGESIZE)], [AC_CHECK_LIB(ucb, getpagesize, [LIBS="$LIBS -lucb"; AC_DEFINE(HAVE_GETPAGESIZE)])] ) # Check for broken snprintf if test "x$ac_cv_func_snprintf" = "xyes" ; then AC_MSG_CHECKING([whether snprintf correctly terminates long strings]) AC_TRY_RUN( [ #include int main(void){char b[5];snprintf(b,5,"123456789");return(b[4]!='\0');} ], [AC_MSG_RESULT(yes)], [ AC_MSG_RESULT(no) AC_DEFINE(BROKEN_SNPRINTF) AC_MSG_WARN([****** Your snprintf() function is broken, complain to your vendor]) ] ) fi AC_FUNC_GETPGRP # Check for PAM libs PAM_MSG="no" AC_ARG_WITH(pam, [ --with-pam Enable PAM support ], [ if test "x$withval" != "xno" ; then if test "x$ac_cv_header_security_pam_appl_h" != "xyes" ; then AC_MSG_ERROR([PAM headers not found]) fi AC_CHECK_LIB(dl, dlopen, , ) AC_CHECK_LIB(pam, pam_set_item, , AC_MSG_ERROR([*** libpam missing])) AC_CHECK_FUNCS(pam_getenvlist) disable_shadow=yes PAM_MSG="yes" AC_DEFINE(USE_PAM) if test $ac_cv_lib_dl_dlopen = yes; then LIBPAM="-lpam -ldl" else LIBPAM="-lpam" fi AC_SUBST(LIBPAM) fi ] ) # Check for older PAM if test "x$PAM_MSG" = "xyes" ; then # Check PAM strerror arguments (old PAM) AC_MSG_CHECKING([whether pam_strerror takes only one argument]) AC_TRY_COMPILE( [ #include #include ], [(void)pam_strerror((pam_handle_t *)NULL, -1);], [AC_MSG_RESULT(no)], [ AC_DEFINE(HAVE_OLD_PAM) AC_MSG_RESULT(yes) PAM_MSG="yes (old library)" ] ) fi # 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 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 if test -n "${need_dash_r}"; then LDFLAGS="-L${withval} -R${withval} ${LDFLAGS}" else LDFLAGS="-L${withval} ${LDFLAGS}" fi fi if test -d "$withval/include"; then CPPFLAGS="-I${withval}/include ${CPPFLAGS}" else CPPFLAGS="-I${withval} ${CPPFLAGS}" fi fi ] ) LIBS="$LIBS -lcrypto" AC_TRY_LINK_FUNC(RAND_add, AC_DEFINE(HAVE_OPENSSL), [ 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 LDFLAGS="-L/usr/local/ssl/lib ${saved_LDFLAGS}" 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]) AC_TRY_RUN( [ #include #include int main(void) { return(SSLeay() == OPENSSL_VERSION_NUMBER ? 0 : 1); } ], [ AC_MSG_RESULT(yes) ], [ AC_MSG_RESULT(no) AC_MSG_ERROR(Your OpenSSL headers do not match your library) ] ) # Some Linux systems (Slackware) need crypt() from libcrypt, *not* the # version in OpenSSL. Skip this for PAM if test "x$PAM_MSG" = "xno" -a "x$check_for_libcrypt_later" = "x1"; then AC_CHECK_LIB(crypt, crypt, LIBS="$LIBS -lcrypt") fi ### Configure cryptographic random number support # Check wheter OpenSSL seeds itself AC_MSG_CHECKING([whether OpenSSL's PRNG is internally seeded]) AC_TRY_RUN( [ #include #include int main(void) { return(RAND_status() == 1 ? 0 : 1); } ], [ OPENSSL_SEEDS_ITSELF=yes AC_MSG_RESULT(yes) ], [ AC_MSG_RESULT(no) # Default to use of the rand helper if OpenSSL doesn't # seed itself USE_RAND_HELPER=yes ] ) # Do we want to force the use of the rand helper? AC_ARG_WITH(rand-helper, [ --with-rand-helper Use subprocess to gather strong randomness ], [ if test "x$withval" = "xno" ; then # Force use of OpenSSL's internal RNG, even if # the previous test showed it to be unseeded. if test -z "$OPENSSL_SEEDS_ITSELF" ; then AC_MSG_WARN([*** Forcing use of OpenSSL's non-self-seeding PRNG]) OPENSSL_SEEDS_ITSELF=yes USE_RAND_HELPER="" fi else USE_RAND_HELPER=yes fi ], ) # Which randomness source do we use? if test ! -z "$OPENSSL_SEEDS_ITSELF" -a -z "$USE_RAND_HELPER" ; then # OpenSSL only AC_DEFINE(OPENSSL_PRNG_ONLY) RAND_MSG="OpenSSL internal ONLY" INSTALL_SSH_RAND_HELPER="" elif test ! -z "$USE_RAND_HELPER" ; then # install rand helper RAND_MSG="ssh-rand-helper" INSTALL_SSH_RAND_HELPER="yes" fi AC_SUBST(INSTALL_SSH_RAND_HELPER) ### Configuration of ssh-rand-helper # PRNGD TCP socket AC_ARG_WITH(prngd-port, [ --with-prngd-port=PORT read entropy from PRNGD/EGD TCP localhost:PORT], [ case "$withval" in no) withval="" ;; [[0-9]]*) ;; *) AC_MSG_ERROR(You must specify a numeric port number for --with-prngd-port) ;; esac if test ! -z "$withval" ; then PRNGD_PORT="$withval" AC_DEFINE_UNQUOTED(PRNGD_PORT, $PRNGD_PORT) fi ] ) # PRNGD Unix domain socket AC_ARG_WITH(prngd-socket, [ --with-prngd-socket=FILE read entropy from PRNGD/EGD socket FILE (default=/var/run/egd-pool)], [ case "$withval" in yes) withval="/var/run/egd-pool" ;; no) withval="" ;; /*) ;; *) AC_MSG_ERROR(You must specify an absolute path to the entropy socket) ;; esac if test ! -z "$withval" ; then if test ! -z "$PRNGD_PORT" ; then AC_MSG_ERROR(You may not specify both a PRNGD/EGD port and socket) fi if test ! -r "$withval" ; then AC_MSG_WARN(Entropy socket is not readable) fi PRNGD_SOCKET="$withval" AC_DEFINE_UNQUOTED(PRNGD_SOCKET, "$PRNGD_SOCKET") fi ], [ # Check for existing socket only if we don't have a random device already if test "$USE_RAND_HELPER" = yes ; then AC_MSG_CHECKING(for PRNGD/EGD socket) # Insert other locations here for sock in /var/run/egd-pool /dev/egd-pool /etc/entropy; do if test -r $sock && $TEST_MINUS_S_SH -c "test -S $sock -o -p $sock" ; then PRNGD_SOCKET="$sock" AC_DEFINE_UNQUOTED(PRNGD_SOCKET, "$PRNGD_SOCKET") break; fi done if test ! -z "$PRNGD_SOCKET" ; then AC_MSG_RESULT($PRNGD_SOCKET) else AC_MSG_RESULT(not found) fi fi ] ) # Change default command timeout for hashing entropy source entropy_timeout=200 AC_ARG_WITH(entropy-timeout, [ --with-entropy-timeout Specify entropy gathering command timeout (msec)], [ if test "x$withval" != "xno" ; then entropy_timeout=$withval 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) OSSH_PATH_ENTROPY_PROG(PROG_ARP, arp) OSSH_PATH_ENTROPY_PROG(PROG_IFCONFIG, ifconfig) OSSH_PATH_ENTROPY_PROG(PROG_JSTAT, jstat) OSSH_PATH_ENTROPY_PROG(PROG_PS, ps) OSSH_PATH_ENTROPY_PROG(PROG_SAR, sar) OSSH_PATH_ENTROPY_PROG(PROG_W, w) OSSH_PATH_ENTROPY_PROG(PROG_WHO, who) OSSH_PATH_ENTROPY_PROG(PROG_LAST, last) OSSH_PATH_ENTROPY_PROG(PROG_LASTLOG, lastlog) OSSH_PATH_ENTROPY_PROG(PROG_DF, df) 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="" if test ! -z "$INSTALL_SSH_RAND_HELPER" ; then if test ! -z "$PRNGD_PORT" ; then RAND_HELPER_MSG="TCP localhost:$PRNGD_PORT" elif test ! -z "$PRNGD_SOCKET" ; then RAND_HELPER_MSG="Unix domain socket \"$PRNGD_SOCKET\"" else RAND_HELPER_MSG="Command hashing (timeout $entropy_timeout)" RAND_HELPER_CMDHASH=yes INSTALL_SSH_PRNG_CMDS="yes" fi fi AC_SUBST(INSTALL_SSH_PRNG_CMDS) # Cheap hack to ensure NEWS-OS libraries are arranged right. if test ! -z "$SONY" ; then LIBS="$LIBS -liberty"; fi # Checks for data types AC_CHECK_SIZEOF(char, 1) AC_CHECK_SIZEOF(short int, 2) 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( [ #include ], [ u_int a; a = 1;], [ ac_cv_have_u_int="yes" ], [ ac_cv_have_u_int="no" ] ) ]) if test "x$ac_cv_have_u_int" = "xyes" ; then AC_DEFINE(HAVE_U_INT) have_u_int=1 fi AC_CACHE_CHECK([for intXX_t types], ac_cv_have_intxx_t, [ AC_TRY_COMPILE( [ #include ], [ int8_t a; int16_t b; int32_t c; a = b = c = 1;], [ ac_cv_have_intxx_t="yes" ], [ ac_cv_have_intxx_t="no" ] ) ]) if test "x$ac_cv_have_intxx_t" = "xyes" ; then AC_DEFINE(HAVE_INTXX_T) have_intxx_t=1 fi if (test -z "$have_intxx_t" && \ test "x$ac_cv_header_stdint_h" = "xyes") then AC_MSG_CHECKING([for intXX_t types in stdint.h]) AC_TRY_COMPILE( [ #include ], [ int8_t a; int16_t b; int32_t c; a = b = c = 1;], [ AC_DEFINE(HAVE_INTXX_T) AC_MSG_RESULT(yes) ], [ AC_MSG_RESULT(no) ] ) fi AC_CACHE_CHECK([for int64_t type], ac_cv_have_int64_t, [ AC_TRY_COMPILE( [ #include ], [ int64_t a; a = 1;], [ ac_cv_have_int64_t="yes" ], [ ac_cv_have_int64_t="no" ] ) ]) if test "x$ac_cv_have_int64_t" = "xyes" ; then AC_DEFINE(HAVE_INT64_T) have_int64_t=1 fi if test -z "$have_int64_t" ; then AC_MSG_CHECKING([for int64_t type in sys/socket.h]) AC_TRY_COMPILE( [ #include ], [ int64_t a; a = 1], [ AC_DEFINE(HAVE_INT64_T) AC_MSG_RESULT(yes) ], [ AC_MSG_RESULT(no) ] ) fi if test -z "$have_int64_t" ; then AC_MSG_CHECKING([for int64_t type in sys/bitypes.h]) AC_TRY_COMPILE( [ #include ], [ int64_t a; a = 1], [ AC_DEFINE(HAVE_INT64_T) AC_MSG_RESULT(yes) ], [ AC_MSG_RESULT(no) ] ) fi AC_CACHE_CHECK([for u_intXX_t types], ac_cv_have_u_intxx_t, [ AC_TRY_COMPILE( [ #include ], [ u_int8_t a; u_int16_t b; u_int32_t c; a = b = c = 1;], [ ac_cv_have_u_intxx_t="yes" ], [ ac_cv_have_u_intxx_t="no" ] ) ]) if test "x$ac_cv_have_u_intxx_t" = "xyes" ; then AC_DEFINE(HAVE_U_INTXX_T) have_u_intxx_t=1 fi if test -z "$have_u_intxx_t" ; then AC_MSG_CHECKING([for u_intXX_t types in sys/socket.h]) AC_TRY_COMPILE( [ #include ], [ u_int8_t a; u_int16_t b; u_int32_t c; a = b = c = 1;], [ AC_DEFINE(HAVE_U_INTXX_T) AC_MSG_RESULT(yes) ], [ AC_MSG_RESULT(no) ] ) fi AC_CACHE_CHECK([for u_int64_t types], ac_cv_have_u_int64_t, [ AC_TRY_COMPILE( [ #include ], [ u_int64_t a; a = 1;], [ ac_cv_have_u_int64_t="yes" ], [ ac_cv_have_u_int64_t="no" ] ) ]) if test "x$ac_cv_have_u_int64_t" = "xyes" ; then AC_DEFINE(HAVE_U_INT64_T) have_u_int64_t=1 fi if test -z "$have_u_int64_t" ; then AC_MSG_CHECKING([for u_int64_t type in sys/bitypes.h]) AC_TRY_COMPILE( [ #include ], [ u_int64_t a; a = 1], [ AC_DEFINE(HAVE_U_INT64_T) AC_MSG_RESULT(yes) ], [ AC_MSG_RESULT(no) ] ) fi if test -z "$have_u_intxx_t" ; then AC_CACHE_CHECK([for uintXX_t types], ac_cv_have_uintxx_t, [ AC_TRY_COMPILE( [ #include ], [ uint8_t a; uint16_t b; uint32_t c; a = b = c = 1; ], [ ac_cv_have_uintxx_t="yes" ], [ ac_cv_have_uintxx_t="no" ] ) ]) if test "x$ac_cv_have_uintxx_t" = "xyes" ; then AC_DEFINE(HAVE_UINTXX_T) fi fi if test -z "$have_uintxx_t" ; then AC_MSG_CHECKING([for uintXX_t types in stdint.h]) AC_TRY_COMPILE( [ #include ], [ uint8_t a; uint16_t b; uint32_t c; a = b = c = 1;], [ AC_DEFINE(HAVE_UINTXX_T) AC_MSG_RESULT(yes) ], [ AC_MSG_RESULT(no) ] ) fi if (test -z "$have_u_intxx_t" || test -z "$have_intxx_t" && \ test "x$ac_cv_header_sys_bitypes_h" = "xyes") then AC_MSG_CHECKING([for intXX_t and u_intXX_t types in sys/bitypes.h]) AC_TRY_COMPILE( [ #include ], [ int8_t a; int16_t b; int32_t c; u_int8_t e; u_int16_t f; u_int32_t g; a = b = c = e = f = g = 1; ], [ AC_DEFINE(HAVE_U_INTXX_T) AC_DEFINE(HAVE_INTXX_T) AC_MSG_RESULT(yes) ], [AC_MSG_RESULT(no)] ) fi AC_CACHE_CHECK([for u_char], ac_cv_have_u_char, [ AC_TRY_COMPILE( [ #include ], [ u_char foo; foo = 125; ], [ ac_cv_have_u_char="yes" ], [ ac_cv_have_u_char="no" ] ) ]) if test "x$ac_cv_have_u_char" = "xyes" ; then AC_DEFINE(HAVE_U_CHAR) fi TYPE_SOCKLEN_T AC_CHECK_TYPES(sig_atomic_t,,,[#include ]) AC_CACHE_CHECK([for size_t], ac_cv_have_size_t, [ AC_TRY_COMPILE( [ #include ], [ size_t foo; foo = 1235; ], [ ac_cv_have_size_t="yes" ], [ ac_cv_have_size_t="no" ] ) ]) if test "x$ac_cv_have_size_t" = "xyes" ; then AC_DEFINE(HAVE_SIZE_T) fi AC_CACHE_CHECK([for ssize_t], ac_cv_have_ssize_t, [ AC_TRY_COMPILE( [ #include ], [ ssize_t foo; foo = 1235; ], [ ac_cv_have_ssize_t="yes" ], [ ac_cv_have_ssize_t="no" ] ) ]) if test "x$ac_cv_have_ssize_t" = "xyes" ; then AC_DEFINE(HAVE_SSIZE_T) fi AC_CACHE_CHECK([for clock_t], ac_cv_have_clock_t, [ AC_TRY_COMPILE( [ #include ], [ clock_t foo; foo = 1235; ], [ ac_cv_have_clock_t="yes" ], [ ac_cv_have_clock_t="no" ] ) ]) if test "x$ac_cv_have_clock_t" = "xyes" ; then AC_DEFINE(HAVE_CLOCK_T) fi AC_CACHE_CHECK([for sa_family_t], ac_cv_have_sa_family_t, [ AC_TRY_COMPILE( [ #include #include ], [ sa_family_t foo; foo = 1235; ], [ ac_cv_have_sa_family_t="yes" ], [ AC_TRY_COMPILE( [ #include #include #include ], [ sa_family_t foo; foo = 1235; ], [ ac_cv_have_sa_family_t="yes" ], [ ac_cv_have_sa_family_t="no" ] )] ) ]) if test "x$ac_cv_have_sa_family_t" = "xyes" ; then AC_DEFINE(HAVE_SA_FAMILY_T) fi AC_CACHE_CHECK([for pid_t], ac_cv_have_pid_t, [ AC_TRY_COMPILE( [ #include ], [ pid_t foo; foo = 1235; ], [ ac_cv_have_pid_t="yes" ], [ ac_cv_have_pid_t="no" ] ) ]) if test "x$ac_cv_have_pid_t" = "xyes" ; then AC_DEFINE(HAVE_PID_T) fi AC_CACHE_CHECK([for mode_t], ac_cv_have_mode_t, [ AC_TRY_COMPILE( [ #include ], [ mode_t foo; foo = 1235; ], [ ac_cv_have_mode_t="yes" ], [ ac_cv_have_mode_t="no" ] ) ]) if test "x$ac_cv_have_mode_t" = "xyes" ; then AC_DEFINE(HAVE_MODE_T) fi AC_CACHE_CHECK([for struct sockaddr_storage], ac_cv_have_struct_sockaddr_storage, [ AC_TRY_COMPILE( [ #include #include ], [ struct sockaddr_storage s; ], [ ac_cv_have_struct_sockaddr_storage="yes" ], [ ac_cv_have_struct_sockaddr_storage="no" ] ) ]) if test "x$ac_cv_have_struct_sockaddr_storage" = "xyes" ; then AC_DEFINE(HAVE_STRUCT_SOCKADDR_STORAGE) fi AC_CACHE_CHECK([for struct sockaddr_in6], ac_cv_have_struct_sockaddr_in6, [ AC_TRY_COMPILE( [ #include #include ], [ struct sockaddr_in6 s; s.sin6_family = 0; ], [ ac_cv_have_struct_sockaddr_in6="yes" ], [ ac_cv_have_struct_sockaddr_in6="no" ] ) ]) if test "x$ac_cv_have_struct_sockaddr_in6" = "xyes" ; then AC_DEFINE(HAVE_STRUCT_SOCKADDR_IN6) fi AC_CACHE_CHECK([for struct in6_addr], ac_cv_have_struct_in6_addr, [ AC_TRY_COMPILE( [ #include #include ], [ struct in6_addr s; s.s6_addr[0] = 0; ], [ ac_cv_have_struct_in6_addr="yes" ], [ ac_cv_have_struct_in6_addr="no" ] ) ]) if test "x$ac_cv_have_struct_in6_addr" = "xyes" ; then AC_DEFINE(HAVE_STRUCT_IN6_ADDR) fi AC_CACHE_CHECK([for struct addrinfo], ac_cv_have_struct_addrinfo, [ AC_TRY_COMPILE( [ #include #include #include ], [ struct addrinfo s; s.ai_flags = AI_PASSIVE; ], [ ac_cv_have_struct_addrinfo="yes" ], [ ac_cv_have_struct_addrinfo="no" ] ) ]) if test "x$ac_cv_have_struct_addrinfo" = "xyes" ; then AC_DEFINE(HAVE_STRUCT_ADDRINFO) fi AC_CACHE_CHECK([for struct timeval], ac_cv_have_struct_timeval, [ AC_TRY_COMPILE( [ #include ], [ struct timeval tv; tv.tv_sec = 1;], [ ac_cv_have_struct_timeval="yes" ], [ ac_cv_have_struct_timeval="no" ] ) ]) if test "x$ac_cv_have_struct_timeval" = "xyes" ; then AC_DEFINE(HAVE_STRUCT_TIMEVAL) have_struct_timeval=1 fi # If we don't have int64_t then we can't compile sftp-server. So don't # even attempt to do it. if test "x$ac_cv_have_int64_t" = "xno" -a \ "x$ac_cv_sizeof_long_int" != "x8" -a \ "x$ac_cv_sizeof_long_long_int" = "x0" ; then NO_SFTP='#' else dnl test snprintf (broken on SCO w/gcc) AC_TRY_RUN( [ #include #include #ifdef HAVE_SNPRINTF main() { char buf[50]; char expected_out[50]; int mazsize = 50 ; #if (SIZEOF_LONG_INT == 8) long int num = 0x7fffffffffffffff; #else long long num = 0x7fffffffffffffffll; #endif strcpy(expected_out, "9223372036854775807"); snprintf(buf, mazsize, "%lld", num); if(strcmp(buf, expected_out) != 0) exit(1); exit(0); } #else main() { exit(0); } #endif ], [ true ], [ AC_DEFINE(BROKEN_SNPRINTF) ] ) fi AC_SUBST(NO_SFTP) dnl Checks for structure members OSSH_CHECK_HEADER_FOR_FIELD(ut_host, utmp.h, HAVE_HOST_IN_UTMP) OSSH_CHECK_HEADER_FOR_FIELD(ut_host, utmpx.h, HAVE_HOST_IN_UTMPX) OSSH_CHECK_HEADER_FOR_FIELD(syslen, utmpx.h, HAVE_SYSLEN_IN_UTMPX) OSSH_CHECK_HEADER_FOR_FIELD(ut_pid, utmp.h, HAVE_PID_IN_UTMP) OSSH_CHECK_HEADER_FOR_FIELD(ut_type, utmp.h, HAVE_TYPE_IN_UTMP) OSSH_CHECK_HEADER_FOR_FIELD(ut_type, utmpx.h, HAVE_TYPE_IN_UTMPX) OSSH_CHECK_HEADER_FOR_FIELD(ut_tv, utmp.h, HAVE_TV_IN_UTMP) OSSH_CHECK_HEADER_FOR_FIELD(ut_id, utmp.h, HAVE_ID_IN_UTMP) OSSH_CHECK_HEADER_FOR_FIELD(ut_id, utmpx.h, HAVE_ID_IN_UTMPX) OSSH_CHECK_HEADER_FOR_FIELD(ut_addr, utmp.h, HAVE_ADDR_IN_UTMP) OSSH_CHECK_HEADER_FOR_FIELD(ut_addr, utmpx.h, HAVE_ADDR_IN_UTMPX) OSSH_CHECK_HEADER_FOR_FIELD(ut_addr_v6, utmp.h, HAVE_ADDR_V6_IN_UTMP) OSSH_CHECK_HEADER_FOR_FIELD(ut_addr_v6, utmpx.h, HAVE_ADDR_V6_IN_UTMPX) OSSH_CHECK_HEADER_FOR_FIELD(ut_exit, utmp.h, HAVE_EXIT_IN_UTMP) OSSH_CHECK_HEADER_FOR_FIELD(ut_time, utmp.h, HAVE_TIME_IN_UTMP) OSSH_CHECK_HEADER_FOR_FIELD(ut_time, utmpx.h, HAVE_TIME_IN_UTMPX) OSSH_CHECK_HEADER_FOR_FIELD(ut_tv, utmpx.h, HAVE_TV_IN_UTMPX) AC_CHECK_MEMBERS([struct stat.st_blksize]) AC_CACHE_CHECK([for ss_family field in struct sockaddr_storage], ac_cv_have_ss_family_in_struct_ss, [ AC_TRY_COMPILE( [ #include #include ], [ struct sockaddr_storage s; s.ss_family = 1; ], [ ac_cv_have_ss_family_in_struct_ss="yes" ], [ ac_cv_have_ss_family_in_struct_ss="no" ], ) ]) if test "x$ac_cv_have_ss_family_in_struct_ss" = "xyes" ; then AC_DEFINE(HAVE_SS_FAMILY_IN_SS) fi AC_CACHE_CHECK([for __ss_family field in struct sockaddr_storage], ac_cv_have___ss_family_in_struct_ss, [ AC_TRY_COMPILE( [ #include #include ], [ struct sockaddr_storage s; s.__ss_family = 1; ], [ ac_cv_have___ss_family_in_struct_ss="yes" ], [ ac_cv_have___ss_family_in_struct_ss="no" ] ) ]) if test "x$ac_cv_have___ss_family_in_struct_ss" = "xyes" ; then AC_DEFINE(HAVE___SS_FAMILY_IN_SS) fi AC_CACHE_CHECK([for pw_class field in struct passwd], ac_cv_have_pw_class_in_struct_passwd, [ AC_TRY_COMPILE( [ #include ], [ struct passwd p; p.pw_class = 0; ], [ ac_cv_have_pw_class_in_struct_passwd="yes" ], [ ac_cv_have_pw_class_in_struct_passwd="no" ] ) ]) if test "x$ac_cv_have_pw_class_in_struct_passwd" = "xyes" ; then AC_DEFINE(HAVE_PW_CLASS_IN_PASSWD) fi AC_CACHE_CHECK([for pw_expire field in struct passwd], ac_cv_have_pw_expire_in_struct_passwd, [ AC_TRY_COMPILE( [ #include ], [ struct passwd p; p.pw_expire = 0; ], [ ac_cv_have_pw_expire_in_struct_passwd="yes" ], [ ac_cv_have_pw_expire_in_struct_passwd="no" ] ) ]) if test "x$ac_cv_have_pw_expire_in_struct_passwd" = "xyes" ; then AC_DEFINE(HAVE_PW_EXPIRE_IN_PASSWD) fi AC_CACHE_CHECK([for pw_change field in struct passwd], ac_cv_have_pw_change_in_struct_passwd, [ AC_TRY_COMPILE( [ #include ], [ struct passwd p; p.pw_change = 0; ], [ ac_cv_have_pw_change_in_struct_passwd="yes" ], [ ac_cv_have_pw_change_in_struct_passwd="no" ] ) ]) if test "x$ac_cv_have_pw_change_in_struct_passwd" = "xyes" ; then AC_DEFINE(HAVE_PW_CHANGE_IN_PASSWD) fi dnl make sure we're using the real structure members and not defines AC_CACHE_CHECK([for msg_accrights field in struct msghdr], ac_cv_have_accrights_in_msghdr, [ AC_TRY_RUN( [ #include #include #include int main() { #ifdef msg_accrights exit(1); #endif struct msghdr m; m.msg_accrights = 0; exit(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_RUN( [ #include #include #include int main() { #ifdef msg_control exit(1); #endif struct msghdr m; m.msg_control = 0; exit(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); ], [ ac_cv_libc_defines___progname="yes" ], [ ac_cv_libc_defines___progname="no" ] ) ]) 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( [ +#if HAVE_GETOPT_H #include +#elif HAVE_UNISTD_H +#include +#endif ], [ extern int optreset; optreset = 0; ], [ ac_cv_have_getopt_optreset="yes" ], [ ac_cv_have_getopt_optreset="no" ] ) ]) if test "x$ac_cv_have_getopt_optreset" = "xyes" ; then AC_DEFINE(HAVE_GETOPT_OPTRESET) fi AC_CACHE_CHECK([if libc defines sys_errlist], ac_cv_libc_defines_sys_errlist, [ AC_TRY_LINK([], [ extern const char *const sys_errlist[]; printf("%s", sys_errlist[0]);], [ ac_cv_libc_defines_sys_errlist="yes" ], [ ac_cv_libc_defines_sys_errlist="no" ] ) ]) if test "x$ac_cv_libc_defines_sys_errlist" = "xyes" ; then AC_DEFINE(HAVE_SYS_ERRLIST) fi AC_CACHE_CHECK([if libc defines sys_nerr], ac_cv_libc_defines_sys_nerr, [ AC_TRY_LINK([], [ extern int sys_nerr; printf("%i", sys_nerr);], [ ac_cv_libc_defines_sys_nerr="yes" ], [ ac_cv_libc_defines_sys_nerr="no" ] ) ]) if test "x$ac_cv_libc_defines_sys_nerr" = "xyes" ; then AC_DEFINE(HAVE_SYS_NERR) fi SCARD_MSG="no" # 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 CPPFLAGS="$CPPFLAGS -I${withval}" LDFLAGS="$LDFLAGS -L${withval}" if test ! -z "$need_dash_r" ; then LDFLAGS="$LDFLAGS -R${withval}" fi if test ! -z "$blibpath" ; then blibpath="$blibpath:${withval}" fi fi AC_CHECK_HEADERS(sectok.h) if test "$ac_cv_header_sectok_h" != yes; then AC_MSG_ERROR(Can't find sectok.h) fi AC_CHECK_LIB(sectok, sectok_open) if test "$ac_cv_lib_sectok_sectok_open" != yes; then AC_MSG_ERROR(Can't find libsectok) fi AC_DEFINE(SMARTCARD) 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], [ if test "x$withval" != "xno" ; then if test "x$withval" = "xyes" ; then KRB5ROOT="/usr/local" else KRB5ROOT=${withval} fi 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; ], [ AC_MSG_RESULT(yes) AC_DEFINE(HEIMDAL) K5LIBS="-lkrb5 -ldes -lcom_err -lasn1 -lroken" ], [ AC_MSG_RESULT(no) K5LIBS="-lkrb5 -lk5crypto -lcom_err" ] ) if test ! -z "$need_dash_r" ; then LDFLAGS="$LDFLAGS -R${KRB5ROOT}/lib" fi if test ! -z "$blibpath" ; then blibpath="$blibpath:${KRB5ROOT}/lib" fi AC_CHECK_LIB(resolv, dn_expand, , ) KRB5=yes fi ] ) # Check whether user wants Kerberos 4 support KRB4_MSG="no" AC_ARG_WITH(kerberos4, [ --with-kerberos4=PATH Enable Kerberos 4 support], [ if test "x$withval" != "xno" ; then if test "x$withval" != "xyes" ; then CPPFLAGS="$CPPFLAGS -I${withval}/include" LDFLAGS="$LDFLAGS -L${withval}/lib" if test ! -z "$need_dash_r" ; then LDFLAGS="$LDFLAGS -R${withval}/lib" fi if test ! -z "$blibpath" ; then blibpath="$blibpath:${withval}/lib" fi else if test -d /usr/include/kerberosIV ; then CPPFLAGS="$CPPFLAGS -I/usr/include/kerberosIV" fi fi AC_CHECK_HEADERS(krb.h) if test "$ac_cv_header_krb_h" != yes; then AC_MSG_WARN([Cannot find krb.h, build may fail]) fi AC_CHECK_LIB(krb, main) if test "$ac_cv_lib_krb_main" != yes; then AC_CHECK_LIB(krb4, main) if test "$ac_cv_lib_krb4_main" != yes; then AC_MSG_WARN([Cannot find libkrb nor libkrb4, build may fail]) else KLIBS="-lkrb4" fi else KLIBS="-lkrb" fi AC_CHECK_LIB(des, des_cbc_encrypt) if test "$ac_cv_lib_des_des_cbc_encrypt" != yes; then AC_CHECK_LIB(des425, des_cbc_encrypt) if test "$ac_cv_lib_des425_des_cbc_encrypt" != yes; then AC_MSG_WARN([Cannot find libdes nor libdes425, build may fail]) else KLIBS="-ldes425" fi else KLIBS="-ldes" fi AC_CHECK_LIB(resolv, dn_expand, , ) KRB4=yes KRB4_MSG="yes" AC_DEFINE(KRB4) fi ] ) # Check whether user wants AFS support AFS_MSG="no" AC_ARG_WITH(afs, [ --with-afs=PATH Enable AFS support], [ if test "x$withval" != "xno" ; then if test "x$withval" != "xyes" ; then CPPFLAGS="$CPPFLAGS -I${withval}/include" LDFLAGS="$LDFLAGS -L${withval}/lib" fi if test -z "$KRB4" ; then AC_MSG_WARN([AFS requires Kerberos IV support, build may fail]) fi LIBS="-lkafs $LIBS" if test ! -z "$AFS_LIBS" ; then LIBS="$LIBS $AFS_LIBS" fi AC_DEFINE(AFS) AFS_MSG="yes" fi ] ) LIBS="$LIBS $KLIBS $K5LIBS" # Looking for programs, paths and files AC_ARG_WITH(rsh, [ --with-rsh=PATH Specify path to remote shell program ], [ if test "x$withval" != "$no" ; then rsh_path=$withval fi ], [ AC_PATH_PROG(rsh_path, rsh) ] ) PRIVSEP_PATH=/var/empty AC_ARG_WITH(privsep-path, [ --with-privsep-path=xxx Path for privilege separation 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 ], [ if test "x$withval" != "xno" ; then xauth_path=$withval fi ], [ AC_PATH_PROG(xauth_path, xauth,,$PATH:/usr/X/bin:/usr/bin/X11:/usr/X11R6/bin:/usr/openwin/bin) if (test ! -z "$xauth_path" && test -x "/usr/openwin/bin/xauth") ; then xauth_path="/usr/openwin/bin/xauth" fi ] ) if test -z "$xauth_path" ; then XAUTH_PATH="undefined" AC_SUBST(XAUTH_PATH) else AC_DEFINE_UNQUOTED(XAUTH_PATH, "$xauth_path") XAUTH_PATH=$xauth_path AC_SUBST(XAUTH_PATH) fi if test ! -z "$rsh_path" ; then AC_DEFINE_UNQUOTED(RSH_PATH, "$rsh_path") fi # Check for mail directory (last resort if we cannot get it from headers) if test ! -z "$MAIL" ; then maildir=`dirname $MAIL` AC_DEFINE_UNQUOTED(MAIL_DIRECTORY, "$maildir") fi if test -z "$no_dev_ptmx" ; then 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", [ AC_DEFINE_UNQUOTED(HAVE_DEV_PTS_AND_PTC) have_dev_ptc=1 ] ) # Options from here on. Some of these are preset by platform above AC_ARG_WITH(mantype, [ --with-mantype=man|cat|doc Set man page type], [ case "$withval" in man|cat|doc) MANTYPE=$withval ;; *) AC_MSG_ERROR(invalid man type: $withval) ;; esac ] ) if test -z "$MANTYPE"; then AC_PATH_PROGS(NROFF, nroff awf, /bin/false, /usr/bin:/usr/ucb) if ${NROFF} -mdoc ${srcdir}/ssh.1 >/dev/null 2>&1; then MANTYPE=doc elif ${NROFF} -man ${srcdir}/ssh.1 >/dev/null 2>&1; then MANTYPE=man else MANTYPE=cat fi fi AC_SUBST(MANTYPE) if test "$MANTYPE" = "doc"; then mansubdir=man; else mansubdir=$MANTYPE; fi AC_SUBST(mansubdir) # Check whether to enable MD5 passwords MD5_MSG="no" AC_ARG_WITH(md5-passwords, [ --with-md5-passwords Enable use of MD5 passwords], [ if test "x$withval" != "xno" ; then AC_DEFINE(HAVE_MD5_PASSWORDS) MD5_MSG="yes" fi ] ) # Whether to disable shadow password support AC_ARG_WITH(shadow, [ --without-shadow Disable shadow password support], [ if test "x$withval" = "xno" ; then AC_DEFINE(DISABLE_SHADOW) disable_shadow=yes fi ] ) if test -z "$disable_shadow" ; then AC_MSG_CHECKING([if the systems has expire shadow information]) AC_TRY_COMPILE( [ #include #include struct spwd sp; ],[ sp.sp_expire = sp.sp_lstchg = sp.sp_inact = 0; ], [ sp_expire_available=yes ], [] ) if test "x$sp_expire_available" = "xyes" ; then AC_MSG_RESULT(yes) AC_DEFINE(HAS_SHADOW_EXPIRE) else AC_MSG_RESULT(no) fi fi # Use ip address instead of hostname in $DISPLAY if test ! -z "$IPADDR_IN_DISPLAY" ; then DISPLAY_HACK_MSG="yes" AC_DEFINE(IPADDR_IN_DISPLAY) else DISPLAY_HACK_MSG="no" AC_ARG_WITH(ipaddr-display, [ --with-ipaddr-display Use ip address instead of hostname in \$DISPLAY], [ if test "x$withval" != "xno" ; then AC_DEFINE(IPADDR_IN_DISPLAY) DISPLAY_HACK_MSG="yes" fi ] ) 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= Specify default \$PATH environment for server], [ 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 */ #include #ifdef HAVE_PATHS_H # include #endif #ifndef _PATH_STDPATH # define _PATH_STDPATH "/usr/bin:/bin:/usr/sbin:/sbin" #endif #include #include #include #define DATA "conftest.stdpath" main() { FILE *fd; int rc; fd = fopen(DATA,"w"); if(fd == NULL) exit(1); if ((rc = fprintf(fd,"%s", _PATH_STDPATH)) < 0) exit(1); exit(0); } ], [ user_path=`cat conftest.stdpath` ], [ user_path="/usr/bin:/bin:/usr/sbin:/sbin" ], [ user_path="/usr/bin:/bin:/usr/sbin:/sbin" ] ) # make sure $bindir is in USER_PATH so scp will work t_bindir=`eval echo ${bindir}` case $t_bindir in NONE/*) t_bindir=`echo $t_bindir | sed "s~NONE~$prefix~"` ;; esac case $t_bindir in NONE/*) t_bindir=`echo $t_bindir | sed "s~NONE~$ac_default_prefix~"` ;; esac echo $user_path | grep ":$t_bindir" > /dev/null 2>&1 if test $? -ne 0 ; then echo $user_path | grep "^$t_bindir" > /dev/null 2>&1 if test $? -ne 0 ; then user_path=$user_path:$t_bindir 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 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 ] ) # Whether to force IPv4 by default (needed on broken glibc Linux) IPV4_HACK_MSG="no" AC_ARG_WITH(ipv4-default, [ --with-ipv4-default Use IPv4 by connections unless '-6' specified], [ if test "x$withval" != "xno" ; then AC_DEFINE(IPV4_DEFAULT) IPV4_HACK_MSG="yes" fi ] ) AC_MSG_CHECKING([if we need to convert IPv4 in IPv6-mapped addresses]) IPV4_IN6_HACK_MSG="no" AC_ARG_WITH(4in6, [ --with-4in6 Check for and convert IPv4 in IPv6 mapped addresses], [ if test "x$withval" != "xno" ; then AC_MSG_RESULT(yes) AC_DEFINE(IPV4_IN_IPV6) IPV4_IN6_HACK_MSG="yes" else AC_MSG_RESULT(no) fi ],[ if test "x$inet6_default_4in6" = "xyes"; then AC_MSG_RESULT([yes (default)]) AC_DEFINE(IPV4_IN_IPV6) IPV4_IN6_HACK_MSG="yes" else AC_MSG_RESULT([no (default)]) fi ] ) # Whether to enable BSD auth support BSD_AUTH_MSG=no AC_ARG_WITH(bsd-auth, [ --with-bsd-auth Enable BSD auth support], [ if test "x$withval" != "xno" ; then AC_DEFINE(BSD_AUTH) BSD_AUTH_MSG=yes fi ] ) # 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 ] ) AC_DEFINE_UNQUOTED(_PATH_SSH_PIDDIR, "$piddir") AC_SUBST(piddir) dnl allow user to disable some login recording features AC_ARG_ENABLE(lastlog, [ --disable-lastlog disable use of lastlog even if detected [no]], [ AC_DEFINE(DISABLE_LASTLOG) ] ) AC_ARG_ENABLE(utmp, [ --disable-utmp disable use of utmp even if detected [no]], [ AC_DEFINE(DISABLE_UTMP) ] ) AC_ARG_ENABLE(utmpx, [ --disable-utmpx disable use of utmpx even if detected [no]], [ AC_DEFINE(DISABLE_UTMPX) ] ) AC_ARG_ENABLE(wtmp, [ --disable-wtmp disable use of wtmp even if detected [no]], [ AC_DEFINE(DISABLE_WTMP) ] ) AC_ARG_ENABLE(wtmpx, [ --disable-wtmpx disable use of wtmpx even if detected [no]], [ AC_DEFINE(DISABLE_WTMPX) ] ) AC_ARG_ENABLE(libutil, [ --disable-libutil disable use of libutil (login() etc.) [no]], [ AC_DEFINE(DISABLE_LOGIN) ] ) AC_ARG_ENABLE(pututline, [ --disable-pututline disable use of pututline() etc. ([uw]tmp) [no]], [ AC_DEFINE(DISABLE_PUTUTLINE) ] ) AC_ARG_ENABLE(pututxline, [ --disable-pututxline disable use of pututxline() etc. ([uw]tmpx) [no]], [ AC_DEFINE(DISABLE_PUTUTXLINE) ] ) AC_ARG_WITH(lastlog, [ --with-lastlog=FILE|DIR specify lastlog location [common locations]], [ if test "x$withval" = "xno" ; then AC_DEFINE(DISABLE_LASTLOG) else conf_lastlog_location=$withval fi ] ) dnl lastlog, [uw]tmpx? detection dnl NOTE: set the paths in the platform section to avoid the dnl need for command-line parameters dnl lastlog and [uw]tmp are subject to a file search if all else fails dnl lastlog detection dnl NOTE: the code itself will detect if lastlog is a directory AC_MSG_CHECKING([if your system defines LASTLOG_FILE]) AC_TRY_COMPILE([ #include #include #ifdef HAVE_LASTLOG_H # include #endif #ifdef HAVE_PATHS_H # include #endif #ifdef HAVE_LOGIN_H # include #endif ], [ char *lastlog = LASTLOG_FILE; ], [ AC_MSG_RESULT(yes) ], [ AC_MSG_RESULT(no) AC_MSG_CHECKING([if your system defines _PATH_LASTLOG]) AC_TRY_COMPILE([ #include #include #ifdef HAVE_LASTLOG_H # include #endif #ifdef HAVE_PATHS_H # include #endif ], [ char *lastlog = _PATH_LASTLOG; ], [ AC_MSG_RESULT(yes) ], [ AC_MSG_RESULT(no) system_lastlog_path=no ]) ] ) if test -z "$conf_lastlog_location"; then if test x"$system_lastlog_path" = x"no" ; then for f in /var/log/lastlog /usr/adm/lastlog /var/adm/lastlog /etc/security/lastlog ; do if (test -d "$f" || test -f "$f") ; then conf_lastlog_location=$f fi done if test -z "$conf_lastlog_location"; then AC_MSG_WARN([** Cannot find lastlog **]) dnl Don't define DISABLE_LASTLOG - that means we don't try wtmp/wtmpx fi fi fi if test -n "$conf_lastlog_location"; then AC_DEFINE_UNQUOTED(CONF_LASTLOG_FILE, "$conf_lastlog_location") fi dnl utmp detection AC_MSG_CHECKING([if your system defines UTMP_FILE]) AC_TRY_COMPILE([ #include #include #ifdef HAVE_PATHS_H # include #endif ], [ char *utmp = UTMP_FILE; ], [ AC_MSG_RESULT(yes) ], [ AC_MSG_RESULT(no) system_utmp_path=no ] ) if test -z "$conf_utmp_location"; then if test x"$system_utmp_path" = x"no" ; then for f in /etc/utmp /usr/adm/utmp /var/run/utmp; do if test -f $f ; then conf_utmp_location=$f fi done if test -z "$conf_utmp_location"; then AC_DEFINE(DISABLE_UTMP) fi fi fi if test -n "$conf_utmp_location"; then AC_DEFINE_UNQUOTED(CONF_UTMP_FILE, "$conf_utmp_location") fi dnl wtmp detection AC_MSG_CHECKING([if your system defines WTMP_FILE]) AC_TRY_COMPILE([ #include #include #ifdef HAVE_PATHS_H # include #endif ], [ char *wtmp = WTMP_FILE; ], [ AC_MSG_RESULT(yes) ], [ AC_MSG_RESULT(no) system_wtmp_path=no ] ) if test -z "$conf_wtmp_location"; then if test x"$system_wtmp_path" = x"no" ; then for f in /usr/adm/wtmp /var/log/wtmp; do if test -f $f ; then conf_wtmp_location=$f fi done if test -z "$conf_wtmp_location"; then AC_DEFINE(DISABLE_WTMP) fi fi fi if test -n "$conf_wtmp_location"; then AC_DEFINE_UNQUOTED(CONF_WTMP_FILE, "$conf_wtmp_location") fi dnl utmpx detection - I don't know any system so perverse as to require dnl utmpx, but not define UTMPX_FILE (ditto wtmpx.) No doubt it's out dnl there, though. AC_MSG_CHECKING([if your system defines UTMPX_FILE]) AC_TRY_COMPILE([ #include #include #ifdef HAVE_UTMPX_H #include #endif #ifdef HAVE_PATHS_H # include #endif ], [ char *utmpx = UTMPX_FILE; ], [ AC_MSG_RESULT(yes) ], [ AC_MSG_RESULT(no) system_utmpx_path=no ] ) if test -z "$conf_utmpx_location"; then if test x"$system_utmpx_path" = x"no" ; then AC_DEFINE(DISABLE_UTMPX) fi else AC_DEFINE_UNQUOTED(CONF_UTMPX_FILE, "$conf_utmpx_location") fi dnl wtmpx detection AC_MSG_CHECKING([if your system defines WTMPX_FILE]) AC_TRY_COMPILE([ #include #include #ifdef HAVE_UTMPX_H #include #endif #ifdef HAVE_PATHS_H # include #endif ], [ char *wtmpx = WTMPX_FILE; ], [ AC_MSG_RESULT(yes) ], [ AC_MSG_RESULT(no) system_wtmpx_path=no ] ) if test -z "$conf_wtmpx_location"; then if test x"$system_wtmpx_path" = x"no" ; then AC_DEFINE(DISABLE_WTMPX) fi else AC_DEFINE_UNQUOTED(CONF_WTMPX_FILE, "$conf_wtmpx_location") fi if test ! -z "$blibpath" ; then LDFLAGS="$LDFLAGS -blibpath:$blibpath" AC_MSG_WARN([Please check and edit -blibpath in LDFLAGS in Makefile]) fi dnl remove pam and dl because they are in $LIBPAM if test "$PAM_MSG" = yes ; then LIBS=`echo $LIBS | sed 's/-lpam //'` fi if test "$ac_cv_lib_pam_pam_set_item" = yes ; then LIBS=`echo $LIBS | sed 's/-ldl //'` fi AC_EXEEXT AC_CONFIG_FILES([Makefile openbsd-compat/Makefile scard/Makefile ssh_prng_cmds]) AC_OUTPUT # Print summary of options # Someone please show me a better way :) A=`eval echo ${prefix}` ; A=`eval echo ${A}` B=`eval echo ${bindir}` ; B=`eval echo ${B}` C=`eval echo ${sbindir}` ; C=`eval echo ${C}` 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 ${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 " 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 " OPIE support: $OPIE_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" fi echo "" echo " Host: ${host}" echo " Compiler: ${CC}" echo " Compiler flags: ${CFLAGS}" echo "Preprocessor flags: ${CPPFLAGS}" echo " Linker flags: ${LDFLAGS}" echo " Libraries: ${LIBWRAP} ${LIBPAM} ${LIBS}" echo "" if test "x$PAM_MSG" = "xyes" ; then echo "PAM is enabled. You may need to install a PAM control file " echo "for sshd, otherwise password authentication may fail. " echo "Example PAM control files can be found in the contrib/ " echo "subdirectory" echo "" fi if test ! -z "$NO_SFTP"; then echo "sftp-server will be disabled. Your compiler does not " echo "support 64bit integers." echo "" fi if test ! -z "$RAND_HELPER_CMDHASH" ; then echo "WARNING: you are using the builtin random number collection " echo "service. Please read WARNING.RNG and request that your OS " echo "vendor includes kernel-based random number collection in " echo "future versions of your OS." echo "" fi diff --git a/crypto/openssh/monitor.c b/crypto/openssh/monitor.c index 39b6248d44ff..1770e67ffc63 100644 --- a/crypto/openssh/monitor.c +++ b/crypto/openssh/monitor.c @@ -1,1541 +1,1550 @@ /* * Copyright 2002 Niels Provos * Copyright 2002 Markus Friedl * 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: monitor.c,v 1.16 2002/06/21 05:50:51 djm Exp $"); +RCSID("$FreeBSD$"); #include #ifdef SKEY +#ifdef OPIE +#include +#define skey opie +#define skeychallenge(k, u, c) opiechallenge((k), (u), (c)) +#define skey_haskey(u) opie_haskey((u)) +#define skey_passcheck(u, r) opie_passverify((u), (r)) +#else #include #endif +#endif #include "ssh.h" #include "auth.h" #include "kex.h" #include "dh.h" #include "zlib.h" #include "packet.h" #include "auth-options.h" #include "sshpty.h" #include "channels.h" #include "session.h" #include "sshlogin.h" #include "canohost.h" #include "log.h" #include "servconf.h" #include "monitor.h" #include "monitor_mm.h" #include "monitor_wrap.h" #include "monitor_fdpass.h" #include "xmalloc.h" #include "misc.h" #include "buffer.h" #include "bufaux.h" #include "compat.h" #include "ssh2.h" #include "mpaux.h" /* Imports */ extern ServerOptions options; extern u_int utmp_len; extern Newkeys *current_keys[]; extern z_stream incoming_stream; extern z_stream outgoing_stream; extern u_char session_id[]; extern Buffer input, output; extern Buffer auth_debug; extern int auth_debug_init; /* State exported from the child */ struct { z_stream incoming; z_stream outgoing; u_char *keyin; u_int keyinlen; u_char *keyout; u_int keyoutlen; u_char *ivin; u_int ivinlen; u_char *ivout; u_int ivoutlen; u_char *ssh1key; u_int ssh1keylen; int ssh1cipher; int ssh1protoflags; u_char *input; u_int ilen; u_char *output; u_int olen; } child_state; /* Functions on the montior that answer unprivileged requests */ int mm_answer_moduli(int, Buffer *); int mm_answer_sign(int, Buffer *); int mm_answer_pwnamallow(int, Buffer *); int mm_answer_auth2_read_banner(int, Buffer *); int mm_answer_authserv(int, Buffer *); int mm_answer_authpassword(int, Buffer *); int mm_answer_bsdauthquery(int, Buffer *); int mm_answer_bsdauthrespond(int, Buffer *); int mm_answer_skeyquery(int, Buffer *); int mm_answer_skeyrespond(int, Buffer *); int mm_answer_keyallowed(int, Buffer *); int mm_answer_keyverify(int, Buffer *); int mm_answer_pty(int, Buffer *); int mm_answer_pty_cleanup(int, Buffer *); int mm_answer_term(int, Buffer *); int mm_answer_rsa_keyallowed(int, Buffer *); int mm_answer_rsa_challenge(int, Buffer *); int mm_answer_rsa_response(int, Buffer *); int mm_answer_sesskey(int, Buffer *); int mm_answer_sessid(int, Buffer *); #ifdef USE_PAM int mm_answer_pam_start(int, Buffer *); #endif static Authctxt *authctxt; static BIGNUM *ssh1_challenge = NULL; /* used for ssh1 rsa auth */ /* local state for key verify */ static u_char *key_blob = NULL; static u_int key_bloblen = 0; static int key_blobtype = MM_NOKEY; static u_char *hostbased_cuser = NULL; static u_char *hostbased_chost = NULL; static char *auth_method = "unknown"; static int session_id2_len = 0; static u_char *session_id2 = NULL; struct mon_table { enum monitor_reqtype type; int flags; int (*f)(int, Buffer *); }; #define MON_ISAUTH 0x0004 /* Required for Authentication */ #define MON_AUTHDECIDE 0x0008 /* Decides Authentication */ #define MON_ONCE 0x0010 /* Disable after calling */ #define MON_AUTH (MON_ISAUTH|MON_AUTHDECIDE) #define MON_PERMIT 0x1000 /* Request is permitted */ struct mon_table mon_dispatch_proto20[] = { {MONITOR_REQ_MODULI, MON_ONCE, mm_answer_moduli}, {MONITOR_REQ_SIGN, MON_ONCE, mm_answer_sign}, {MONITOR_REQ_PWNAM, MON_ONCE, mm_answer_pwnamallow}, {MONITOR_REQ_AUTHSERV, MON_ONCE, mm_answer_authserv}, {MONITOR_REQ_AUTH2_READ_BANNER, MON_ONCE, mm_answer_auth2_read_banner}, {MONITOR_REQ_AUTHPASSWORD, MON_AUTH, mm_answer_authpassword}, #ifdef USE_PAM {MONITOR_REQ_PAM_START, MON_ONCE, mm_answer_pam_start}, #endif #ifdef BSD_AUTH {MONITOR_REQ_BSDAUTHQUERY, MON_ISAUTH, mm_answer_bsdauthquery}, {MONITOR_REQ_BSDAUTHRESPOND, MON_AUTH,mm_answer_bsdauthrespond}, #endif #ifdef SKEY {MONITOR_REQ_SKEYQUERY, MON_ISAUTH, mm_answer_skeyquery}, {MONITOR_REQ_SKEYRESPOND, MON_AUTH, mm_answer_skeyrespond}, #endif {MONITOR_REQ_KEYALLOWED, MON_ISAUTH, mm_answer_keyallowed}, {MONITOR_REQ_KEYVERIFY, MON_AUTH, mm_answer_keyverify}, {0, 0, NULL} }; struct mon_table mon_dispatch_postauth20[] = { {MONITOR_REQ_MODULI, 0, mm_answer_moduli}, {MONITOR_REQ_SIGN, 0, mm_answer_sign}, {MONITOR_REQ_PTY, 0, mm_answer_pty}, {MONITOR_REQ_PTYCLEANUP, 0, mm_answer_pty_cleanup}, {MONITOR_REQ_TERM, 0, mm_answer_term}, {0, 0, NULL} }; struct mon_table mon_dispatch_proto15[] = { {MONITOR_REQ_PWNAM, MON_ONCE, mm_answer_pwnamallow}, {MONITOR_REQ_SESSKEY, MON_ONCE, mm_answer_sesskey}, {MONITOR_REQ_SESSID, MON_ONCE, mm_answer_sessid}, {MONITOR_REQ_AUTHPASSWORD, MON_AUTH, mm_answer_authpassword}, {MONITOR_REQ_RSAKEYALLOWED, MON_ISAUTH, mm_answer_rsa_keyallowed}, {MONITOR_REQ_KEYALLOWED, MON_ISAUTH, mm_answer_keyallowed}, {MONITOR_REQ_RSACHALLENGE, MON_ONCE, mm_answer_rsa_challenge}, {MONITOR_REQ_RSARESPONSE, MON_ONCE|MON_AUTHDECIDE, mm_answer_rsa_response}, #ifdef USE_PAM {MONITOR_REQ_PAM_START, MON_ONCE, mm_answer_pam_start}, #endif #ifdef BSD_AUTH {MONITOR_REQ_BSDAUTHQUERY, MON_ISAUTH, mm_answer_bsdauthquery}, {MONITOR_REQ_BSDAUTHRESPOND, MON_AUTH,mm_answer_bsdauthrespond}, #endif #ifdef SKEY {MONITOR_REQ_SKEYQUERY, MON_ISAUTH, mm_answer_skeyquery}, {MONITOR_REQ_SKEYRESPOND, MON_AUTH, mm_answer_skeyrespond}, #endif #ifdef USE_PAM {MONITOR_REQ_PAM_START, MON_ONCE, mm_answer_pam_start}, #endif {0, 0, NULL} }; struct mon_table mon_dispatch_postauth15[] = { {MONITOR_REQ_PTY, MON_ONCE, mm_answer_pty}, {MONITOR_REQ_PTYCLEANUP, MON_ONCE, mm_answer_pty_cleanup}, {MONITOR_REQ_TERM, 0, mm_answer_term}, {0, 0, NULL} }; struct mon_table *mon_dispatch; /* Specifies if a certain message is allowed at the moment */ static void monitor_permit(struct mon_table *ent, enum monitor_reqtype type, int permit) { while (ent->f != NULL) { if (ent->type == type) { ent->flags &= ~MON_PERMIT; ent->flags |= permit ? MON_PERMIT : 0; return; } ent++; } } static void monitor_permit_authentications(int permit) { struct mon_table *ent = mon_dispatch; while (ent->f != NULL) { if (ent->flags & MON_AUTH) { ent->flags &= ~MON_PERMIT; ent->flags |= permit ? MON_PERMIT : 0; } ent++; } } Authctxt * monitor_child_preauth(struct monitor *pmonitor) { struct mon_table *ent; int authenticated = 0; debug3("preauth child monitor started"); if (compat20) { mon_dispatch = mon_dispatch_proto20; /* Permit requests for moduli and signatures */ monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1); monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1); } else { mon_dispatch = mon_dispatch_proto15; monitor_permit(mon_dispatch, MONITOR_REQ_SESSKEY, 1); } authctxt = authctxt_new(); /* The first few requests do not require asynchronous access */ while (!authenticated) { authenticated = monitor_read(pmonitor, mon_dispatch, &ent); if (authenticated) { if (!(ent->flags & MON_AUTHDECIDE)) fatal("%s: unexpected authentication from %d", __func__, ent->type); if (authctxt->pw->pw_uid == 0 && !auth_root_allowed(auth_method)) authenticated = 0; #ifdef USE_PAM if (!do_pam_account(authctxt->pw->pw_name, NULL)) authenticated = 0; #endif } if (ent->flags & MON_AUTHDECIDE) { auth_log(authctxt, authenticated, auth_method, compat20 ? " ssh2" : ""); if (!authenticated) authctxt->failures++; } } if (!authctxt->valid) fatal("%s: authenticated invalid user", __func__); debug("%s: %s has been authenticated by privileged process", __func__, authctxt->user); mm_get_keystate(pmonitor); return (authctxt); } void monitor_child_postauth(struct monitor *pmonitor) { if (compat20) { mon_dispatch = mon_dispatch_postauth20; /* Permit requests for moduli and signatures */ monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1); monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1); monitor_permit(mon_dispatch, MONITOR_REQ_TERM, 1); } else { mon_dispatch = mon_dispatch_postauth15; monitor_permit(mon_dispatch, MONITOR_REQ_TERM, 1); } if (!no_pty_flag) { monitor_permit(mon_dispatch, MONITOR_REQ_PTY, 1); monitor_permit(mon_dispatch, MONITOR_REQ_PTYCLEANUP, 1); } for (;;) monitor_read(pmonitor, mon_dispatch, NULL); } void monitor_sync(struct monitor *pmonitor) { if (options.compression) { /* The member allocation is not visible, so sync it */ mm_share_sync(&pmonitor->m_zlib, &pmonitor->m_zback); } } int monitor_read(struct monitor *pmonitor, struct mon_table *ent, struct mon_table **pent) { Buffer m; int ret; u_char type; buffer_init(&m); mm_request_receive(pmonitor->m_sendfd, &m); type = buffer_get_char(&m); debug3("%s: checking request %d", __func__, type); while (ent->f != NULL) { if (ent->type == type) break; ent++; } if (ent->f != NULL) { if (!(ent->flags & MON_PERMIT)) fatal("%s: unpermitted request %d", __func__, type); ret = (*ent->f)(pmonitor->m_sendfd, &m); buffer_free(&m); /* The child may use this request only once, disable it */ if (ent->flags & MON_ONCE) { debug2("%s: %d used once, disabling now", __func__, type); ent->flags &= ~MON_PERMIT; } if (pent != NULL) *pent = ent; return ret; } fatal("%s: unsupported request: %d", __func__, type); /* NOTREACHED */ return (-1); } /* allowed key state */ static int monitor_allowed_key(u_char *blob, u_int bloblen) { /* make sure key is allowed */ if (key_blob == NULL || key_bloblen != bloblen || memcmp(key_blob, blob, key_bloblen)) return (0); return (1); } static void monitor_reset_key_state(void) { /* reset state */ if (key_blob != NULL) xfree(key_blob); if (hostbased_cuser != NULL) xfree(hostbased_cuser); if (hostbased_chost != NULL) xfree(hostbased_chost); key_blob = NULL; key_bloblen = 0; key_blobtype = MM_NOKEY; hostbased_cuser = NULL; hostbased_chost = NULL; } int mm_answer_moduli(int socket, Buffer *m) { DH *dh; int min, want, max; min = buffer_get_int(m); want = buffer_get_int(m); max = buffer_get_int(m); debug3("%s: got parameters: %d %d %d", __func__, min, want, max); /* We need to check here, too, in case the child got corrupted */ if (max < min || want < min || max < want) fatal("%s: bad parameters: %d %d %d", __func__, min, want, max); buffer_clear(m); dh = choose_dh(min, want, max); if (dh == NULL) { buffer_put_char(m, 0); return (0); } else { /* Send first bignum */ buffer_put_char(m, 1); buffer_put_bignum2(m, dh->p); buffer_put_bignum2(m, dh->g); DH_free(dh); } mm_request_send(socket, MONITOR_ANS_MODULI, m); return (0); } int mm_answer_sign(int socket, Buffer *m) { Key *key; u_char *p; u_char *signature; u_int siglen, datlen; int keyid; debug3("%s", __func__); keyid = buffer_get_int(m); p = buffer_get_string(m, &datlen); if (datlen != 20) fatal("%s: data length incorrect: %d", __func__, datlen); /* save session id, it will be passed on the first call */ if (session_id2_len == 0) { session_id2_len = datlen; session_id2 = xmalloc(session_id2_len); memcpy(session_id2, p, session_id2_len); } if ((key = get_hostkey_by_index(keyid)) == NULL) fatal("%s: no hostkey from index %d", __func__, keyid); if (key_sign(key, &signature, &siglen, p, datlen) < 0) fatal("%s: key_sign failed", __func__); debug3("%s: signature %p(%d)", __func__, signature, siglen); buffer_clear(m); buffer_put_string(m, signature, siglen); xfree(p); xfree(signature); mm_request_send(socket, MONITOR_ANS_SIGN, m); /* Turn on permissions for getpwnam */ monitor_permit(mon_dispatch, MONITOR_REQ_PWNAM, 1); return (0); } /* Retrieves the password entry and also checks if the user is permitted */ int mm_answer_pwnamallow(int socket, Buffer *m) { char *login; struct passwd *pwent; int allowed = 0; debug3("%s", __func__); if (authctxt->attempt++ != 0) fatal("%s: multiple attempts for getpwnam", __func__); login = buffer_get_string(m, NULL); pwent = getpwnamallow(login); authctxt->user = xstrdup(login); setproctitle("%s [priv]", pwent ? login : "unknown"); xfree(login); buffer_clear(m); if (pwent == NULL) { buffer_put_char(m, 0); goto out; } allowed = 1; authctxt->pw = pwent; authctxt->valid = 1; buffer_put_char(m, 1); buffer_put_string(m, pwent, sizeof(struct passwd)); buffer_put_cstring(m, pwent->pw_name); buffer_put_cstring(m, "*"); buffer_put_cstring(m, pwent->pw_gecos); #ifdef HAVE_PW_CLASS_IN_PASSWD buffer_put_cstring(m, pwent->pw_class); #endif buffer_put_cstring(m, pwent->pw_dir); buffer_put_cstring(m, pwent->pw_shell); out: debug3("%s: sending MONITOR_ANS_PWNAM: %d", __func__, allowed); mm_request_send(socket, MONITOR_ANS_PWNAM, m); /* For SSHv1 allow authentication now */ if (!compat20) monitor_permit_authentications(1); else { /* Allow service/style information on the auth context */ monitor_permit(mon_dispatch, MONITOR_REQ_AUTHSERV, 1); monitor_permit(mon_dispatch, MONITOR_REQ_AUTH2_READ_BANNER, 1); } #ifdef USE_PAM monitor_permit(mon_dispatch, MONITOR_REQ_PAM_START, 1); #endif return (0); } int mm_answer_auth2_read_banner(int socket, Buffer *m) { char *banner; buffer_clear(m); banner = auth2_read_banner(); buffer_put_cstring(m, banner != NULL ? banner : ""); mm_request_send(socket, MONITOR_ANS_AUTH2_READ_BANNER, m); if (banner != NULL) free(banner); return (0); } int mm_answer_authserv(int socket, Buffer *m) { monitor_permit_authentications(1); authctxt->service = buffer_get_string(m, NULL); authctxt->style = buffer_get_string(m, NULL); debug3("%s: service=%s, style=%s", __func__, authctxt->service, authctxt->style); if (strlen(authctxt->style) == 0) { xfree(authctxt->style); authctxt->style = NULL; } return (0); } int mm_answer_authpassword(int socket, Buffer *m) { static int call_count; char *passwd; int authenticated, plen; passwd = buffer_get_string(m, &plen); /* Only authenticate if the context is valid */ authenticated = options.password_authentication && authctxt->valid && auth_password(authctxt, passwd); memset(passwd, 0, strlen(passwd)); xfree(passwd); buffer_clear(m); buffer_put_int(m, authenticated); debug3("%s: sending result %d", __func__, authenticated); mm_request_send(socket, MONITOR_ANS_AUTHPASSWORD, m); call_count++; if (plen == 0 && call_count == 1) auth_method = "none"; else auth_method = "password"; /* Causes monitor loop to terminate if authenticated */ return (authenticated); } #ifdef BSD_AUTH int mm_answer_bsdauthquery(int socket, Buffer *m) { char *name, *infotxt; u_int numprompts; u_int *echo_on; char **prompts; int res; res = bsdauth_query(authctxt, &name, &infotxt, &numprompts, &prompts, &echo_on); buffer_clear(m); buffer_put_int(m, res); if (res != -1) buffer_put_cstring(m, prompts[0]); debug3("%s: sending challenge res: %d", __func__, res); mm_request_send(socket, MONITOR_ANS_BSDAUTHQUERY, m); if (res != -1) { xfree(name); xfree(infotxt); xfree(prompts); xfree(echo_on); } return (0); } int mm_answer_bsdauthrespond(int socket, Buffer *m) { char *response; int authok; if (authctxt->as == 0) fatal("%s: no bsd auth session", __func__); response = buffer_get_string(m, NULL); authok = options.challenge_response_authentication && auth_userresponse(authctxt->as, response, 0); authctxt->as = NULL; debug3("%s: <%s> = <%d>", __func__, response, authok); xfree(response); buffer_clear(m); buffer_put_int(m, authok); debug3("%s: sending authenticated: %d", __func__, authok); mm_request_send(socket, MONITOR_ANS_BSDAUTHRESPOND, m); auth_method = "bsdauth"; return (authok != 0); } #endif #ifdef SKEY int mm_answer_skeyquery(int socket, Buffer *m) { struct skey skey; char challenge[1024]; int res; res = skeychallenge(&skey, authctxt->user, challenge); buffer_clear(m); buffer_put_int(m, res); if (res != -1) buffer_put_cstring(m, challenge); debug3("%s: sending challenge res: %d", __func__, res); mm_request_send(socket, MONITOR_ANS_SKEYQUERY, m); return (0); } int mm_answer_skeyrespond(int socket, Buffer *m) { char *response; int authok; response = buffer_get_string(m, NULL); authok = (options.challenge_response_authentication && authctxt->valid && skey_haskey(authctxt->pw->pw_name) == 0 && skey_passcheck(authctxt->pw->pw_name, response) != -1); xfree(response); buffer_clear(m); buffer_put_int(m, authok); debug3("%s: sending authenticated: %d", __func__, authok); mm_request_send(socket, MONITOR_ANS_SKEYRESPOND, m); auth_method = "skey"; return (authok != 0); } #endif #ifdef USE_PAM int mm_answer_pam_start(int socket, Buffer *m) { char *user; user = buffer_get_string(m, NULL); start_pam(user); xfree(user); return (0); } #endif static void mm_append_debug(Buffer *m) { if (auth_debug_init && buffer_len(&auth_debug)) { debug3("%s: Appending debug messages for child", __func__); buffer_append(m, buffer_ptr(&auth_debug), buffer_len(&auth_debug)); buffer_clear(&auth_debug); } } int mm_answer_keyallowed(int socket, Buffer *m) { Key *key; u_char *cuser, *chost, *blob; u_int bloblen; enum mm_keytype type = 0; int allowed = 0; debug3("%s entering", __func__); type = buffer_get_int(m); cuser = buffer_get_string(m, NULL); chost = buffer_get_string(m, NULL); blob = buffer_get_string(m, &bloblen); key = key_from_blob(blob, bloblen); if ((compat20 && type == MM_RSAHOSTKEY) || (!compat20 && type != MM_RSAHOSTKEY)) fatal("%s: key type and protocol mismatch", __func__); debug3("%s: key_from_blob: %p", __func__, key); if (key != NULL && authctxt->pw != NULL) { switch(type) { case MM_USERKEY: allowed = options.pubkey_authentication && user_key_allowed(authctxt->pw, key); break; case MM_HOSTKEY: allowed = options.hostbased_authentication && hostbased_key_allowed(authctxt->pw, cuser, chost, key); break; case MM_RSAHOSTKEY: key->type = KEY_RSA1; /* XXX */ allowed = options.rhosts_rsa_authentication && auth_rhosts_rsa_key_allowed(authctxt->pw, cuser, chost, key); break; default: fatal("%s: unknown key type %d", __func__, type); break; } key_free(key); } /* clear temporarily storage (used by verify) */ monitor_reset_key_state(); if (allowed) { /* Save temporarily for comparison in verify */ key_blob = blob; key_bloblen = bloblen; key_blobtype = type; hostbased_cuser = cuser; hostbased_chost = chost; } debug3("%s: key %p is %s", __func__, key, allowed ? "allowed" : "disallowed"); buffer_clear(m); buffer_put_int(m, allowed); mm_append_debug(m); mm_request_send(socket, MONITOR_ANS_KEYALLOWED, m); if (type == MM_RSAHOSTKEY) monitor_permit(mon_dispatch, MONITOR_REQ_RSACHALLENGE, allowed); return (0); } static int monitor_valid_userblob(u_char *data, u_int datalen) { Buffer b; u_char *p; u_int len; int fail = 0; buffer_init(&b); buffer_append(&b, data, datalen); if (datafellows & SSH_OLD_SESSIONID) { p = buffer_ptr(&b); len = buffer_len(&b); if ((session_id2 == NULL) || (len < session_id2_len) || (memcmp(p, session_id2, session_id2_len) != 0)) fail++; buffer_consume(&b, session_id2_len); } else { p = buffer_get_string(&b, &len); if ((session_id2 == NULL) || (len != session_id2_len) || (memcmp(p, session_id2, session_id2_len) != 0)) fail++; xfree(p); } if (buffer_get_char(&b) != SSH2_MSG_USERAUTH_REQUEST) fail++; p = buffer_get_string(&b, NULL); if (strcmp(authctxt->user, p) != 0) { log("wrong user name passed to monitor: expected %s != %.100s", authctxt->user, p); fail++; } xfree(p); buffer_skip_string(&b); if (datafellows & SSH_BUG_PKAUTH) { if (!buffer_get_char(&b)) fail++; } else { p = buffer_get_string(&b, NULL); if (strcmp("publickey", p) != 0) fail++; xfree(p); if (!buffer_get_char(&b)) fail++; buffer_skip_string(&b); } buffer_skip_string(&b); if (buffer_len(&b) != 0) fail++; buffer_free(&b); return (fail == 0); } static int monitor_valid_hostbasedblob(u_char *data, u_int datalen, u_char *cuser, u_char *chost) { Buffer b; u_char *p; u_int len; int fail = 0; buffer_init(&b); buffer_append(&b, data, datalen); p = buffer_get_string(&b, &len); if ((session_id2 == NULL) || (len != session_id2_len) || (memcmp(p, session_id2, session_id2_len) != 0)) fail++; xfree(p); if (buffer_get_char(&b) != SSH2_MSG_USERAUTH_REQUEST) fail++; p = buffer_get_string(&b, NULL); if (strcmp(authctxt->user, p) != 0) { log("wrong user name passed to monitor: expected %s != %.100s", authctxt->user, p); fail++; } xfree(p); buffer_skip_string(&b); /* service */ p = buffer_get_string(&b, NULL); if (strcmp(p, "hostbased") != 0) fail++; xfree(p); buffer_skip_string(&b); /* pkalg */ buffer_skip_string(&b); /* pkblob */ /* verify client host, strip trailing dot if necessary */ p = buffer_get_string(&b, NULL); if (((len = strlen(p)) > 0) && p[len - 1] == '.') p[len - 1] = '\0'; if (strcmp(p, chost) != 0) fail++; xfree(p); /* verify client user */ p = buffer_get_string(&b, NULL); if (strcmp(p, cuser) != 0) fail++; xfree(p); if (buffer_len(&b) != 0) fail++; buffer_free(&b); return (fail == 0); } int mm_answer_keyverify(int socket, Buffer *m) { Key *key; u_char *signature, *data, *blob; u_int signaturelen, datalen, bloblen; int verified = 0; int valid_data = 0; blob = buffer_get_string(m, &bloblen); signature = buffer_get_string(m, &signaturelen); data = buffer_get_string(m, &datalen); if (hostbased_cuser == NULL || hostbased_chost == NULL || !monitor_allowed_key(blob, bloblen)) fatal("%s: bad key, not previously allowed", __func__); key = key_from_blob(blob, bloblen); if (key == NULL) fatal("%s: bad public key blob", __func__); switch (key_blobtype) { case MM_USERKEY: valid_data = monitor_valid_userblob(data, datalen); break; case MM_HOSTKEY: valid_data = monitor_valid_hostbasedblob(data, datalen, hostbased_cuser, hostbased_chost); break; default: valid_data = 0; break; } if (!valid_data) fatal("%s: bad signature data blob", __func__); verified = key_verify(key, signature, signaturelen, data, datalen); debug3("%s: key %p signature %s", __func__, key, verified ? "verified" : "unverified"); key_free(key); xfree(blob); xfree(signature); xfree(data); monitor_reset_key_state(); buffer_clear(m); buffer_put_int(m, verified); mm_request_send(socket, MONITOR_ANS_KEYVERIFY, m); auth_method = key_blobtype == MM_USERKEY ? "publickey" : "hostbased"; return (verified); } static void mm_record_login(Session *s, struct passwd *pw) { socklen_t fromlen; struct sockaddr_storage from; /* * Get IP address of client. If the connection is not a socket, let * the address be 0.0.0.0. */ memset(&from, 0, sizeof(from)); if (packet_connection_is_on_socket()) { fromlen = sizeof(from); if (getpeername(packet_get_connection_in(), (struct sockaddr *) & from, &fromlen) < 0) { debug("getpeername: %.100s", strerror(errno)); fatal_cleanup(); } } /* Record that there was a login on that tty from the remote host. */ record_login(s->pid, s->tty, pw->pw_name, pw->pw_uid, get_remote_name_or_ip(utmp_len, options.verify_reverse_mapping), (struct sockaddr *)&from); } static void mm_session_close(Session *s) { debug3("%s: session %d pid %d", __func__, s->self, s->pid); if (s->ttyfd != -1) { debug3("%s: tty %s ptyfd %d", __func__, s->tty, s->ptyfd); fatal_remove_cleanup(session_pty_cleanup2, (void *)s); session_pty_cleanup2(s); } s->used = 0; } int mm_answer_pty(int socket, Buffer *m) { extern struct monitor *pmonitor; Session *s; int res, fd0; debug3("%s entering", __func__); buffer_clear(m); s = session_new(); if (s == NULL) goto error; s->authctxt = authctxt; s->pw = authctxt->pw; s->pid = pmonitor->m_pid; res = pty_allocate(&s->ptyfd, &s->ttyfd, s->tty, sizeof(s->tty)); if (res == 0) goto error; fatal_add_cleanup(session_pty_cleanup2, (void *)s); pty_setowner(authctxt->pw, s->tty); buffer_put_int(m, 1); buffer_put_cstring(m, s->tty); mm_request_send(socket, MONITOR_ANS_PTY, m); mm_send_fd(socket, s->ptyfd); mm_send_fd(socket, s->ttyfd); /* We need to trick ttyslot */ if (dup2(s->ttyfd, 0) == -1) fatal("%s: dup2", __func__); mm_record_login(s, authctxt->pw); /* Now we can close the file descriptor again */ close(0); /* make sure nothing uses fd 0 */ if ((fd0 = open(_PATH_DEVNULL, O_RDONLY)) < 0) fatal("%s: open(/dev/null): %s", __func__, strerror(errno)); if (fd0 != 0) error("%s: fd0 %d != 0", __func__, fd0); /* slave is not needed */ close(s->ttyfd); s->ttyfd = s->ptyfd; /* no need to dup() because nobody closes ptyfd */ s->ptymaster = s->ptyfd; debug3("%s: tty %s ptyfd %d", __func__, s->tty, s->ttyfd); return (0); error: if (s != NULL) mm_session_close(s); buffer_put_int(m, 0); mm_request_send(socket, MONITOR_ANS_PTY, m); return (0); } int mm_answer_pty_cleanup(int socket, Buffer *m) { Session *s; char *tty; debug3("%s entering", __func__); tty = buffer_get_string(m, NULL); if ((s = session_by_tty(tty)) != NULL) mm_session_close(s); buffer_clear(m); xfree(tty); return (0); } int mm_answer_sesskey(int socket, Buffer *m) { BIGNUM *p; int rsafail; /* Turn off permissions */ monitor_permit(mon_dispatch, MONITOR_REQ_SESSKEY, 1); if ((p = BN_new()) == NULL) fatal("%s: BN_new", __func__); buffer_get_bignum2(m, p); rsafail = ssh1_session_key(p); buffer_clear(m); buffer_put_int(m, rsafail); buffer_put_bignum2(m, p); BN_clear_free(p); mm_request_send(socket, MONITOR_ANS_SESSKEY, m); /* Turn on permissions for sessid passing */ monitor_permit(mon_dispatch, MONITOR_REQ_SESSID, 1); return (0); } int mm_answer_sessid(int socket, Buffer *m) { int i; debug3("%s entering", __func__); if (buffer_len(m) != 16) fatal("%s: bad ssh1 session id", __func__); for (i = 0; i < 16; i++) session_id[i] = buffer_get_char(m); /* Turn on permissions for getpwnam */ monitor_permit(mon_dispatch, MONITOR_REQ_PWNAM, 1); return (0); } int mm_answer_rsa_keyallowed(int socket, Buffer *m) { BIGNUM *client_n; Key *key = NULL; u_char *blob = NULL; u_int blen = 0; int allowed = 0; debug3("%s entering", __func__); if (options.rsa_authentication && authctxt->valid) { if ((client_n = BN_new()) == NULL) fatal("%s: BN_new", __func__); buffer_get_bignum2(m, client_n); allowed = auth_rsa_key_allowed(authctxt->pw, client_n, &key); BN_clear_free(client_n); } buffer_clear(m); buffer_put_int(m, allowed); /* clear temporarily storage (used by generate challenge) */ monitor_reset_key_state(); if (allowed && key != NULL) { key->type = KEY_RSA; /* cheat for key_to_blob */ if (key_to_blob(key, &blob, &blen) == 0) fatal("%s: key_to_blob failed", __func__); buffer_put_string(m, blob, blen); /* Save temporarily for comparison in verify */ key_blob = blob; key_bloblen = blen; key_blobtype = MM_RSAUSERKEY; key_free(key); } mm_append_debug(m); mm_request_send(socket, MONITOR_ANS_RSAKEYALLOWED, m); monitor_permit(mon_dispatch, MONITOR_REQ_RSACHALLENGE, allowed); monitor_permit(mon_dispatch, MONITOR_REQ_RSARESPONSE, 0); return (0); } int mm_answer_rsa_challenge(int socket, Buffer *m) { Key *key = NULL; u_char *blob; u_int blen; debug3("%s entering", __func__); if (!authctxt->valid) fatal("%s: authctxt not valid", __func__); blob = buffer_get_string(m, &blen); if (!monitor_allowed_key(blob, blen)) fatal("%s: bad key, not previously allowed", __func__); if (key_blobtype != MM_RSAUSERKEY && key_blobtype != MM_RSAHOSTKEY) fatal("%s: key type mismatch", __func__); if ((key = key_from_blob(blob, blen)) == NULL) fatal("%s: received bad key", __func__); if (ssh1_challenge) BN_clear_free(ssh1_challenge); ssh1_challenge = auth_rsa_generate_challenge(key); buffer_clear(m); buffer_put_bignum2(m, ssh1_challenge); debug3("%s sending reply", __func__); mm_request_send(socket, MONITOR_ANS_RSACHALLENGE, m); monitor_permit(mon_dispatch, MONITOR_REQ_RSARESPONSE, 1); return (0); } int mm_answer_rsa_response(int socket, Buffer *m) { Key *key = NULL; u_char *blob, *response; u_int blen, len; int success; debug3("%s entering", __func__); if (!authctxt->valid) fatal("%s: authctxt not valid", __func__); if (ssh1_challenge == NULL) fatal("%s: no ssh1_challenge", __func__); blob = buffer_get_string(m, &blen); if (!monitor_allowed_key(blob, blen)) fatal("%s: bad key, not previously allowed", __func__); if (key_blobtype != MM_RSAUSERKEY && key_blobtype != MM_RSAHOSTKEY) fatal("%s: key type mismatch: %d", __func__, key_blobtype); if ((key = key_from_blob(blob, blen)) == NULL) fatal("%s: received bad key", __func__); response = buffer_get_string(m, &len); if (len != 16) fatal("%s: received bad response to challenge", __func__); success = auth_rsa_verify_response(key, ssh1_challenge, response); key_free(key); xfree(response); auth_method = key_blobtype == MM_RSAUSERKEY ? "rsa" : "rhosts-rsa"; /* reset state */ BN_clear_free(ssh1_challenge); ssh1_challenge = NULL; monitor_reset_key_state(); buffer_clear(m); buffer_put_int(m, success); mm_request_send(socket, MONITOR_ANS_RSARESPONSE, m); return (success); } int mm_answer_term(int socket, Buffer *req) { extern struct monitor *pmonitor; int res, status; debug3("%s: tearing down sessions", __func__); /* The child is terminating */ session_destroy_all(&mm_session_close); while (waitpid(pmonitor->m_pid, &status, 0) == -1) if (errno != EINTR) exit(1); res = WIFEXITED(status) ? WEXITSTATUS(status) : 1; /* Terminate process */ exit (res); } void monitor_apply_keystate(struct monitor *pmonitor) { if (compat20) { set_newkeys(MODE_IN); set_newkeys(MODE_OUT); } else { packet_set_protocol_flags(child_state.ssh1protoflags); packet_set_encryption_key(child_state.ssh1key, child_state.ssh1keylen, child_state.ssh1cipher); xfree(child_state.ssh1key); } /* for rc4 and other stateful ciphers */ packet_set_keycontext(MODE_OUT, child_state.keyout); xfree(child_state.keyout); packet_set_keycontext(MODE_IN, child_state.keyin); xfree(child_state.keyin); if (!compat20) { packet_set_iv(MODE_OUT, child_state.ivout); xfree(child_state.ivout); packet_set_iv(MODE_IN, child_state.ivin); xfree(child_state.ivin); } memcpy(&incoming_stream, &child_state.incoming, sizeof(incoming_stream)); memcpy(&outgoing_stream, &child_state.outgoing, sizeof(outgoing_stream)); /* Update with new address */ if (options.compression) mm_init_compression(pmonitor->m_zlib); /* Network I/O buffers */ /* XXX inefficient for large buffers, need: buffer_init_from_string */ buffer_clear(&input); buffer_append(&input, child_state.input, child_state.ilen); memset(child_state.input, 0, child_state.ilen); xfree(child_state.input); buffer_clear(&output); buffer_append(&output, child_state.output, child_state.olen); memset(child_state.output, 0, child_state.olen); xfree(child_state.output); } static Kex * mm_get_kex(Buffer *m) { Kex *kex; void *blob; u_int bloblen; kex = xmalloc(sizeof(*kex)); memset(kex, 0, sizeof(*kex)); kex->session_id = buffer_get_string(m, &kex->session_id_len); if ((session_id2 == NULL) || (kex->session_id_len != session_id2_len) || (memcmp(kex->session_id, session_id2, session_id2_len) != 0)) fatal("mm_get_get: internal error: bad session id"); kex->we_need = buffer_get_int(m); kex->server = 1; kex->hostkey_type = buffer_get_int(m); kex->kex_type = buffer_get_int(m); blob = buffer_get_string(m, &bloblen); buffer_init(&kex->my); buffer_append(&kex->my, blob, bloblen); xfree(blob); blob = buffer_get_string(m, &bloblen); buffer_init(&kex->peer); buffer_append(&kex->peer, blob, bloblen); xfree(blob); kex->done = 1; kex->flags = buffer_get_int(m); kex->client_version_string = buffer_get_string(m, NULL); kex->server_version_string = buffer_get_string(m, NULL); kex->load_host_key=&get_hostkey_by_type; kex->host_key_index=&get_hostkey_index; return (kex); } /* This function requries careful sanity checking */ void mm_get_keystate(struct monitor *pmonitor) { Buffer m; u_char *blob, *p; u_int bloblen, plen; debug3("%s: Waiting for new keys", __func__); buffer_init(&m); mm_request_receive_expect(pmonitor->m_sendfd, MONITOR_REQ_KEYEXPORT, &m); if (!compat20) { child_state.ssh1protoflags = buffer_get_int(&m); child_state.ssh1cipher = buffer_get_int(&m); child_state.ssh1key = buffer_get_string(&m, &child_state.ssh1keylen); child_state.ivout = buffer_get_string(&m, &child_state.ivoutlen); child_state.ivin = buffer_get_string(&m, &child_state.ivinlen); goto skip; } else { /* Get the Kex for rekeying */ *pmonitor->m_pkex = mm_get_kex(&m); } blob = buffer_get_string(&m, &bloblen); current_keys[MODE_OUT] = mm_newkeys_from_blob(blob, bloblen); xfree(blob); debug3("%s: Waiting for second key", __func__); blob = buffer_get_string(&m, &bloblen); current_keys[MODE_IN] = mm_newkeys_from_blob(blob, bloblen); xfree(blob); /* Now get sequence numbers for the packets */ packet_set_seqnr(MODE_OUT, buffer_get_int(&m)); packet_set_seqnr(MODE_IN, buffer_get_int(&m)); skip: /* Get the key context */ child_state.keyout = buffer_get_string(&m, &child_state.keyoutlen); child_state.keyin = buffer_get_string(&m, &child_state.keyinlen); debug3("%s: Getting compression state", __func__); /* Get compression state */ p = buffer_get_string(&m, &plen); if (plen != sizeof(child_state.outgoing)) fatal("%s: bad request size", __func__); memcpy(&child_state.outgoing, p, sizeof(child_state.outgoing)); xfree(p); p = buffer_get_string(&m, &plen); if (plen != sizeof(child_state.incoming)) fatal("%s: bad request size", __func__); memcpy(&child_state.incoming, p, sizeof(child_state.incoming)); xfree(p); /* Network I/O buffers */ debug3("%s: Getting Network I/O buffers", __func__); child_state.input = buffer_get_string(&m, &child_state.ilen); child_state.output = buffer_get_string(&m, &child_state.olen); buffer_free(&m); } /* Allocation functions for zlib */ void * mm_zalloc(struct mm_master *mm, u_int ncount, u_int size) { void *address; address = mm_malloc(mm, size * ncount); return (address); } void mm_zfree(struct mm_master *mm, void *address) { mm_free(mm, address); } void mm_init_compression(struct mm_master *mm) { outgoing_stream.zalloc = (alloc_func)mm_zalloc; outgoing_stream.zfree = (free_func)mm_zfree; outgoing_stream.opaque = mm; incoming_stream.zalloc = (alloc_func)mm_zalloc; incoming_stream.zfree = (free_func)mm_zfree; incoming_stream.opaque = mm; } /* XXX */ #define FD_CLOSEONEXEC(x) do { \ if (fcntl(x, F_SETFD, 1) == -1) \ fatal("fcntl(%d, F_SETFD)", x); \ } while (0) static void monitor_socketpair(int *pair) { #ifdef HAVE_SOCKETPAIR if (socketpair(AF_UNIX, SOCK_STREAM, 0, pair) == -1) fatal("%s: socketpair", __func__); #else fatal("%s: UsePrivilegeSeparation=yes not supported", __func__); #endif FD_CLOSEONEXEC(pair[0]); FD_CLOSEONEXEC(pair[1]); } #define MM_MEMSIZE 65536 struct monitor * monitor_init(void) { struct monitor *mon; int pair[2]; mon = xmalloc(sizeof(*mon)); monitor_socketpair(pair); mon->m_recvfd = pair[0]; mon->m_sendfd = pair[1]; /* Used to share zlib space across processes */ if (options.compression) { mon->m_zback = mm_create(NULL, MM_MEMSIZE); mon->m_zlib = mm_create(mon->m_zback, 20 * MM_MEMSIZE); /* Compression needs to share state across borders */ mm_init_compression(mon->m_zlib); } return mon; } void monitor_reinit(struct monitor *mon) { int pair[2]; monitor_socketpair(pair); mon->m_recvfd = pair[0]; mon->m_sendfd = pair[1]; } diff --git a/crypto/openssh/monitor_wrap.c b/crypto/openssh/monitor_wrap.c index f7e332d8ed41..9b740ac19102 100644 --- a/crypto/openssh/monitor_wrap.c +++ b/crypto/openssh/monitor_wrap.c @@ -1,939 +1,941 @@ /* * Copyright 2002 Niels Provos * Copyright 2002 Markus Friedl * 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: monitor_wrap.c,v 1.11 2002/06/19 18:01:00 markus Exp $"); #include #include #include "ssh.h" #include "dh.h" #include "kex.h" #include "auth.h" #include "buffer.h" #include "bufaux.h" #include "packet.h" #include "mac.h" #include "log.h" #include "zlib.h" #include "monitor.h" #include "monitor_wrap.h" #include "xmalloc.h" #include "atomicio.h" #include "monitor_fdpass.h" #include "getput.h" #include "auth.h" #include "channels.h" #include "session.h" /* Imports */ extern int compat20; extern Newkeys *newkeys[]; extern z_stream incoming_stream; extern z_stream outgoing_stream; extern struct monitor *pmonitor; extern Buffer input, output; void mm_request_send(int socket, enum monitor_reqtype type, Buffer *m) { u_char buf[5]; u_int mlen = buffer_len(m); debug3("%s entering: type %d", __func__, type); PUT_32BIT(buf, mlen + 1); buf[4] = (u_char) type; /* 1st byte of payload is mesg-type */ if (atomicio(write, socket, buf, sizeof(buf)) != sizeof(buf)) fatal("%s: write", __func__); if (atomicio(write, socket, buffer_ptr(m), mlen) != mlen) fatal("%s: write", __func__); } void mm_request_receive(int socket, Buffer *m) { u_char buf[4]; ssize_t res; u_int msg_len; debug3("%s entering", __func__); res = atomicio(read, socket, buf, sizeof(buf)); if (res != sizeof(buf)) { if (res == 0) fatal_cleanup(); fatal("%s: read: %ld", __func__, (long)res); } msg_len = GET_32BIT(buf); if (msg_len > 256 * 1024) fatal("%s: read: bad msg_len %d", __func__, msg_len); buffer_clear(m); buffer_append_space(m, msg_len); res = atomicio(read, socket, buffer_ptr(m), msg_len); if (res != msg_len) fatal("%s: read: %ld != msg_len", __func__, (long)res); } void mm_request_receive_expect(int socket, enum monitor_reqtype type, Buffer *m) { u_char rtype; debug3("%s entering: type %d", __func__, type); mm_request_receive(socket, m); rtype = buffer_get_char(m); if (rtype != type) fatal("%s: read: rtype %d != type %d", __func__, rtype, type); } DH * mm_choose_dh(int min, int nbits, int max) { BIGNUM *p, *g; int success = 0; Buffer m; buffer_init(&m); buffer_put_int(&m, min); buffer_put_int(&m, nbits); buffer_put_int(&m, max); mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_MODULI, &m); debug3("%s: waiting for MONITOR_ANS_MODULI", __func__); mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_MODULI, &m); success = buffer_get_char(&m); if (success == 0) fatal("%s: MONITOR_ANS_MODULI failed", __func__); if ((p = BN_new()) == NULL) fatal("%s: BN_new failed", __func__); if ((g = BN_new()) == NULL) fatal("%s: BN_new failed", __func__); buffer_get_bignum2(&m, p); buffer_get_bignum2(&m, g); debug3("%s: remaining %d", __func__, buffer_len(&m)); buffer_free(&m); return (dh_new_group(g, p)); } int mm_key_sign(Key *key, u_char **sigp, u_int *lenp, u_char *data, u_int datalen) { Kex *kex = *pmonitor->m_pkex; Buffer m; debug3("%s entering", __func__); buffer_init(&m); buffer_put_int(&m, kex->host_key_index(key)); buffer_put_string(&m, data, datalen); mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_SIGN, &m); debug3("%s: waiting for MONITOR_ANS_SIGN", __func__); mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_SIGN, &m); *sigp = buffer_get_string(&m, lenp); buffer_free(&m); return (0); } struct passwd * mm_getpwnamallow(const char *login) { Buffer m; struct passwd *pw; u_int pwlen; debug3("%s entering", __func__); buffer_init(&m); buffer_put_cstring(&m, login); mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PWNAM, &m); debug3("%s: waiting for MONITOR_ANS_PWNAM", __func__); mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PWNAM, &m); if (buffer_get_char(&m) == 0) { buffer_free(&m); return (NULL); } pw = buffer_get_string(&m, &pwlen); if (pwlen != sizeof(struct passwd)) fatal("%s: struct passwd size mismatch", __func__); pw->pw_name = buffer_get_string(&m, NULL); pw->pw_passwd = buffer_get_string(&m, NULL); pw->pw_gecos = buffer_get_string(&m, NULL); #ifdef HAVE_PW_CLASS_IN_PASSWD pw->pw_class = buffer_get_string(&m, NULL); #endif pw->pw_dir = buffer_get_string(&m, NULL); pw->pw_shell = buffer_get_string(&m, NULL); buffer_free(&m); return (pw); } char* mm_auth2_read_banner(void) { Buffer m; char *banner; debug3("%s entering", __func__); buffer_init(&m); mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUTH2_READ_BANNER, &m); buffer_clear(&m); mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_AUTH2_READ_BANNER, &m); banner = buffer_get_string(&m, NULL); buffer_free(&m); return (banner); } /* Inform the privileged process about service and style */ void mm_inform_authserv(char *service, char *style) { Buffer m; debug3("%s entering", __func__); buffer_init(&m); buffer_put_cstring(&m, service); buffer_put_cstring(&m, style ? style : ""); mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUTHSERV, &m); buffer_free(&m); } /* Do the password authentication */ int mm_auth_password(Authctxt *authctxt, char *password) { Buffer m; int authenticated = 0; debug3("%s entering", __func__); buffer_init(&m); buffer_put_cstring(&m, password); mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUTHPASSWORD, &m); debug3("%s: waiting for MONITOR_ANS_AUTHPASSWORD", __func__); mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_AUTHPASSWORD, &m); authenticated = buffer_get_int(&m); buffer_free(&m); debug3("%s: user %sauthenticated", __func__, authenticated ? "" : "not "); return (authenticated); } int mm_user_key_allowed(struct passwd *pw, Key *key) { return (mm_key_allowed(MM_USERKEY, NULL, NULL, key)); } int mm_hostbased_key_allowed(struct passwd *pw, char *user, char *host, Key *key) { return (mm_key_allowed(MM_HOSTKEY, user, host, key)); } int mm_auth_rhosts_rsa_key_allowed(struct passwd *pw, char *user, char *host, Key *key) { int ret; key->type = KEY_RSA; /* XXX hack for key_to_blob */ ret = mm_key_allowed(MM_RSAHOSTKEY, user, host, key); key->type = KEY_RSA1; return (ret); } static void mm_send_debug(Buffer *m) { char *msg; while (buffer_len(m)) { msg = buffer_get_string(m, NULL); debug3("%s: Sending debug: %s", __func__, msg); packet_send_debug("%s", msg); xfree(msg); } } int mm_key_allowed(enum mm_keytype type, char *user, char *host, Key *key) { Buffer m; u_char *blob; u_int len; int allowed = 0; debug3("%s entering", __func__); /* Convert the key to a blob and the pass it over */ if (!key_to_blob(key, &blob, &len)) return (0); buffer_init(&m); buffer_put_int(&m, type); buffer_put_cstring(&m, user ? user : ""); buffer_put_cstring(&m, host ? host : ""); buffer_put_string(&m, blob, len); xfree(blob); mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_KEYALLOWED, &m); debug3("%s: waiting for MONITOR_ANS_KEYALLOWED", __func__); mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_KEYALLOWED, &m); allowed = buffer_get_int(&m); /* Send potential debug messages */ mm_send_debug(&m); buffer_free(&m); return (allowed); } /* * This key verify needs to send the key type along, because the * privileged parent makes the decision if the key is allowed * for authentication. */ int mm_key_verify(Key *key, u_char *sig, u_int siglen, u_char *data, u_int datalen) { Buffer m; u_char *blob; u_int len; int verified = 0; debug3("%s entering", __func__); /* Convert the key to a blob and the pass it over */ if (!key_to_blob(key, &blob, &len)) return (0); buffer_init(&m); buffer_put_string(&m, blob, len); buffer_put_string(&m, sig, siglen); buffer_put_string(&m, data, datalen); xfree(blob); mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_KEYVERIFY, &m); debug3("%s: waiting for MONITOR_ANS_KEYVERIFY", __func__); mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_KEYVERIFY, &m); verified = buffer_get_int(&m); buffer_free(&m); return (verified); } /* Export key state after authentication */ Newkeys * mm_newkeys_from_blob(u_char *blob, int blen) { Buffer b; u_int len; Newkeys *newkey = NULL; Enc *enc; Mac *mac; Comp *comp; debug3("%s: %p(%d)", __func__, blob, blen); #ifdef DEBUG_PK dump_base64(stderr, blob, blen); #endif buffer_init(&b); buffer_append(&b, blob, blen); newkey = xmalloc(sizeof(*newkey)); enc = &newkey->enc; mac = &newkey->mac; comp = &newkey->comp; /* Enc structure */ enc->name = buffer_get_string(&b, NULL); buffer_get(&b, &enc->cipher, sizeof(enc->cipher)); enc->enabled = buffer_get_int(&b); enc->block_size = buffer_get_int(&b); enc->key = buffer_get_string(&b, &enc->key_len); enc->iv = buffer_get_string(&b, &len); if (len != enc->block_size) fatal("%s: bad ivlen: expected %d != %d", __func__, enc->block_size, len); if (enc->name == NULL || cipher_by_name(enc->name) != enc->cipher) fatal("%s: bad cipher name %s or pointer %p", __func__, enc->name, enc->cipher); /* Mac structure */ mac->name = buffer_get_string(&b, NULL); if (mac->name == NULL || mac_init(mac, mac->name) == -1) fatal("%s: can not init mac %s", __func__, mac->name); mac->enabled = buffer_get_int(&b); mac->key = buffer_get_string(&b, &len); if (len > mac->key_len) fatal("%s: bad mac key length: %d > %d", __func__, len, mac->key_len); mac->key_len = len; /* Comp structure */ comp->type = buffer_get_int(&b); comp->enabled = buffer_get_int(&b); comp->name = buffer_get_string(&b, NULL); len = buffer_len(&b); if (len != 0) error("newkeys_from_blob: remaining bytes in blob %d", len); buffer_free(&b); return (newkey); } int mm_newkeys_to_blob(int mode, u_char **blobp, u_int *lenp) { Buffer b; int len; u_char *buf; Enc *enc; Mac *mac; Comp *comp; Newkeys *newkey = newkeys[mode]; debug3("%s: converting %p", __func__, newkey); if (newkey == NULL) { error("%s: newkey == NULL", __func__); return 0; } enc = &newkey->enc; mac = &newkey->mac; comp = &newkey->comp; buffer_init(&b); /* Enc structure */ buffer_put_cstring(&b, enc->name); /* The cipher struct is constant and shared, you export pointer */ buffer_append(&b, &enc->cipher, sizeof(enc->cipher)); buffer_put_int(&b, enc->enabled); buffer_put_int(&b, enc->block_size); buffer_put_string(&b, enc->key, enc->key_len); packet_get_keyiv(mode, enc->iv, enc->block_size); buffer_put_string(&b, enc->iv, enc->block_size); /* Mac structure */ buffer_put_cstring(&b, mac->name); buffer_put_int(&b, mac->enabled); buffer_put_string(&b, mac->key, mac->key_len); /* Comp structure */ buffer_put_int(&b, comp->type); buffer_put_int(&b, comp->enabled); buffer_put_cstring(&b, comp->name); len = buffer_len(&b); buf = xmalloc(len); memcpy(buf, buffer_ptr(&b), len); memset(buffer_ptr(&b), 0, len); buffer_free(&b); if (lenp != NULL) *lenp = len; if (blobp != NULL) *blobp = buf; return len; } static void mm_send_kex(Buffer *m, Kex *kex) { buffer_put_string(m, kex->session_id, kex->session_id_len); buffer_put_int(m, kex->we_need); buffer_put_int(m, kex->hostkey_type); buffer_put_int(m, kex->kex_type); buffer_put_string(m, buffer_ptr(&kex->my), buffer_len(&kex->my)); buffer_put_string(m, buffer_ptr(&kex->peer), buffer_len(&kex->peer)); buffer_put_int(m, kex->flags); buffer_put_cstring(m, kex->client_version_string); buffer_put_cstring(m, kex->server_version_string); } void mm_send_keystate(struct monitor *pmonitor) { Buffer m; u_char *blob, *p; u_int bloblen, plen; buffer_init(&m); if (!compat20) { u_char iv[24]; u_char *key; u_int ivlen, keylen; buffer_put_int(&m, packet_get_protocol_flags()); buffer_put_int(&m, packet_get_ssh1_cipher()); debug3("%s: Sending ssh1 KEY+IV", __func__); keylen = packet_get_encryption_key(NULL); key = xmalloc(keylen+1); /* add 1 if keylen == 0 */ keylen = packet_get_encryption_key(key); buffer_put_string(&m, key, keylen); memset(key, 0, keylen); xfree(key); ivlen = packet_get_keyiv_len(MODE_OUT); packet_get_keyiv(MODE_OUT, iv, ivlen); buffer_put_string(&m, iv, ivlen); ivlen = packet_get_keyiv_len(MODE_OUT); packet_get_keyiv(MODE_IN, iv, ivlen); buffer_put_string(&m, iv, ivlen); goto skip; } else { /* Kex for rekeying */ mm_send_kex(&m, *pmonitor->m_pkex); } debug3("%s: Sending new keys: %p %p", __func__, newkeys[MODE_OUT], newkeys[MODE_IN]); /* Keys from Kex */ if (!mm_newkeys_to_blob(MODE_OUT, &blob, &bloblen)) fatal("%s: conversion of newkeys failed", __func__); buffer_put_string(&m, blob, bloblen); xfree(blob); if (!mm_newkeys_to_blob(MODE_IN, &blob, &bloblen)) fatal("%s: conversion of newkeys failed", __func__); buffer_put_string(&m, blob, bloblen); xfree(blob); buffer_put_int(&m, packet_get_seqnr(MODE_OUT)); buffer_put_int(&m, packet_get_seqnr(MODE_IN)); debug3("%s: New keys have been sent", __func__); skip: /* More key context */ plen = packet_get_keycontext(MODE_OUT, NULL); p = xmalloc(plen+1); packet_get_keycontext(MODE_OUT, p); buffer_put_string(&m, p, plen); xfree(p); plen = packet_get_keycontext(MODE_IN, NULL); p = xmalloc(plen+1); packet_get_keycontext(MODE_IN, p); buffer_put_string(&m, p, plen); xfree(p); /* Compression state */ debug3("%s: Sending compression state", __func__); buffer_put_string(&m, &outgoing_stream, sizeof(outgoing_stream)); buffer_put_string(&m, &incoming_stream, sizeof(incoming_stream)); /* Network I/O buffers */ buffer_put_string(&m, buffer_ptr(&input), buffer_len(&input)); buffer_put_string(&m, buffer_ptr(&output), buffer_len(&output)); mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_KEYEXPORT, &m); debug3("%s: Finished sending state", __func__); buffer_free(&m); } int mm_pty_allocate(int *ptyfd, int *ttyfd, char *namebuf, int namebuflen) { Buffer m; u_char *p; int success = 0; buffer_init(&m); mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PTY, &m); debug3("%s: waiting for MONITOR_ANS_PTY", __func__); mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PTY, &m); success = buffer_get_int(&m); if (success == 0) { debug3("%s: pty alloc failed", __func__); buffer_free(&m); return (0); } p = buffer_get_string(&m, NULL); buffer_free(&m); strlcpy(namebuf, p, namebuflen); /* Possible truncation */ xfree(p); *ptyfd = mm_receive_fd(pmonitor->m_recvfd); *ttyfd = mm_receive_fd(pmonitor->m_recvfd); /* Success */ return (1); } void mm_session_pty_cleanup2(void *session) { Session *s = session; Buffer m; if (s->ttyfd == -1) return; buffer_init(&m); buffer_put_cstring(&m, s->tty); mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PTYCLEANUP, &m); buffer_free(&m); /* closed dup'ed master */ if (close(s->ptymaster) < 0) error("close(s->ptymaster): %s", strerror(errno)); /* unlink pty from session */ s->ttyfd = -1; } #ifdef USE_PAM void mm_start_pam(char *user) { Buffer m; debug3("%s entering", __func__); buffer_init(&m); buffer_put_cstring(&m, user); mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_START, &m); buffer_free(&m); } #endif /* USE_PAM */ /* Request process termination */ void mm_terminate(void) { Buffer m; buffer_init(&m); mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_TERM, &m); buffer_free(&m); } int mm_ssh1_session_key(BIGNUM *num) { int rsafail; Buffer m; buffer_init(&m); buffer_put_bignum2(&m, num); mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_SESSKEY, &m); mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_SESSKEY, &m); rsafail = buffer_get_int(&m); buffer_get_bignum2(&m, num); buffer_free(&m); return (rsafail); } static void mm_chall_setup(char **name, char **infotxt, u_int *numprompts, char ***prompts, u_int **echo_on) { *name = xstrdup(""); *infotxt = xstrdup(""); *numprompts = 1; *prompts = xmalloc(*numprompts * sizeof(char*)); *echo_on = xmalloc(*numprompts * sizeof(u_int)); (*echo_on)[0] = 0; } int mm_bsdauth_query(void *ctx, char **name, char **infotxt, u_int *numprompts, char ***prompts, u_int **echo_on) { Buffer m; int res; char *challenge; debug3("%s: entering", __func__); buffer_init(&m); mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_BSDAUTHQUERY, &m); mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_BSDAUTHQUERY, &m); res = buffer_get_int(&m); if (res == -1) { debug3("%s: no challenge", __func__); buffer_free(&m); return (-1); } /* Get the challenge, and format the response */ challenge = buffer_get_string(&m, NULL); buffer_free(&m); mm_chall_setup(name, infotxt, numprompts, prompts, echo_on); (*prompts)[0] = challenge; debug3("%s: received challenge: %s", __func__, challenge); return (0); } int mm_bsdauth_respond(void *ctx, u_int numresponses, char **responses) { Buffer m; int authok; debug3("%s: entering", __func__); if (numresponses != 1) return (-1); buffer_init(&m); buffer_put_cstring(&m, responses[0]); mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_BSDAUTHRESPOND, &m); mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_BSDAUTHRESPOND, &m); authok = buffer_get_int(&m); buffer_free(&m); return ((authok == 0) ? -1 : 0); } +#ifdef SKEY int mm_skey_query(void *ctx, char **name, char **infotxt, u_int *numprompts, char ***prompts, u_int **echo_on) { Buffer m; int len, res; char *p, *challenge; debug3("%s: entering", __func__); buffer_init(&m); mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_SKEYQUERY, &m); mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_SKEYQUERY, &m); res = buffer_get_int(&m); if (res == -1) { debug3("%s: no challenge", __func__); buffer_free(&m); return (-1); } /* Get the challenge, and format the response */ challenge = buffer_get_string(&m, NULL); buffer_free(&m); debug3("%s: received challenge: %s", __func__, challenge); mm_chall_setup(name, infotxt, numprompts, prompts, echo_on); len = strlen(challenge) + strlen(SKEY_PROMPT) + 1; p = xmalloc(len); strlcpy(p, challenge, len); strlcat(p, SKEY_PROMPT, len); (*prompts)[0] = p; xfree(challenge); return (0); } int mm_skey_respond(void *ctx, u_int numresponses, char **responses) { Buffer m; int authok; debug3("%s: entering", __func__); if (numresponses != 1) return (-1); buffer_init(&m); buffer_put_cstring(&m, responses[0]); mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_SKEYRESPOND, &m); mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_SKEYRESPOND, &m); authok = buffer_get_int(&m); buffer_free(&m); return ((authok == 0) ? -1 : 0); } +#endif void mm_ssh1_session_id(u_char session_id[16]) { Buffer m; int i; debug3("%s entering", __func__); buffer_init(&m); for (i = 0; i < 16; i++) buffer_put_char(&m, session_id[i]); mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_SESSID, &m); buffer_free(&m); } int mm_auth_rsa_key_allowed(struct passwd *pw, BIGNUM *client_n, Key **rkey) { Buffer m; Key *key; u_char *blob; u_int blen; int allowed = 0; debug3("%s entering", __func__); buffer_init(&m); buffer_put_bignum2(&m, client_n); mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_RSAKEYALLOWED, &m); mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_RSAKEYALLOWED, &m); allowed = buffer_get_int(&m); if (allowed && rkey != NULL) { blob = buffer_get_string(&m, &blen); if ((key = key_from_blob(blob, blen)) == NULL) fatal("%s: key_from_blob failed", __func__); *rkey = key; xfree(blob); } mm_send_debug(&m); buffer_free(&m); return (allowed); } BIGNUM * mm_auth_rsa_generate_challenge(Key *key) { Buffer m; BIGNUM *challenge; u_char *blob; u_int blen; debug3("%s entering", __func__); if ((challenge = BN_new()) == NULL) fatal("%s: BN_new failed", __func__); key->type = KEY_RSA; /* XXX cheat for key_to_blob */ if (key_to_blob(key, &blob, &blen) == 0) fatal("%s: key_to_blob failed", __func__); key->type = KEY_RSA1; buffer_init(&m); buffer_put_string(&m, blob, blen); xfree(blob); mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_RSACHALLENGE, &m); mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_RSACHALLENGE, &m); buffer_get_bignum2(&m, challenge); buffer_free(&m); return (challenge); } int mm_auth_rsa_verify_response(Key *key, BIGNUM *p, u_char response[16]) { Buffer m; u_char *blob; u_int blen; int success = 0; debug3("%s entering", __func__); key->type = KEY_RSA; /* XXX cheat for key_to_blob */ if (key_to_blob(key, &blob, &blen) == 0) fatal("%s: key_to_blob failed", __func__); key->type = KEY_RSA1; buffer_init(&m); buffer_put_string(&m, blob, blen); buffer_put_string(&m, response, 16); xfree(blob); mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_RSARESPONSE, &m); mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_RSARESPONSE, &m); success = buffer_get_int(&m); buffer_free(&m); return (success); }