diff --git a/ChangeLog b/ChangeLog index a55a3b3d7..9b0b3e2af 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,9 @@ 20050215 - (dtucker) [config.sh.in] Collect oslevel -r too. + - (dtucker) [README.platform auth.c configure.ac loginrec.c + openbsd-compat/port-aix.c openbsd-compat/port-aix.h] Bug #835: enable IPv6 + on AIX where possible (see README.platform for details) and work around + a misfeature of AIX's getnameinfo. ok djm@ 20050211 - (dtucker) [configure.ac] Tidy up configure --help output. @@ -2126,4 +2130,4 @@ - (djm) Trim deprecated options from INSTALL. Mention UsePAM - (djm) Fix quote handling in sftp; Patch from admorten AT umich.edu -$Id: ChangeLog,v 1.3651 2005/02/15 10:26:32 dtucker Exp $ +$Id: ChangeLog,v 1.3652 2005/02/15 10:45:57 dtucker Exp $ diff --git a/README.platform b/README.platform index 880b83c63..136304a8e 100644 --- a/README.platform +++ b/README.platform @@ -13,6 +13,15 @@ Accounts in this state must have their passwords reset manually by the administrator. As a precaution, it is recommended that the administrative passwords be reset before upgrading from OpenSSH <3.8. +As of OpenSSH 4.0, configure will attempt to detect if your version +and maintenance level of AIX has a working getaddrinfo, and will use it +if found. This will enable IPv6 support. If for some reason configure +gets it wrong, or if you want to build binaries to work on earlier MLs +than the build host then you can add "-DBROKEN_GETADDRINFO" to CFLAGS +to force the previous IPv4-only behaviour. + +IPv6 known to work: 5.2ML2 5.2ML5 +IPv6 known broken: 4.3.3ML11 5.1ML4 Cygwin ------ @@ -27,4 +36,4 @@ Currently, sshd does not support BSM auditting. This can show up as errors when editting cron entries via crontab. See. http://bugzilla.mindrot.org/show_bug.cgi?id=125 -$Id: README.platform,v 1.2 2004/04/23 08:57:13 dtucker Exp $ +$Id: README.platform,v 1.3 2005/02/15 10:45:57 dtucker Exp $ diff --git a/auth.c b/auth.c index e6dcab209..256807683 100644 --- a/auth.c +++ b/auth.c @@ -209,7 +209,7 @@ allowed_user(struct passwd * pw) } #ifdef CUSTOM_SYS_AUTH_ALLOWED_USER - if (!sys_auth_allowed_user(pw)) + if (!sys_auth_allowed_user(pw, &loginmsg)) return 0; #endif diff --git a/configure.ac b/configure.ac index 2df8a5e87..b27f0cf70 100644 --- a/configure.ac +++ b/configure.ac @@ -1,4 +1,4 @@ -# $Id: configure.ac,v 1.241 2005/02/11 05:11:49 dtucker Exp $ +# $Id: configure.ac,v 1.242 2005/02/15 10:45:57 dtucker Exp $ # # Copyright (c) 1999-2004 Damien Miller # @@ -135,7 +135,7 @@ case "$host" in [#include ] ) AC_CHECK_FUNCS(setauthdb) - AC_DEFINE(BROKEN_GETADDRINFO) + check_for_aix_broken_getaddrinfo=1 AC_DEFINE(BROKEN_REALPATH) AC_DEFINE(SETEUID_BREAKS_SETUID) AC_DEFINE(BROKEN_SETREUID) @@ -1146,6 +1146,64 @@ main(void) ) fi +if test "x$ac_cv_func_getaddrinfo" = "xyes" -a "x$check_for_aix_broken_getaddrinfo" = "x1"; then + AC_MSG_CHECKING(if getaddrinfo seems to work) + AC_TRY_RUN( + [ +#include +#include +#include +#include +#include + +#define TEST_PORT "2222" + +int +main(void) +{ + int err, sock; + struct addrinfo *gai_ai, *ai, hints; + char ntop[NI_MAXHOST], strport[NI_MAXSERV], *name = NULL; + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = PF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_flags = AI_PASSIVE; + + err = getaddrinfo(name, TEST_PORT, &hints, &gai_ai); + if (err != 0) { + fprintf(stderr, "getaddrinfo failed (%s)", gai_strerror(err)); + exit(1); + } + + for (ai = gai_ai; ai != NULL; ai = ai->ai_next) { + if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6) + continue; + + err = getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop, + sizeof(ntop), strport, sizeof(strport), + NI_NUMERICHOST|NI_NUMERICSERV); + + if (ai->ai_family == AF_INET && err != 0) { + perror("getnameinfo"); + exit(2); + } + } + exit(0); +} + ], + [ + AC_MSG_RESULT(yes) + AC_DEFINE(AIX_GETNAMEINFO_HACK, [], +[Define if you have a getaddrinfo that fails for the all-zeros IPv6 address]) + ], + [ + AC_MSG_RESULT(no) + AC_DEFINE(BROKEN_GETADDRINFO) + ] + ) +fi + if test "x$check_for_conflicting_getspnam" = "x1"; then AC_MSG_CHECKING(for conflicting getspnam in shadow.h) AC_COMPILE_IFELSE( diff --git a/loginrec.c b/loginrec.c index c033582ad..8f5061cdc 100644 --- a/loginrec.c +++ b/loginrec.c @@ -164,7 +164,7 @@ # include #endif -RCSID("$Id: loginrec.c,v 1.65 2005/02/08 10:52:48 dtucker Exp $"); +RCSID("$Id: loginrec.c,v 1.66 2005/02/15 10:45:57 dtucker Exp $"); /** ** prototypes for helper functions in this file @@ -192,6 +192,8 @@ int lastlog_get_entry(struct logininfo *li); int wtmp_get_entry(struct logininfo *li); int wtmpx_get_entry(struct logininfo *li); +extern Buffer loginmsg; + /* pick the shortest string */ #define MIN_SIZEOF(s1,s2) (sizeof(s1) < sizeof(s2) ? sizeof(s1) : sizeof(s2)) @@ -441,7 +443,7 @@ login_write(struct logininfo *li) #endif #ifdef CUSTOM_SYS_AUTH_RECORD_LOGIN if (li->type == LTYPE_LOGIN && - !sys_auth_record_login(li->username,li->hostname,li->line)) + !sys_auth_record_login(li->username,li->hostname,li->line, &loginmsg)) logit("Writing login record failed for %s", li->username); #endif #ifdef SSH_AUDIT_EVENTS diff --git a/openbsd-compat/port-aix.c b/openbsd-compat/port-aix.c index b16988543..8ab862f98 100644 --- a/openbsd-compat/port-aix.c +++ b/openbsd-compat/port-aix.c @@ -34,14 +34,13 @@ #ifdef _AIX #include +#include #include "port-aix.h" /* These should be in the system headers but are not. */ int usrinfo(int, char *, int); int setauthdb(const char *, char *); -extern Buffer loginmsg; - # ifdef HAVE_SETAUTHDB static char old_registry[REGISTRY_SIZE] = ""; # endif @@ -156,7 +155,7 @@ aix_valid_authentications(const char *user) * returns 0. */ int -sys_auth_passwd(Authctxt *ctxt, const char *password) +sys_auth_passwd(Authctxt *ctxt, const char *password, Buffer *loginmsg) { char *authmsg = NULL, *msg, *name = ctxt->pw->pw_name; int authsuccess = 0, expired, reenter, result; @@ -186,7 +185,7 @@ sys_auth_passwd(Authctxt *ctxt, const char *password) */ expired = passwdexpired(name, &msg); if (msg && *msg) { - buffer_append(&loginmsg, msg, strlen(msg)); + buffer_append(loginmsg, msg, strlen(msg)); aix_remove_embedded_newlines(msg); } debug3("AIX/passwdexpired returned %d msg %.100s", expired, msg); @@ -219,7 +218,7 @@ sys_auth_passwd(Authctxt *ctxt, const char *password) * Returns 1 if login is allowed, 0 if not allowed. */ int -sys_auth_allowed_user(struct passwd *pw) +sys_auth_allowed_user(struct passwd *pw, Buffer *loginmsg) { char *msg = NULL; int result, permitted = 0; @@ -246,7 +245,7 @@ sys_auth_allowed_user(struct passwd *pw) if (result == -1 && errno == EPERM && stat(_PATH_NOLOGIN, &st) == 0) permitted = 1; else if (msg != NULL) - buffer_append(&loginmsg, msg, strlen(msg)); + buffer_append(loginmsg, msg, strlen(msg)); if (msg == NULL) msg = xstrdup("(none)"); aix_remove_embedded_newlines(msg); @@ -259,7 +258,8 @@ sys_auth_allowed_user(struct passwd *pw) } int -sys_auth_record_login(const char *user, const char *host, const char *ttynm) +sys_auth_record_login(const char *user, const char *host, const char *ttynm, + Buffer *loginmsg) { char *msg; int success = 0; @@ -269,7 +269,7 @@ sys_auth_record_login(const char *user, const char *host, const char *ttynm) success = 1; if (msg != NULL) { debug("AIX/loginsuccess: msg %s", msg); - buffer_append(&loginmsg, msg, strlen(msg)); + buffer_append(loginmsg, msg, strlen(msg)); xfree(msg); } } @@ -349,4 +349,33 @@ aix_restoreauthdb(void) # endif /* WITH_AIXAUTHENTICATE */ +# if defined(AIX_GETNAMEINFO_HACK) && !defined(BROKEN_ADDRINFO) +# undef getnameinfo +/* + * For some reason, AIX's getnameinfo will refuse to resolve the all-zeros + * IPv6 address into its textual representation ("::"), so we wrap it + * with a function that will. + */ +int +sshaix_getnameinfo(const struct sockaddr *sa, size_t salen, char *host, + size_t hostlen, char *serv, size_t servlen, int flags) +{ + struct sockaddr_in6 *sa6; + u_int32_t *a6; + + if (flags & (NI_NUMERICHOST|NI_NUMERICSERV) && + sa->sa_family == AF_INET6) { + sa6 = (struct sockaddr_in6 *)sa; + a6 = sa6->sin6_addr.u6_addr.u6_addr32; + + if (a6[0] == 0 && a6[1] == 0 && a6[2] == 0 && a6[3] == 0) { + strlcpy(host, "::", hostlen); + snprintf(serv, servlen, "%d", sa6->sin6_port); + return 0; + } + } + return getnameinfo(sa, salen, host, hostlen, serv, servlen, flags); +} +# endif /* AIX_GETNAMEINFO_HACK */ + #endif /* _AIX */ diff --git a/openbsd-compat/port-aix.h b/openbsd-compat/port-aix.h index 751139004..cc7c43cda 100644 --- a/openbsd-compat/port-aix.h +++ b/openbsd-compat/port-aix.h @@ -1,4 +1,4 @@ -/* $Id: port-aix.h,v 1.22 2005/02/02 06:10:11 dtucker Exp $ */ +/* $Id: port-aix.h,v 1.23 2005/02/15 10:45:58 dtucker Exp $ */ /* * @@ -27,6 +27,10 @@ #ifdef _AIX +#ifdef HAVE_SYS_SOCKET_H +# include +#endif + #ifdef WITH_AIXAUTHENTICATE # include # include @@ -36,6 +40,8 @@ # include #endif +#include "buffer.h" + /* Some versions define r_type in the above headers, which causes a conflict */ #ifdef r_type # undef r_type @@ -64,13 +70,23 @@ void aix_usrinfo(struct passwd *); #ifdef WITH_AIXAUTHENTICATE # define CUSTOM_SYS_AUTH_PASSWD 1 # define CUSTOM_SYS_AUTH_ALLOWED_USER 1 -int sys_auth_allowed_user(struct passwd *); +int sys_auth_allowed_user(struct passwd *, Buffer *); # define CUSTOM_SYS_AUTH_RECORD_LOGIN 1 -int sys_auth_record_login(const char *, const char *, const char *); +int sys_auth_record_login(const char *, const char *, const char *, Buffer *); # define CUSTOM_FAILED_LOGIN 1 #endif void aix_setauthdb(const char *); void aix_restoreauthdb(void); void aix_remove_embedded_newlines(char *); + +#if defined(AIX_GETNAMEINFO_HACK) && !defined(BROKEN_GETADDRINFO) +# ifdef getnameinfo +# undef getnameinfo +# endif +int sshaix_getnameinfo(const struct sockaddr *, size_t, char *, size_t, + char *, size_t, int); +# define getnameinfo(a,b,c,d,e,f,g) (sshaix_getnameinfo(a,b,c,d,e,f,g)) +#endif + #endif /* _AIX */