diff options
-rw-r--r-- | ChangeLog | 33 | ||||
-rw-r--r-- | Makefile.in | 62 | ||||
-rw-r--r-- | TODO | 2 | ||||
-rw-r--r-- | acconfig.h | 28 | ||||
-rw-r--r-- | bsd-bindresvport.c | 116 | ||||
-rw-r--r-- | bsd-bindresvport.h | 10 | ||||
-rw-r--r-- | bsd-rresvport.c | 107 | ||||
-rw-r--r-- | bsd-rresvport.h | 10 | ||||
-rw-r--r-- | canohost.c | 184 | ||||
-rw-r--r-- | channels.c | 388 | ||||
-rw-r--r-- | configure.in | 88 | ||||
-rw-r--r-- | defines.h | 4 | ||||
-rw-r--r-- | fake-gai-errnos.h | 12 | ||||
-rw-r--r-- | fake-getaddrinfo.c | 119 | ||||
-rw-r--r-- | fake-getaddrinfo.h | 44 | ||||
-rw-r--r-- | fake-getnameinfo.c | 61 | ||||
-rw-r--r-- | fake-getnameinfo.h | 17 | ||||
-rw-r--r-- | fake-socket.h | 49 | ||||
-rwxr-xr-x | fixpaths | 2 | ||||
-rw-r--r-- | hostfile.c | 2 | ||||
-rw-r--r-- | includes.h | 9 | ||||
-rw-r--r-- | log.c | 2 | ||||
-rw-r--r-- | login.c | 42 | ||||
-rw-r--r-- | nchan.c | 30 | ||||
-rw-r--r-- | nchan.ms | 9 | ||||
-rw-r--r-- | packet.c | 65 | ||||
-rw-r--r-- | packet.h | 6 | ||||
-rw-r--r-- | scp.1.in | 12 | ||||
-rw-r--r-- | scp.c | 56 | ||||
-rw-r--r-- | servconf.c | 88 | ||||
-rw-r--r-- | servconf.h | 12 | ||||
-rw-r--r-- | ssh.1.in | 22 | ||||
-rw-r--r-- | ssh.c | 54 | ||||
-rw-r--r-- | ssh.h | 17 | ||||
-rw-r--r-- | sshconnect.c | 207 | ||||
-rw-r--r-- | sshd.8.in | 17 | ||||
-rw-r--r-- | sshd.c | 249 | ||||
-rw-r--r-- | sshd_config.in | 1 |
38 files changed, 1633 insertions, 603 deletions
@@ -1,3 +1,36 @@ +20000114 + - Merged OpenBSD IPv6 patch: + - [sshd.c sshd.8 sshconnect.c ssh.h ssh.c servconf.h servconf.c scp.1] + [scp.c packet.h packet.c login.c log.c canohost.c channels.c] + [hostfile.c sshd_config] + ipv6 support: mostly gethostbyname->getaddrinfo/getnameinfo, new + features: sshd allows multiple ListenAddress and Port options. note + that libwrap is not IPv6-ready. (based on patches from + fujiwara@rcac.tdi.co.jp) + - [ssh.c canohost.c] + more hints (hints.ai_socktype=SOCK_STREAM) for getaddrinfo, + from itojun@ + - [channels.c] + listen on _all_ interfaces for X11-Fwd (hints.ai_flags = AI_PASSIVE) + - [packet.h] + allow auth-kerberos for IPv4 only + - [scp.1 sshd.8 servconf.h scp.c] + document -4, -6, and 'ssh -L 2022/::1/22' + - [ssh.c] + 'ssh @host' is illegal (null user name), from + karsten@gedankenpolizei.de + - [sshconnect.c] + better error message + - [sshd.c] + allow auth-kerberos for IPv4 only + - Big IPv6 merge: + - Cleanup overrun in sockaddr copying on RHL 6.1 + - Replacements for getaddrinfo, getnameinfo, etc based on versions + from patch from KIKUCHI Takahiro <kick@kyoto.wide.ad.jp> + - Replacement for missing structures on systems that lack IPv6 + - record_login needed to know about AF_INET6 addresses + - Borrowed more code from OpenBSD: rresvport_af and requisites + 20000110 - Fixes to auth-skey to enable it to use the standard OpenSSL libraries diff --git a/Makefile.in b/Makefile.in index 23f00582..786cd436 100644 --- a/Makefile.in +++ b/Makefile.in @@ -19,7 +19,6 @@ CC=@CC@ PATHS=-DETCDIR=\"$(sysconfdir)\" -DSSH_PROGRAM=\"$(SSH_PROGRAM)\" -DSSH_ASKPASS_DEFAULT=\"$(ASKPASS_PROGRAM)\" CFLAGS=@CFLAGS@ $(PATHS) @DEFS@ EXTRA_TARGETS=@GNOME_ASKPASS@ -TARGETS=libssh.a ssh sshd ssh-add ssh-keygen ssh-agent scp $(EXTRA_TARGETS) LIBS=@LIBS@ AR=@AR@ RANLIB=@RANLIB@ @@ -30,34 +29,19 @@ LDFLAGS=-L. @LDFLAGS@ GNOME_CFLAGS=`gnome-config --cflags gnome gnomeui` GNOME_LIBS=`gnome-config --libs gnome gnomeui` -OBJS= atomicio.o authfd.o authfile.o auth-krb4.o auth-passwd.o auth-pam.o \ - auth-rhosts.o auth-rh-rsa.o auth-rsa.o auth-skey.o bsd-daemon.o \ - bsd-login.o bsd-misc.o bsd-mktemp.o bsd-snprintf.o bsd-strlcat.o \ - bsd-strlcpy.o bufaux.o buffer.o canohost.o channels.o cipher.o \ - clientloop.o compress.o crc32.o deattack.o hostfile.o \ - log-client.o login.o log-server.o match.o md5crypt.o mpaux.o \ - packet.o pty.o radix.o readconf.o readpass.o rsa.o servconf.o \ - serverloop.o sshconnect.o tildexpand.o ttymodes.o uidswap.o \ - xmalloc.o - -LIBOBJS= atomicio.o authfd.o authfile.o bsd-daemon.o bsd-misc.o \ - bsd-mktemp.o bsd-snprintf.o bsd-strlcat.o bsd-strlcpy.o bufaux.o \ - buffer.o canohost.o channels.o cipher.o compat.o compress.o crc32.o \ - deattack.o fingerprint.o hostfile.o log.o match.o mpaux.o nchan.o \ - packet.o radix.o readpass.o rsa.o tildexpand.o ttymodes.o uidswap.o \ - xmalloc.o +TARGETS=ssh sshd ssh-add ssh-keygen ssh-agent scp $(EXTRA_TARGETS) + +LIBOBJS= atomicio.o authfd.o authfile.o bsd-bindresvport.o bsd-daemon.o bsd-misc.o bsd-mktemp.o bsd-rresvport.o bsd-snprintf.o bsd-strlcat.o bsd-strlcpy.o bufaux.o buffer.o canohost.o channels.o cipher.o compat.o compress.o crc32.o deattack.o fake-getaddrinfo.o fake-getnameinfo.o fingerprint.o hostfile.o log.o match.o mpaux.o nchan.o packet.o radix.o readpass.o rsa.o tildexpand.o ttymodes.o uidswap.o xmalloc.o SSHOBJS= ssh.o sshconnect.o log-client.o readconf.o clientloop.o -SSHDOBJS= sshd.o auth-rhosts.o auth-krb4.o auth-pam.o auth-passwd.o \ - auth-rsa.o auth-rh-rsa.o pty.o log-server.o login.o servconf.o \ - serverloop.o bsd-login.o md5crypt.o +SSHDOBJS= sshd.o auth-rhosts.o auth-krb4.o auth-pam.o auth-passwd.o auth-rsa.o auth-rh-rsa.o pty.o log-server.o login.o servconf.o serverloop.o bsd-login.o md5crypt.o MANPAGES=scp.1 ssh-add.1 ssh-agent.1 ssh-keygen.1 ssh.1 sshd.8 CONFIGFILES=sshd_config ssh_config -all: $(OBJS) $(TARGETS) $(MANPAGES) $(CONFIGFILES) +all: $(TARGETS) $(MANPAGES) $(CONFIGFILES) $(OBJS): config.h @@ -67,31 +51,27 @@ libssh.a: $(LIBOBJS) $(AR) rv $@ $(LIBOBJS) $(RANLIB) $@ -ssh: $(SSHOBJS) libssh.a +ssh: libssh.a $(SSHOBJS) $(CC) -o $@ $(SSHOBJS) $(LDFLAGS) -lssh $(LIBS) -sshd: $(SSHDOBJS) libssh.a +sshd: libssh.a $(SSHDOBJS) $(CC) -o $@ $(SSHDOBJS) $(LDFLAGS) -lssh $(LIBS) -scp: scp.o libssh.a +scp: libssh.a scp.o $(CC) -o $@ scp.o $(LDFLAGS) -lssh $(LIBS) -ssh-add: ssh-add.o log-client.o libssh.a +ssh-add: libssh.a ssh-add.o log-client.o $(CC) -o $@ ssh-add.o log-client.o $(LDFLAGS) -lssh $(LIBS) -ssh-agent: ssh-agent.o log-client.o libssh.a +ssh-agent: libssh.a ssh-agent.o log-client.o $(CC) -o $@ ssh-agent.o log-client.o $(LDFLAGS) -lssh $(LIBS) -ssh-keygen: ssh-keygen.o log-client.o libssh.a +ssh-keygen: libssh.a ssh-keygen.o log-client.o $(CC) -o $@ ssh-keygen.o log-client.o $(LDFLAGS) -lssh $(LIBS) gnome-ssh-askpass: gnome-ssh-askpass.c $(CC) $(CFLAGS) $(GNOME_CFLAGS) -o $@ gnome-ssh-askpass.c $(GNOME_LIBS) -clean: - rm -f *.o $(TARGETS) config.status config.cache config.log core \ - *.1 *.8 sshd_config ssh_config - scp.1: scp.1.in $(PERL) $(FIXPATHS) -Dsysconfdir=${sysconfdir} $(srcdir)/scp.1.in @@ -116,6 +96,18 @@ sshd_config: sshd_config.in ssh_config: ssh_config.in $(PERL) $(FIXPATHS) -Dsysconfdir=${sysconfdir} ssh_config.in +clean: + rm -f *.o *.a $(TARGETS) config.status config.cache config.log + rm -f core *.1 *.8 sshd_config ssh_config + +distclean: clean + rm -f Makefile config.h core *~ + +mrproper: distclean + +veryclean: distclean + rm -f configure config.h.in + install: $(TARGETS) $(INSTALL) -d $(bindir) $(INSTALL) -d $(sbindir) @@ -180,11 +172,3 @@ uninstall: -rm -f ${ASKPASS_PROGRAM} -rmdir $(libexecdir)/ssh ; -distclean: clean - rm -f Makefile config.h core *~ - -mrproper: distclean - -veryclean: distclean - rm -f configure config.h.in - @@ -7,6 +7,8 @@ - Replace the horror in acconfig.h which tries to comphensate for the lack of u_intXX_t types. There must be a better way. +- Move all compatability cruft (bsd-*, fake-*) into subordinate library + - Hanging on logout: localhost$ ssh remotehost @@ -40,31 +40,17 @@ * message at run-time. */ #undef RSAREF -/* Define is utmp.h has a ut_host field */ +/* struct utmp and struct utmpx fields */ #undef HAVE_HOST_IN_UTMP - -/* Define is utmpx.h has a ut_host field */ #undef HAVE_HOST_IN_UTMPX - -/* Define is utmp.h has a ut_addr field */ #undef HAVE_ADDR_IN_UTMP - -/* Define is utmpx.h has a ut_addr field */ #undef HAVE_ADDR_IN_UTMPX - -/* Define is utmpx.h has a syslen field */ +#undef HAVE_ADDR_V6_IN_UTMP +#undef HAVE_ADDR_V6_IN_UTMPX #undef HAVE_SYSLEN_IN_UTMPX - -/* Define is utmp.h has a ut_pid field */ #undef HAVE_PID_IN_UTMP - -/* Define is utmp.h has a ut_type field */ #undef HAVE_TYPE_IN_UTMP - -/* Define is utmp.h has a ut_tv field */ #undef HAVE_TV_IN_UTMP - -/* Define is utmp.h has a ut_id field */ #undef HAVE_ID_IN_UTMP /* Define if you want to use utmpx */ @@ -125,6 +111,14 @@ #undef HAVE_UINTXX_T #undef HAVE_SOCKLEN_T #undef HAVE_SIZE_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 diff --git a/bsd-bindresvport.c b/bsd-bindresvport.c new file mode 100644 index 00000000..3ea37ee5 --- /dev/null +++ b/bsd-bindresvport.c @@ -0,0 +1,116 @@ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +#include "config.h" + +#ifndef HAVE_BINRESVPORT_AF + +#if defined(LIBC_SCCS) && !defined(lint) +static char *rcsid = "$OpenBSD: bindresvport.c,v 1.11 1999/12/17 19:22:08 deraadt Exp $"; +#endif /* LIBC_SCCS and not lint */ + +/* + * Copyright (c) 1987 by Sun Microsystems, Inc. + * + * Portions Copyright(C) 1996, Jason Downs. All rights reserved. + */ + +#include "includes.h" + +#define STARTPORT 600 +#define ENDPORT (IPPORT_RESERVED - 1) +#define NPORTS (ENDPORT - STARTPORT + 1) + +#if 0 +/* + * Bind a socket to a privileged IP port + */ +int +bindresvport(sd, sin) + int sd; + struct sockaddr_in *sin; +{ + return bindresvport_af(sd, (struct sockaddr *)sin, AF_INET); +} +#endif + +/* + * Bind a socket to a privileged IP port + */ +int +bindresvport_af(sd, sa, af) + int sd; + struct sockaddr *sa; + int af; +{ + int error; + struct sockaddr_storage myaddr; + struct sockaddr_in *sin; + struct sockaddr_in6 *sin6; + u_int16_t *portp; + int salen; + int i; + + if (sa == NULL) { + memset(&myaddr, 0, sizeof(myaddr)); + sa = (struct sockaddr *)&myaddr; + } + + if (af == AF_INET) { + sin = (struct sockaddr_in *)sa; + salen = sizeof(struct sockaddr_in); + portp = &sin->sin_port; + } else if (af == AF_INET6) { + sin6 = (struct sockaddr_in6 *)sa; + salen = sizeof(struct sockaddr_in6); + portp = &sin6->sin6_port; + } else { + errno = EPFNOSUPPORT; + return (-1); + } + sa->sa_family = af; + + if (*portp == 0) + *portp = (getpid() % NPORTS) + STARTPORT; + + for(i = 0; i < NPORTS; i++) { + error = bind(sd, sa, salen); + + if ((error == 0) || ((error < 0) && (errno != EADDRINUSE))) + break; + + (*portp)++; + if (*portp < ENDPORT) + *portp = STARTPORT; + } + + return (error); +} + +#endif /* HAVE_BINRESVPORT_AF */ diff --git a/bsd-bindresvport.h b/bsd-bindresvport.h new file mode 100644 index 00000000..df084e3d --- /dev/null +++ b/bsd-bindresvport.h @@ -0,0 +1,10 @@ +#ifndef _BSD_BINRESVPORT_H +#define _BSD_BINRESVPORT_H + +#include "config.h" + +#ifndef HAVE_BINRESVPORT_AF +int bindresvport_af(int sd, struct sockaddr *sa, int af); +#endif /* !HAVE_BINRESVPORT_AF */ + +#endif /* _BSD_BINRESVPORT_H */ diff --git a/bsd-rresvport.c b/bsd-rresvport.c new file mode 100644 index 00000000..c29165fa --- /dev/null +++ b/bsd-rresvport.c @@ -0,0 +1,107 @@ +/* + * Copyright (c) 1995, 1996, 1998 Theo de Raadt. All rights reserved. + * Copyright (c) 1983, 1993, 1994 + * The Regents of the University of California. 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. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * This product includes software developed by Theo de Raadt. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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 "config.h" + +#ifndef HAVE_RRESVPORT_AF + +#if defined(LIBC_SCCS) && !defined(lint) +static char *rcsid = "$OpenBSD: rresvport.c,v 1.4 1999/12/17 20:48:03 deraadt Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include "includes.h" + +#if 0 +int +rresvport(alport) + int *alport; +{ + return rresvport_af(alport, AF_INET); +} +#endif + +int +rresvport_af(alport, af) + int *alport; + int af; +{ + struct sockaddr_storage ss; + struct sockaddr *sa; + u_int16_t *portp; + int s; + int sa_len; + + bzero(&ss, sizeof ss); + sa = (struct sockaddr *)&ss; + + switch (af) { + case AF_INET: + sa_len = sizeof(struct sockaddr_in); + portp = &((struct sockaddr_in *)sa)->sin_port; + break; + case AF_INET6: + sa_len = sizeof(struct sockaddr_in6); + portp = &((struct sockaddr_in6 *)sa)->sin6_port; + break; + default: + errno = EPFNOSUPPORT; + return (-1); + } + sa->sa_family = af; + + s = socket(af, SOCK_STREAM, 0); + if (s < 0) + return (-1); + + *portp = htons(*alport); + if (*alport < IPPORT_RESERVED - 1) { + if (bind(s, sa, sa_len) >= 0) + return (s); + if (errno != EADDRINUSE) { + (void)close(s); + return (-1); + } + } + + *portp = 0; + if (bindresvport_af(s, sa, af) == -1) { + (void)close(s); + return (-1); + } + *alport = ntohs(*portp); + return (s); +} + +#endif /* HAVE_RRESVPORT_AF */ diff --git a/bsd-rresvport.h b/bsd-rresvport.h new file mode 100644 index 00000000..69d6bbd9 --- /dev/null +++ b/bsd-rresvport.h @@ -0,0 +1,10 @@ +#ifndef _BSD_RRESVPORT_H +#define _BSD_RRESVPORT_H + +#include "config.h" + +#ifndef HAVE_RRESVPORT_AF +int rresvport_af(int *alport, int af); +#endif /* !HAVE_RRESVPORT_AF */ + +#endif /* _BSD_RRESVPORT_H */ @@ -14,7 +14,7 @@ */ #include "includes.h" -RCSID("$Id: canohost.c,v 1.6 1999/12/18 09:57:40 damien Exp $"); +RCSID("$Id: canohost.c,v 1.7 2000/01/14 04:45:48 damien Exp $"); #include "packet.h" #include "xmalloc.h" @@ -28,10 +28,12 @@ RCSID("$Id: canohost.c,v 1.6 1999/12/18 09:57:40 damien Exp $"); char * get_remote_hostname(int socket) { - struct sockaddr_in from; - int fromlen, i; - struct hostent *hp; + struct sockaddr_storage from; + int i; + socklen_t fromlen; + struct addrinfo hints, *ai, *aitop; char name[MAXHOSTNAMELEN]; + char ntop[NI_MAXHOST], ntop2[NI_MAXHOST]; /* Get IP address of client. */ fromlen = sizeof(from); @@ -40,20 +42,15 @@ get_remote_hostname(int socket) debug("getpeername failed: %.100s", strerror(errno)); fatal_cleanup(); } - /* Map the IP address to a host name. */ - hp = gethostbyaddr((char *) &from.sin_addr, sizeof(struct in_addr), - from.sin_family); - if (hp) { - /* Got host name, find canonic host name. */ - if (strchr(hp->h_name, '.') != 0) - strlcpy(name, hp->h_name, sizeof(name)); - else if (hp->h_aliases != 0 - && hp->h_aliases[0] != 0 - && strchr(hp->h_aliases[0], '.') != 0) - strlcpy(name, hp->h_aliases[0], sizeof(name)); - else - strlcpy(name, hp->h_name, sizeof(name)); + if (getnameinfo((struct sockaddr *)&from, fromlen, ntop, sizeof(ntop), + NULL, 0, NI_NUMERICHOST) != 0) + fatal("get_remote_hostname: getnameinfo NI_NUMERICHOST failed"); + /* Map the IP address to a host name. */ + if (getnameinfo((struct sockaddr *)&from, fromlen, name, sizeof(name), + NULL, 0, NI_NAMEREQD) == 0) { + /* Got host name. */ + name[sizeof(name) - 1] = '\0'; /* * Convert it to all lowercase (which is expected by the rest * of this software). @@ -71,32 +68,34 @@ get_remote_hostname(int socket) * fooled if the intruder has access to the name server of * the domain). */ - hp = gethostbyname(name); - if (!hp) { - log("reverse mapping checking gethostbyname for %.700s failed - POSSIBLE BREAKIN ATTEMPT!", name); - strlcpy(name, inet_ntoa(from.sin_addr), sizeof name); + memset(&hints, 0, sizeof(hints)); + hints.ai_family = from.ss_family; + hints.ai_socktype = SOCK_STREAM; + if (getaddrinfo(name, NULL, &hints, &aitop) != 0) { + log("reverse mapping checking getaddrinfo for %.700s failed - POSSIBLE BREAKIN ATTEMPT!", name); + strlcpy(name, ntop, sizeof name); goto check_ip_options; } /* Look for the address from the list of addresses. */ - for (i = 0; hp->h_addr_list[i]; i++) - if (memcmp(hp->h_addr_list[i], &from.sin_addr, sizeof(from.sin_addr)) - == 0) - break; - /* - * If we reached the end of the list, the address was not - * there. - */ - if (!hp->h_addr_list[i]) { + for (ai = aitop; ai; ai = ai->ai_next) { + if (getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop2, + sizeof(ntop2), NULL, 0, NI_NUMERICHOST) == 0 && + (strcmp(ntop, ntop2) == 0)) + break; + } + freeaddrinfo(aitop); + /* If we reached the end of the list, the address was not there. */ + if (!ai) { /* Address not found for the host name. */ log("Address %.100s maps to %.600s, but this does not map back to the address - POSSIBLE BREAKIN ATTEMPT!", - inet_ntoa(from.sin_addr), name); - strlcpy(name, inet_ntoa(from.sin_addr), sizeof name); + ntop, name); + strlcpy(name, ntop, sizeof name); goto check_ip_options; } /* Address was found for the host name. We accept the host name. */ } else { /* Host name not found. Use ascii representation of the address. */ - strlcpy(name, inet_ntoa(from.sin_addr), sizeof name); + strlcpy(name, ntop, sizeof name); log("Could not reverse map address %.100s.", name); } @@ -113,10 +112,12 @@ check_ip_options: * rest of the interaction and could still bypass security. So we * exit here if we detect any IP options. */ - { + /* IP options -- IPv4 only */ + if (from.ss_family == AF_INET) { unsigned char options[200], *ucp; char text[1024], *cp; - int option_size, ipproto; + socklen_t option_size; + int ipproto; struct protoent *ip; if ((ip = getprotobyname("ip")) != NULL) @@ -125,47 +126,21 @@ check_ip_options: ipproto = IPPROTO_IP; option_size = sizeof(options); if (getsockopt(0, ipproto, IP_OPTIONS, (char *) options, - &option_size) >= 0 && option_size != 0) { + &option_size) >= 0 && option_size != 0) { cp = text; /* Note: "text" buffer must be at least 3x as big as options. */ for (ucp = options; option_size > 0; ucp++, option_size--, cp += 3) sprintf(cp, " %2.2x", *ucp); log("Connection from %.100s with IP options:%.800s", - inet_ntoa(from.sin_addr), text); + ntop, text); packet_disconnect("Connection from %.100s with IP options:%.800s", - inet_ntoa(from.sin_addr), text); + ntop, text); } } return xstrdup(name); } -static char *canonical_host_name = NULL; -static char *canonical_host_ip = NULL; - -/* Returns 1 if remote host is connected via socket, 0 if not. */ - -int -peer_connection_is_on_socket() -{ - struct sockaddr_in from; - int fromlen; - int in = packet_get_connection_in(); - int out = packet_get_connection_out(); - - /* filedescriptors in and out are the same, so it's a socket */ - if (in == out) - return 1; - fromlen = sizeof(from); - memset(&from, 0, sizeof(from)); - if (getpeername(in, (struct sockaddr *) & from, &fromlen) < 0) - return 0; - if (from.sin_family != AF_INET) - return 0; - - return 1; -} - /* * Return the canonical name of the host in the other side of the current * connection. The host name is cached, so it is efficient to call this @@ -175,12 +150,14 @@ peer_connection_is_on_socket() const char * get_canonical_hostname() { + static char *canonical_host_name = NULL; + /* Check if we have previously retrieved this same name. */ if (canonical_host_name != NULL) return canonical_host_name; /* Get the real hostname if socket; otherwise return UNKNOWN. */ - if (peer_connection_is_on_socket()) + if (packet_connection_is_on_socket()) canonical_host_name = get_remote_hostname(packet_get_connection_in()); else canonical_host_name = xstrdup("UNKNOWN"); @@ -190,21 +167,24 @@ get_canonical_hostname() /* * Returns the IP-address of the remote host as a string. The returned - * string need not be freed. + * string must not be freed. */ const char * get_remote_ipaddr() { - struct sockaddr_in from; - int fromlen, socket; + static char *canonical_host_ip = NULL; + struct sockaddr_storage from; + socklen_t fromlen; + int socket; + char ntop[NI_MAXHOST]; /* Check whether we have chached the name. */ if (canonical_host_ip != NULL) return canonical_host_ip; /* If not a socket, return UNKNOWN. */ - if (!peer_connection_is_on_socket()) { + if (!packet_connection_is_on_socket()) { canonical_host_ip = xstrdup("UNKNOWN"); return canonical_host_ip; } @@ -219,48 +199,76 @@ get_remote_ipaddr() fatal_cleanup(); } /* Get the IP address in ascii. */ - canonical_host_ip = xstrdup(inet_ntoa(from.sin_addr)); + if (getnameinfo((struct sockaddr *)&from, fromlen, ntop, sizeof(ntop), + NULL, 0, NI_NUMERICHOST) != 0) + fatal("get_remote_hostname: getnameinfo NI_NUMERICHOST failed"); + + canonical_host_ip = xstrdup(ntop); /* Return ip address string. */ return canonical_host_ip; } -/* Returns the port of the peer of the socket. */ +/* Returns the local/remote port for the socket. */ -int -get_peer_port(int sock) +int +get_sock_port(int sock, int local) { - struct sockaddr_in from; - int fromlen; + struct sockaddr_storage from; + socklen_t fromlen; + char strport[NI_MAXSERV]; /* Get IP address of client. */ fromlen = sizeof(from); memset(&from, 0, sizeof(from)); - if (getpeername(sock, (struct sockaddr *) & from, &fromlen) < 0) { - debug("getpeername failed: %.100s", strerror(errno)); - fatal_cleanup(); + if (local) { + if (getsockname(sock, (struct sockaddr *)&from, &fromlen) < 0) { + error("getsockname failed: %.100s", strerror(errno)); + return 0; + } + } else { + if (getpeername(sock, (struct sockaddr *) & from, &fromlen) < 0) { + debug("getpeername failed: %.100s", strerror(errno)); + fatal_cleanup(); + } } /* Return port number. */ - return ntohs(from.sin_port); + if (getnameinfo((struct sockaddr *)&from, fromlen, NULL, 0, + strport, sizeof(strport), NI_NUMERICSERV) != 0) + fatal("get_sock_port: getnameinfo NI_NUMERICSERV failed"); + return atoi(strport); } -/* Returns the port number of the remote host. */ +/* Returns remote/local port number for the current connection. */ int -get_remote_port() +get_port(int local) { - int socket; - /* * If the connection is not a socket, return 65535. This is * intentionally chosen to be an unprivileged port number. */ - if (!peer_connection_is_on_socket()) + if (!packet_connection_is_on_socket()) return 65535; - /* Get client socket. */ - socket = packet_get_connection_in(); + /* Get socket and return the port number. */ + return get_sock_port(packet_get_connection_in(), local); +} + +int +get_peer_port(int sock) +{ + return get_sock_port(sock, 0); +} - /* Get and return the peer port number. */ - return get_peer_port(socket); +int +get_remote_port() +{ + return get_port(0); +} + +int +get_local_port() +{ + return get_port(1); } @@ -16,7 +16,7 @@ */ #include "includes.h" -RCSID("$Id: channels.c,v 1.14 1999/12/27 12:54:55 damien Exp $"); +RCSID("$Id: channels.c,v 1.15 2000/01/14 04:45:48 damien Exp $"); #include "ssh.h" #include "packet.h" |