mirror of
git://anongit.mindrot.org/openssh.git
synced 2025-02-16 13:56:52 +00:00
- 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
This commit is contained in:
parent
25e4256ad4
commit
34132e54cb
33
ChangeLog
33
ChangeLog
@ -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
|
||||
|
||||
|
60
Makefile.in
60
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
|
||||
TARGETS=ssh sshd ssh-add ssh-keygen ssh-agent scp $(EXTRA_TARGETS)
|
||||
|
||||
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
|
||||
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
|
||||
|
||||
|
2
TODO
2
TODO
@ -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
|
||||
|
28
acconfig.h
28
acconfig.h
@ -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
|
||||
|
116
bsd-bindresvport.c
Normal file
116
bsd-bindresvport.c
Normal file
@ -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 */
|
10
bsd-bindresvport.h
Normal file
10
bsd-bindresvport.h
Normal file
@ -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 */
|
107
bsd-rresvport.c
Normal file
107
bsd-rresvport.c
Normal file
@ -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 */
|
10
bsd-rresvport.h
Normal file
10
bsd-rresvport.h
Normal file
@ -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 */
|
186
canohost.c
186
canohost.c
@ -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 and return the peer port number. */
|
||||
return get_peer_port(socket);
|
||||
/* 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);
|
||||
}
|
||||
|
||||
int
|
||||
get_remote_port()
|
||||
{
|
||||
return get_port(0);
|
||||
}
|
||||
|
||||
int
|
||||
get_local_port()
|
||||
{
|
||||
return get_port(1);
|
||||
}
|
||||
|
386
channels.c
386
channels.c
@ -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"
|
||||
@ -374,7 +374,8 @@ void
|
||||
channel_after_select(fd_set * readset, fd_set * writeset)
|
||||
{
|
||||
struct sockaddr addr;
|
||||
int addrlen, newsock, i, newch, len;
|
||||
int newsock, i, newch, len;
|
||||
socklen_t addrlen;
|
||||
Channel *ch;
|
||||
char buf[16384], *remote_hostname;
|
||||
|
||||
@ -412,7 +413,7 @@ channel_after_select(fd_set * readset, fd_set * writeset)
|
||||
* forwarded TCP/IP port.
|
||||
*/
|
||||
if (FD_ISSET(ch->sock, readset)) {
|
||||
debug("Connection to port %d forwarding to %.100s:%d requested.",
|
||||
debug("Connection to port %d forwarding to %.100s port %d requested.",
|
||||
ch->listening_port, ch->path, ch->host_port);
|
||||
addrlen = sizeof(addr);
|
||||
newsock = accept(ch->sock, &addr, &addrlen);
|
||||
@ -421,7 +422,7 @@ channel_after_select(fd_set * readset, fd_set * writeset)
|
||||
break;
|
||||
}
|
||||
remote_hostname = get_remote_hostname(newsock);
|
||||
snprintf(buf, sizeof buf, "listen port %d:%.100s:%d, connect from %.200s:%d",
|
||||
snprintf(buf, sizeof buf, "listen port %d for %.100s port %d, connect from %.200s port %d",
|
||||
ch->listening_port, ch->path, ch->host_port,
|
||||
remote_hostname, get_peer_port(newsock));
|
||||
xfree(remote_hostname);
|
||||
@ -532,10 +533,19 @@ channel_output_poll()
|
||||
|
||||
for (i = 0; i < channels_alloc; i++) {
|
||||
ch = &channels[i];
|
||||
|
||||
/* We are only interested in channels that can have buffered incoming data. */
|
||||
if (ch->type != SSH_CHANNEL_OPEN &&
|
||||
ch->type != SSH_CHANNEL_INPUT_DRAINING)
|
||||
continue;
|
||||
if (compat13) {
|
||||
if (ch->type != SSH_CHANNEL_OPEN &&
|
||||
ch->type != SSH_CHANNEL_INPUT_DRAINING)
|
||||
continue;
|
||||
} else {
|
||||
if (ch->type != SSH_CHANNEL_OPEN)
|
||||
continue;
|
||||
if (ch->istate != CHAN_INPUT_OPEN &&
|
||||
ch->istate != CHAN_INPUT_WAIT_DRAIN)
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Get the amount of buffered data for this channel. */
|
||||
len = buffer_len(&ch->input);
|
||||
@ -575,25 +585,33 @@ channel_output_poll()
|
||||
void
|
||||
channel_input_data(int payload_len)
|
||||
{
|
||||
int channel;
|
||||
int id;
|
||||
char *data;
|
||||
unsigned int data_len;
|
||||
Channel *ch;
|
||||
|
||||
/* Get the channel number and verify it. */
|
||||
channel = packet_get_int();
|
||||
if (channel < 0 || channel >= channels_alloc ||
|
||||
channels[channel].type == SSH_CHANNEL_FREE)
|
||||
packet_disconnect("Received data for nonexistent channel %d.", channel);
|
||||
id = packet_get_int();
|
||||
if (id < 0 || id >= channels_alloc)
|
||||
packet_disconnect("Received data for nonexistent channel %d.", id);
|
||||
ch = &channels[id];
|
||||
|
||||
if (ch->type == SSH_CHANNEL_FREE)
|
||||
packet_disconnect("Received data for free channel %d.", ch->self);
|
||||
|
||||
/* Ignore any data for non-open channels (might happen on close) */
|
||||
if (channels[channel].type != SSH_CHANNEL_OPEN &&
|
||||
channels[channel].type != SSH_CHANNEL_X11_OPEN)
|
||||
if (ch->type != SSH_CHANNEL_OPEN &&
|
||||
ch->type != SSH_CHANNEL_X11_OPEN)
|
||||
return;
|
||||
|
||||
/* same for protocol 1.5 if output end is no longer open */
|
||||
if (!compat13 && ch->ostate != CHAN_OUTPUT_OPEN)
|
||||
return;
|
||||
|
||||
/* Get the data. */
|
||||
data = packet_get_string(&data_len);
|
||||
packet_integrity_check(payload_len, 4 + 4 + data_len, SSH_MSG_CHANNEL_DATA);
|
||||
buffer_append(&channels[channel].output, data, data_len);
|
||||
buffer_append(&ch->output, data, data_len);
|
||||
xfree(data);
|
||||
}
|
||||
|
||||
@ -610,23 +628,11 @@ channel_not_very_much_buffered_data()
|
||||
|
||||
for (i = 0; i < channels_alloc; i++) {
|
||||
ch = &channels[i];
|
||||
switch (ch->type) {
|
||||
case SSH_CHANNEL_X11_LISTENER:
|
||||
case SSH_CHANNEL_PORT_LISTENER:
|
||||
case SSH_CHANNEL_AUTH_SOCKET:
|
||||
continue;
|
||||
case SSH_CHANNEL_OPEN:
|
||||
if (ch->type == SSH_CHANNEL_OPEN) {
|
||||
if (buffer_len(&ch->input) > packet_get_maxsize())
|
||||
return 0;
|
||||
if (buffer_len(&ch->output) > packet_get_maxsize())
|
||||
return 0;
|
||||
continue;
|
||||
case SSH_CHANNEL_INPUT_DRAINING:
|
||||
case SSH_CHANNEL_OUTPUT_DRAINING:
|
||||
case SSH_CHANNEL_X11_OPEN:
|
||||
case SSH_CHANNEL_FREE:
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
@ -853,9 +859,11 @@ channel_open_message()
|
||||
case SSH_CHANNEL_X11_OPEN:
|
||||
case SSH_CHANNEL_INPUT_DRAINING:
|
||||
case SSH_CHANNEL_OUTPUT_DRAINING:
|
||||
snprintf(buf, sizeof buf, " #%d %.300s (t%d r%d i%d o%d)\r\n",
|
||||
c->self, c->remote_name,
|
||||
c->type, c->remote_id, c->istate, c->ostate);
|
||||
snprintf(buf, sizeof buf, " #%d %.300s (t%d r%d i%d/%d o%d/%d)\r\n",
|
||||
c->self, c->remote_name,
|
||||
c->type, c->remote_id,
|
||||
c->istate, buffer_len(&c->input),
|
||||
c->ostate, buffer_len(&c->output));
|
||||
buffer_append(&buffer, buf, strlen(buf));
|
||||
continue;
|
||||
default:
|
||||
@ -878,50 +886,76 @@ void
|
||||
channel_request_local_forwarding(u_short port, const char *host,
|
||||
u_short host_port, int gateway_ports)
|
||||
{
|
||||
int ch, sock, on = 1;
|
||||
struct sockaddr_in sin;
|
||||
int success, ch, sock, on = 1;
|
||||
struct addrinfo hints, *ai, *aitop;
|
||||
char ntop[NI_MAXHOST], strport[NI_MAXSERV];
|
||||
struct linger linger;
|
||||
|
||||
if (strlen(host) > sizeof(channels[0].path) - 1)
|
||||
packet_disconnect("Forward host name too long.");
|
||||
|
||||
/* Create a port to listen for the host. */
|
||||
sock = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if (sock < 0)
|
||||
packet_disconnect("socket: %.100s", strerror(errno));
|
||||
|
||||
/* Initialize socket address. */
|
||||
memset(&sin, 0, sizeof(sin));
|
||||
sin.sin_family = AF_INET;
|
||||
if (gateway_ports == 1)
|
||||
sin.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
else
|
||||
sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
|
||||
sin.sin_port = htons(port);
|
||||
|
||||
/*
|
||||
* Set socket options. We would like the socket to disappear as soon
|
||||
* as it has been closed for whatever reason.
|
||||
* getaddrinfo returns a loopback address if the hostname is
|
||||
* set to NULL and hints.ai_flags is not AI_PASSIVE
|
||||
*/
|
||||
setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void *)&on, sizeof(on));
|
||||
linger.l_onoff = 1;
|
||||
linger.l_linger = 5;
|
||||
setsockopt(sock, SOL_SOCKET, SO_LINGER, (void *) &linger, sizeof(linger));
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_family = IPv4or6;
|
||||
hints.ai_flags = gateway_ports ? AI_PASSIVE : 0;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
snprintf(strport, sizeof strport, "%d", port);
|
||||
if (getaddrinfo(NULL, strport, &hints, &aitop) != 0)
|
||||
packet_disconnect("getaddrinfo: fatal error");
|
||||
|
||||
/* Bind the socket to the address. */
|
||||
if (bind(sock, (struct sockaddr *) & sin, sizeof(sin)) < 0)
|
||||
packet_disconnect("bind: %.100s", strerror(errno));
|
||||
success = 0;
|
||||
for (ai = aitop; ai; ai = ai->ai_next) {
|
||||
if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6)
|
||||
continue;
|
||||
if (getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop, sizeof(ntop),
|
||||
strport, sizeof(strport), NI_NUMERICHOST|NI_NUMERICSERV) != 0) {
|
||||
error("channel_request_local_forwarding: getnameinfo failed");
|
||||
continue;
|
||||
}
|
||||
/* Create a port to listen for the host. */
|
||||
sock = socket(ai->ai_family, SOCK_STREAM, 0);
|
||||
if (sock < 0) {
|
||||
/* this is no error since kernel may not support ipv6 */
|
||||
verbose("socket: %.100s", strerror(errno));
|
||||
continue;
|
||||
}
|
||||
/*
|
||||
* Set socket options. We would like the socket to disappear
|
||||
* as soon as it has been closed for whatever reason.
|
||||
*/
|
||||
setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void *)&on, sizeof(on));
|
||||
linger.l_onoff = 1;
|
||||
linger.l_linger = 5;
|
||||
setsockopt(sock, SOL_SOCKET, SO_LINGER, (void *)&linger, sizeof(linger));
|
||||
debug("Local forwarding listening on %s port %s.", ntop, strport);
|
||||
|
||||
/* Start listening for connections on the socket. */
|
||||
if (listen(sock, 5) < 0)
|
||||
packet_disconnect("listen: %.100s", strerror(errno));
|
||||
|
||||
/* Allocate a channel number for the socket. */
|
||||
ch = channel_allocate(SSH_CHANNEL_PORT_LISTENER, sock,
|
||||
xstrdup("port listener"));
|
||||
strlcpy(channels[ch].path, host, sizeof(channels[ch].path));
|
||||
channels[ch].host_port = host_port;
|
||||
channels[ch].listening_port = port;
|
||||
/* Bind the socket to the address. */
|
||||
if (bind(sock, ai->ai_addr, ai->ai_addrlen) < 0) {
|
||||
/* address can be in use ipv6 address is already bound */
|
||||
verbose("bind: %.100s", strerror(errno));
|
||||
close(sock);
|
||||
continue;
|
||||
}
|
||||
/* Start listening for connections on the socket. */
|
||||
if (listen(sock, 5) < 0) {
|
||||
error("listen: %.100s", strerror(errno));
|
||||
close(sock);
|
||||
continue;
|
||||
}
|
||||
/* Allocate a channel number for the socket. */
|
||||
ch = channel_allocate(SSH_CHANNEL_PORT_LISTENER, sock,
|
||||
xstrdup("port listener"));
|
||||
strlcpy(channels[ch].path, host, sizeof(channels[ch].path));
|
||||
channels[ch].host_port = host_port;
|
||||
channels[ch].listening_port = port;
|
||||
success = 1;
|
||||
}
|
||||
if (success == 0)
|
||||
packet_disconnect("cannot listen port: %d", port);
|
||||
freeaddrinfo(aitop);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1000,12 +1034,13 @@ channel_input_port_forward_request(int is_root)
|
||||
void
|
||||
channel_input_port_open(int payload_len)
|
||||
{
|
||||
int remote_channel, sock, newch, i;
|
||||
int remote_channel, sock = 0, newch, i;
|
||||
u_short host_port;
|
||||
struct sockaddr_in sin;
|
||||
char *host, *originator_string;
|
||||
struct hostent *hp;
|
||||
int host_len, originator_len;
|
||||
struct addrinfo hints, *ai, *aitop;
|
||||
char ntop[NI_MAXHOST], strport[NI_MAXSERV];
|
||||
int gaierr;
|
||||
|
||||
/* Get remote channel number. */
|
||||
remote_channel = packet_get_int();
|
||||
@ -1047,41 +1082,47 @@ channel_input_port_open(int payload_len)
|
||||
packet_send();
|
||||
}
|
||||
}
|
||||
memset(&sin, 0, sizeof(sin));
|
||||
sin.sin_addr.s_addr = inet_addr(host);
|
||||
if ((sin.sin_addr.s_addr & 0xffffffff) != 0xffffffff) {
|
||||
/* It was a valid numeric host address. */
|
||||
sin.sin_family = AF_INET;
|
||||
} else {
|
||||
/* Look up the host address from the name servers. */
|
||||
hp = gethostbyname(host);
|
||||
if (!hp) {
|
||||
error("%.100s: unknown host.", host);
|
||||
goto fail;
|
||||
}
|
||||
if (!hp->h_addr_list[0]) {
|
||||
error("%.100s: host has no IP address.", host);
|
||||
goto fail;
|
||||
}
|
||||
sin.sin_family = hp->h_addrtype;
|
||||
memcpy(&sin.sin_addr, hp->h_addr_list[0],
|
||||
sizeof(sin.sin_addr));
|
||||
}
|
||||
sin.sin_port = htons(host_port);
|
||||
|
||||
/* Create the socket. */
|
||||
sock = socket(sin.sin_family, SOCK_STREAM, 0);
|
||||
if (sock < 0) {
|
||||
error("socket: %.100s", strerror(errno));
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_family = IPv4or6;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
snprintf(strport, sizeof strport, "%d", host_port);
|
||||
if ((gaierr = getaddrinfo(host, strport, &hints, &aitop)) != 0) {
|
||||
error("%.100s: unknown host (%s)", host, gai_strerror(gaierr));
|
||||
goto fail;
|
||||
}
|
||||
/* Connect to the host/port. */
|
||||
if (connect(sock, (struct sockaddr *) & sin, sizeof(sin)) < 0) {
|
||||
error("connect %.100s:%d: %.100s", host, host_port,
|
||||
strerror(errno));
|
||||
close(sock);
|
||||
|
||||
for (ai = aitop; ai; ai = ai->ai_next) {
|
||||
if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6)
|
||||
continue;
|
||||
if (getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop, sizeof(ntop),
|
||||
strport, sizeof(strport), NI_NUMERICHOST|NI_NUMERICSERV) != 0) {
|
||||
error("channel_input_port_open: getnameinfo failed");
|
||||
continue;
|
||||
}
|
||||
/* Create the socket. */
|
||||
sock = socket(ai->ai_family, SOCK_STREAM, 0);
|
||||
if (sock < 0) {
|
||||
error("socket: %.100s", strerror(errno));
|
||||
continue;
|
||||
}
|
||||
/* Connect to the host/port. */
|
||||
if (connect(sock, ai->ai_addr, ai->ai_addrlen) < 0) {
|
||||
error("connect %.100s port %s: %.100s", ntop, strport,
|
||||
strerror(errno));
|
||||
close(sock);
|
||||
continue; /* fail -- try next */
|
||||
}
|
||||
break; /* success */
|
||||
|
||||
}
|
||||
freeaddrinfo(aitop);
|
||||
|
||||
if (!ai) {
|
||||
error("connect %.100s port %d: failed.", host, host_port);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Successful connection. */
|
||||
|
||||
/* Allocate a channel for this connection. */
|
||||
@ -1115,48 +1156,73 @@ fail:
|
||||
* occurs.
|
||||
*/
|
||||
|
||||
#define NUM_SOCKS 10
|
||||
|
||||
char *
|
||||
x11_create_display_inet(int screen_number, int x11_display_offset)
|
||||
{
|
||||
int display_number, sock;
|
||||
u_short port;
|
||||
struct sockaddr_in sin;
|
||||
char buf[512];
|
||||
struct addrinfo hints, *ai, *aitop;
|
||||
char strport[NI_MAXSERV];
|
||||
int gaierr, n, num_socks = 0, socks[NUM_SOCKS];
|
||||
char display[512];
|
||||
char hostname[MAXHOSTNAMELEN];
|
||||
|
||||
for (display_number = x11_display_offset;
|
||||
display_number < MAX_DISPLAYS;
|
||||
display_number++) {
|
||||
port = 6000 + display_number;
|
||||
memset(&sin, 0, sizeof(sin));
|
||||
sin.sin_family = AF_INET;
|
||||
sin.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
sin.sin_port = htons(port);
|
||||
|
||||
sock = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if (sock < 0) {
|
||||
error("socket: %.100s", strerror(errno));
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_family = IPv4or6;
|
||||
hints.ai_flags = AI_PASSIVE; /* XXX loopback only ? */
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
snprintf(strport, sizeof strport, "%d", port);
|
||||
if ((gaierr = getaddrinfo(NULL, strport, &hints, &aitop)) != 0) {
|
||||
error("getaddrinfo: %.100s", gai_strerror(gaierr));
|
||||
return NULL;
|
||||
}
|
||||
if (bind(sock, (struct sockaddr *) & sin, sizeof(sin)) < 0) {
|
||||
debug("bind port %d: %.100s", port, strerror(errno));
|
||||
shutdown(sock, SHUT_RDWR);
|
||||
close(sock);
|
||||
continue;
|
||||
for (ai = aitop; ai; ai = ai->ai_next) {
|
||||
if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6)
|
||||
continue;
|
||||
sock = socket(ai->ai_family, SOCK_STREAM, 0);
|
||||
if (sock < 0) {
|
||||
error("socket: %.100s", strerror(errno));
|
||||
return NULL;
|
||||
}
|
||||
if (bind(sock, ai->ai_addr, ai->ai_addrlen) < 0) {
|
||||
debug("bind port %d: %.100s", port, strerror(errno));
|
||||
shutdown(sock, SHUT_RDWR);
|
||||
close(sock);
|
||||
for (n = 0; n < num_socks; n++) {
|
||||
shutdown(socks[n], SHUT_RDWR);
|
||||
close(socks[n]);
|
||||
}
|
||||
num_socks = 0;
|
||||
break;
|
||||
}
|
||||
socks[num_socks++] = sock;
|
||||
if (num_socks == NUM_SOCKS)
|
||||
break;
|
||||
}
|
||||
break;
|
||||
if (num_socks > 0)
|
||||
break;
|
||||
}
|
||||
if (display_number >= MAX_DISPLAYS) {
|
||||
error("Failed to allocate internet-domain X11 display socket.");
|
||||
return NULL;
|
||||
}
|
||||
/* Start listening for connections on the socket. */
|
||||
if (listen(sock, 5) < 0) {
|
||||
error("listen: %.100s", strerror(errno));
|
||||
shutdown(sock, SHUT_RDWR);
|
||||
close(sock);
|
||||
return NULL;
|
||||
for (n = 0; n < num_socks; n++) {
|
||||
sock = socks[n];
|
||||
if (listen(sock, 5) < 0) {
|
||||
error("listen: %.100s", strerror(errno));
|
||||
shutdown(sock, SHUT_RDWR);
|
||||
close(sock);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Set up a suitable value for the DISPLAY variable. */
|
||||
|
||||
if (gethostname(hostname, sizeof(hostname)) < 0)
|
||||
@ -1192,21 +1258,24 @@ x11_create_display_inet(int screen_number, int x11_display_offset)
|
||||
memcpy(&my_addr, he->h_addr_list[0], sizeof(struct in_addr));
|
||||
|
||||
/* Set DISPLAY to <ip address>:screen.display */
|
||||
snprintf(buf, sizeof(buf), "%.50s:%d.%d", inet_ntoa(my_addr),
|
||||
snprintf(display, sizeof(display), "%.50s:%d.%d", inet_ntoa(my_addr),
|
||||
display_number, screen_number);
|
||||
}
|
||||
#else /* IPADDR_IN_DISPLAY */
|
||||
/* Just set DISPLAY to hostname:screen.display */
|
||||
snprintf(buf, sizeof buf, "%.400s:%d.%d", hostname,
|
||||
snprintf(display, sizeof display, "%.400s:%d.%d", hostname,
|
||||
display_number, screen_number);
|
||||
#endif /* IPADDR_IN_DISPLAY */
|
||||
|
||||
/* Allocate a channel for the socket. */
|
||||
(void) channel_allocate(SSH_CHANNEL_X11_LISTENER, sock,
|
||||
xstrdup("X11 inet listener"));
|
||||
/* Allocate a channel for each socket. */
|
||||
for (n = 0; n < num_socks; n++) {
|
||||
sock = socks[n];
|
||||
(void) channel_allocate(SSH_CHANNEL_X11_LISTENER, sock,
|
||||
xstrdup("X11 inet listener"));
|
||||
}
|
||||
|
||||
/* Return a suitable value for the DISPLAY environment variable. */
|
||||
return xstrdup(buf);
|
||||
return xstrdup(display);
|
||||
}
|
||||
|
||||
#ifndef X_UNIX_PATH
|
||||
@ -1252,12 +1321,13 @@ connect_local_xsocket(unsigned int dnr)
|
||||
void
|
||||
x11_input_open(int payload_len)
|
||||
{
|
||||
int remote_channel, display_number, sock, newch;
|
||||
int remote_channel, display_number, sock = 0, newch;
|
||||
const char *display;
|
||||
struct sockaddr_in sin;
|
||||
char buf[1024], *cp, *remote_host;
|
||||
struct hostent *hp;
|
||||
int remote_len;
|
||||
struct addrinfo hints, *ai, *aitop;
|
||||
char strport[NI_MAXSERV];
|
||||
int gaierr;
|
||||
|
||||
/* Get remote channel number. */
|
||||
remote_channel = packet_get_int();
|
||||
@ -1323,42 +1393,38 @@ x11_input_open(int payload_len)
|
||||
display);
|
||||
goto fail;
|
||||
}
|
||||
/* Try to parse the host name as a numeric IP address. */
|
||||
memset(&sin, 0, sizeof(sin));
|
||||
sin.sin_addr.s_addr = inet_addr(buf);
|
||||
if ((sin.sin_addr.s_addr & 0xffffffff) != 0xffffffff) {
|
||||
/* It was a valid numeric host address. */
|
||||
sin.sin_family = AF_INET;
|
||||
} else {
|
||||
/* Not a numeric IP address. */
|
||||
/* Look up the host address from the name servers. */
|
||||
hp = gethostbyname(buf);
|
||||
if (!hp) {
|
||||
error("%.100s: unknown host.", buf);
|
||||
goto fail;
|
||||
}
|
||||
if (!hp->h_addr_list[0]) {
|
||||
error("%.100s: host has no IP address.", buf);
|
||||
goto fail;
|
||||
}
|
||||
sin.sin_family = hp->h_addrtype;
|
||||
memcpy(&sin.sin_addr, hp->h_addr_list[0],
|
||||
sizeof(sin.sin_addr));
|
||||
}
|
||||
/* Set port number. */
|
||||
sin.sin_port = htons(6000 + display_number);
|
||||
|
||||
/* Create a socket. */
|
||||
sock = socket(sin.sin_family, SOCK_STREAM, 0);
|
||||
if (sock < 0) {
|
||||
error("socket: %.100s", strerror(errno));
|
||||
/* Look up the host address */
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_family = IPv4or6;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
snprintf(strport, sizeof strport, "%d", 6000 + display_number);
|
||||
if ((gaierr = getaddrinfo(buf, strport, &hints, &aitop)) != 0) {
|
||||
error("%.100s: unknown host. (%s)", buf, gai_strerror(gaierr));
|
||||
goto fail;
|
||||
}
|
||||
for (ai = aitop; ai; ai = ai->ai_next) {
|
||||
/* Create a socket. */
|
||||
sock = socket(ai->ai_family, SOCK_STREAM, 0);
|
||||
if (sock < 0) {
|
||||
debug("socket: %.100s", strerror(errno));
|
||||
continue;
|
||||
}
|
||||
/* Connect it to the display. */
|
||||
if (connect(sock, (struct sockaddr *) & sin, sizeof(sin)) < 0) {
|
||||
error("connect %.100s:%d: %.100s", buf, 6000 + display_number,
|
||||
strerror(errno));
|
||||
if (connect(sock, ai->ai_addr, ai->ai_addrlen) < 0) {
|
||||
debug("connect %.100s port %d: %.100s", buf, 6000 + display_number,
|
||||
strerror(errno));
|
||||
close(sock);
|
||||
continue;
|
||||
}
|
||||
/* Success */
|
||||
break;
|
||||
|
||||
} /* (ai = aitop, ai; ai = ai->ai_next) */
|
||||
freeaddrinfo(aitop);
|
||||
if (!ai) {
|
||||
error("connect %.100s port %d: %.100s", buf, 6000 + display_number,
|
||||
strerror(errno));
|
||||
goto fail;
|
||||
}
|
||||
success:
|
||||
|
88
configure.in
88
configure.in
@ -128,7 +128,7 @@ dnl Checks for header files.
|
||||
AC_CHECK_HEADERS(bstring.h endian.h lastlog.h login.h maillock.h netdb.h netgroup.h paths.h poll.h pty.h shadow.h security/pam_appl.h sys/bsdtty.h sys/cdefs.h sys/poll.h sys/select.h sys/stropts.h sys/time.h sys/ttcompat.h util.h utmp.h utmpx.h)
|
||||
|
||||
dnl Checks for library functions.
|
||||
AC_CHECK_FUNCS(arc4random getpagesize _getpty innetgr md5_crypt mkdtemp openpty setenv seteuid setlogin setproctitle setreuid snprintf strlcat strlcpy updwtmpx vsnprintf)
|
||||
AC_CHECK_FUNCS(arc4random bindresvport_af freeaddrinfo gai_strerror getaddrinfo getpagesize getnameinfo _getpty innetgr md5_crypt mkdtemp openpty rresvport_af setenv seteuid setlogin setproctitle setreuid snprintf strlcat strlcpy updwtmpx vsnprintf)
|
||||
|
||||
AC_CHECK_FUNC(login,
|
||||
[AC_DEFINE(HAVE_LOGIN)],
|
||||
@ -169,7 +169,7 @@ AC_TRY_COMPILE(
|
||||
[AC_MSG_RESULT(no)]
|
||||
)
|
||||
|
||||
AC_MSG_CHECKING([For uintXX_t types])
|
||||
AC_MSG_CHECKING([for uintXX_t types])
|
||||
AC_TRY_COMPILE(
|
||||
[#include <sys/types.h>],
|
||||
[uint16_t c; uint32_t d; c = 1235; d = 1235;],
|
||||
@ -180,7 +180,7 @@ AC_TRY_COMPILE(
|
||||
[AC_MSG_RESULT(no)]
|
||||
)
|
||||
|
||||
AC_MSG_CHECKING([For socklen_t])
|
||||
AC_MSG_CHECKING([for socklen_t])
|
||||
AC_TRY_COMPILE(
|
||||
[
|
||||
#include <sys/types.h>
|
||||
@ -194,7 +194,7 @@ AC_TRY_COMPILE(
|
||||
[AC_MSG_RESULT(no)]
|
||||
)
|
||||
|
||||
AC_MSG_CHECKING([For size_t])
|
||||
AC_MSG_CHECKING([for size_t])
|
||||
AC_TRY_COMPILE(
|
||||
[#include <sys/types.h>],
|
||||
[size_t foo; foo = 1235;],
|
||||
@ -205,6 +205,53 @@ AC_TRY_COMPILE(
|
||||
[AC_MSG_RESULT(no)]
|
||||
)
|
||||
|
||||
AC_MSG_CHECKING([for struct sockaddr_storage])
|
||||
AC_TRY_COMPILE(
|
||||
[#include <sys/socket.h>],
|
||||
[struct sockaddr_storage s;],
|
||||
[
|
||||
AC_DEFINE(HAVE_STRUCT_SOCKADDR_STORAGE)
|
||||
AC_MSG_RESULT(yes)
|
||||
],
|
||||
[AC_MSG_RESULT(no)]
|
||||
)
|
||||
|
||||
AC_MSG_CHECKING([for struct sockaddr_in6])
|
||||
AC_TRY_COMPILE(
|
||||
[#include <netinet/in.h>],
|
||||
[struct sockaddr_in6 s; s.sin6_family = 0;],
|
||||
[
|
||||
AC_DEFINE(HAVE_STRUCT_SOCKADDR_IN6)
|
||||
AC_MSG_RESULT(yes)
|
||||
],
|
||||
[AC_MSG_RESULT(no)]
|
||||
)
|
||||
|
||||
AC_MSG_CHECKING([for struct in6_addr])
|
||||
AC_TRY_COMPILE(
|
||||
[#include <netinet/in.h>],
|
||||
[struct in6_addr s; s.s6_addr[0] = 0;],
|
||||
[
|
||||
AC_DEFINE(HAVE_STRUCT_IN6_ADDR)
|
||||
AC_MSG_RESULT(yes)
|
||||
],
|
||||
[AC_MSG_RESULT(no)]
|
||||
)
|
||||
|
||||
AC_MSG_CHECKING([for struct addrinfo])
|
||||
AC_TRY_COMPILE(
|
||||
[
|
||||
#include <sys/socket.h>
|
||||
#include <netdb.h>
|
||||
],
|
||||
[struct addrinfo s; s.ai_flags = AI_PASSIVE;],
|
||||
[
|
||||
AC_DEFINE(HAVE_STRUCT_ADDRINFO)
|
||||
AC_MSG_RESULT(yes)
|
||||
],
|
||||
[AC_MSG_RESULT(no)]
|
||||
)
|
||||
|
||||
AC_ARG_WITH(pam,
|
||||
[ --without-pam Disable PAM support ],
|
||||
[
|
||||
@ -330,7 +377,38 @@ AC_EGREP_HEADER(ut_addr, utmp.h,
|
||||
)
|
||||
AC_MSG_CHECKING([whether utmpx.h has ut_addr field])
|
||||
AC_EGREP_HEADER(ut_addr, utmpx.h,
|
||||
[AC_DEFINE(HAVE_ADDR_IN_UTMP) AC_MSG_RESULT(yes); ],
|
||||
[AC_DEFINE(HAVE_ADDR_IN_UTMPX) AC_MSG_RESULT(yes); ],
|
||||
[AC_MSG_RESULT(no)]
|
||||
)
|
||||
AC_MSG_CHECKING([whether utmp.h has ut_addr_v6 field])
|
||||
AC_EGREP_HEADER(ut_addr_v6, utmp.h,
|
||||
[AC_DEFINE(HAVE_ADDR_V6_IN_UTMP) AC_MSG_RESULT(yes); ],
|
||||
[AC_MSG_RESULT(no)]
|
||||
)
|
||||
AC_MSG_CHECKING([whether utmpx.h has ut_addr_v6 field])
|
||||
AC_EGREP_HEADER(ut_addr_v6, utmpx.h,
|
||||
[AC_DEFINE(HAVE_ADDR_V6_IN_UTMPX) AC_MSG_RESULT(yes); ],
|
||||
[AC_MSG_RESULT(no)]
|
||||
)
|
||||
|
||||
AC_MSG_CHECKING([whether struct sockaddr_storage has ss_family field])
|
||||
AC_TRY_COMPILE(
|
||||
[#include <sys/socket.h>],
|
||||
[struct sockaddr_storage s; s.ss_family = 1;],
|
||||
[
|
||||
AC_DEFINE(HAVE_SS_FAMILY_IN_SS)
|
||||
AC_MSG_RESULT(yes)
|
||||
],
|
||||
[AC_MSG_RESULT(no)]
|
||||
)
|
||||
AC_MSG_CHECKING([whether struct sockaddr_storage has __ss_family field])
|
||||
AC_TRY_COMPILE(
|
||||
[#include <sys/socket.h>],
|
||||
[struct sockaddr_storage s; s.__ss_family = 1;],
|
||||
[
|
||||
AC_DEFINE(HAVE___SS_FAMILY_IN_SS)
|
||||
AC_MSG_RESULT(yes)
|
||||
],
|
||||
[AC_MSG_RESULT(no)]
|
||||
)
|
||||
|
||||
|
@ -112,6 +112,10 @@ typedef unsigned int size_t;
|
||||
# define HAVE_SIZE_T
|
||||
#endif /* HAVE_SIZE_T */
|
||||
|
||||
#if !defined(HAVE_SS_FAMILY_IN_SS) && defined(HAVE___SS_FAMILY_IN_SS)
|
||||
# define ss_family __ss_family
|
||||
#endif /* !defined(HAVE_SS_FAMILY_IN_SS) && defined(HAVE_SA_FAMILY_IN_SS) */
|
||||
|
||||
/* Paths */
|
||||
|
||||
/* If _PATH_LASTLOG is not defined by system headers, set it to the */
|
||||
|
12
fake-gai-errnos.h
Normal file
12
fake-gai-errnos.h
Normal file
@ -0,0 +1,12 @@
|
||||
/*
|
||||
* fake library for ssh
|
||||
*
|
||||
* This file is included in getaddrinfo.c and getnameinfo.c.
|
||||
* See getaddrinfo.c and getnameinfo.c.
|
||||
*/
|
||||
|
||||
/* for old netdb.h */
|
||||
#ifndef EAI_NODATA
|
||||
#define EAI_NODATA 1
|
||||
#define EAI_MEMORY 2
|
||||
#endif
|
119
fake-getaddrinfo.c
Normal file
119
fake-getaddrinfo.c
Normal file
@ -0,0 +1,119 @@
|
||||
/*
|
||||
* fake library for ssh
|
||||
*
|
||||
* This file includes getaddrinfo(), freeaddrinfo() and gai_strerror().
|
||||
* These funtions are defined in rfc2133.
|
||||
*
|
||||
* But these functions are not implemented correctly. The minimum subset
|
||||
* is implemented for ssh use only. For exapmle, this routine assumes
|
||||
* that ai_family is AF_INET. Don't use it for another purpose.
|
||||
*
|
||||
* In the case not using 'configure --enable-ipv6', this getaddrinfo.c
|
||||
* will be used if you have broken getaddrinfo or no getaddrinfo.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
#include "ssh.h"
|
||||
|
||||
#ifndef HAVE_GAI_STRERROR
|
||||
char *
|
||||
gai_strerror(ecode)
|
||||
int ecode;
|
||||
{
|
||||
switch (ecode) {
|
||||
case EAI_NODATA:
|
||||
return "no address associated with hostname.";
|
||||
case EAI_MEMORY:
|
||||
return "memory allocation failure.";
|
||||
default:
|
||||
return "unknown error.";
|
||||
}
|
||||
}
|
||||
#endif /* !HAVE_GAI_STRERROR */
|
||||
|
||||
#ifndef HAVE_FREEADDRINFO
|
||||
void
|
||||
freeaddrinfo(ai)
|
||||
struct addrinfo *ai;
|
||||
{
|
||||
struct addrinfo *next;
|
||||
|
||||
do {
|
||||
next = ai->ai_next;
|
||||
free(ai);
|
||||
} while (ai = next);
|
||||
}
|
||||
#endif /* !HAVE_FREEADDRINFO */
|
||||
|
||||
#ifndef HAVE_GETADDRINFO
|
||||
static struct addrinfo *
|
||||
malloc_ai(port, addr)
|
||||
int port;
|
||||
u_long addr;
|
||||
{
|
||||
struct addrinfo *ai;
|
||||
|
||||
if (ai = (struct addrinfo *)malloc(sizeof(struct addrinfo) +
|
||||
sizeof(struct sockaddr_in))) {
|
||||
memset(ai, 0, sizeof(struct addrinfo) + sizeof(struct sockaddr_in));
|
||||
ai->ai_addr = (struct sockaddr *)(ai + 1);
|
||||
/* XXX -- ssh doesn't use sa_len */
|
||||
ai->ai_addrlen = sizeof(struct sockaddr_in);
|
||||
ai->ai_addr->sa_family = ai->ai_family = AF_INET;
|
||||
((struct sockaddr_in *)(ai)->ai_addr)->sin_port = port;
|
||||
((struct sockaddr_in *)(ai)->ai_addr)->sin_addr.s_addr = addr;
|
||||
return ai;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
getaddrinfo(hostname, servname, hints, res)
|
||||
const char *hostname, *servname;
|
||||
const struct addrinfo *hints;
|
||||
struct addrinfo **res;
|
||||
{
|
||||
struct addrinfo *cur, *prev = NULL;
|
||||
struct hostent *hp;
|
||||
int i, port;
|
||||
|
||||
if (servname)
|
||||
port = htons(atoi(servname));
|
||||
else
|
||||
port = 0;
|
||||
if (hints && hints->ai_flags & AI_PASSIVE)
|
||||
if (*res = malloc_ai(port, htonl(0x00000000)))
|
||||
return 0;
|
||||
else
|
||||
return EAI_MEMORY;
|
||||
if (!hostname)
|
||||
if (*res = malloc_ai(port, htonl(0x7f000001)))
|
||||
return 0;
|
||||
else
|
||||
return EAI_MEMORY;
|
||||
if (inet_addr(hostname) != -1)
|
||||
if (*res = malloc_ai(port, inet_addr(hostname)))
|
||||
return 0;
|
||||
else
|
||||
return EAI_MEMORY;
|
||||
if ((hp = gethostbyname(hostname)) &&
|
||||
hp->h_name && hp->h_name[0] && hp->h_addr_list[0]) {
|
||||
for (i = 0; hp->h_addr_list[i]; i++)
|
||||
if (cur = malloc_ai(port,
|
||||
((struct in_addr *)hp->h_addr_list[i])->s_addr)) {
|
||||
if (prev)
|
||||
prev->ai_next = cur;
|
||||
else
|
||||
*res = cur;
|
||||
prev = cur;
|
||||
} else {
|
||||
if (*res)
|
||||
freeaddrinfo(*res);
|
||||
return EAI_MEMORY;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
return EAI_NODATA;
|
||||
}
|
||||
#endif /* !HAVE_GETADDRINFO */
|
44
fake-getaddrinfo.h
Normal file
44
fake-getaddrinfo.h
Normal file
@ -0,0 +1,44 @@
|
||||
#ifndef _FAKE_GETADDRINFO_H
|
||||
#define _FAKE_GETADDRINFO_H
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "fake-gai-errnos.h"
|
||||
|
||||
#ifndef AI_PASSIVE
|
||||
# define AI_PASSIVE 1
|
||||
#endif
|
||||
|
||||
#ifndef NI_NUMERICHOST
|
||||
# define NI_NUMERICHOST 2
|
||||
# define NI_NAMEREQD 4
|
||||
# define NI_NUMERICSERV 8
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_STRUCT_ADDRINFO
|
||||
struct addrinfo {
|
||||
int ai_flags; /* AI_PASSIVE, AI_CANONNAME */
|
||||
int ai_family; /* PF_xxx */
|
||||
int ai_socktype; /* SOCK_xxx */
|
||||
int ai_protocol; /* 0 or IPPROTO_xxx for IPv4 and IPv6 */
|
||||
size_t ai_addrlen; /* length of ai_addr */
|
||||
char *ai_canonname; /* canonical name for hostname */
|
||||
struct sockaddr *ai_addr; /* binary address */
|
||||
struct addrinfo *ai_next; /* next structure in linked list */
|
||||
}
|
||||
#endif /* !HAVE_STRUCT_ADDRINFO */
|
||||
|
||||
#ifndef HAVE_GETADDRINFO
|
||||
int getaddrinfo(const char *hostname, const char *servname,
|
||||
const struct addrinfo *hints, struct addrinfo **res);
|
||||
#endif /* !HAVE_GETADDRINFO */
|
||||
|
||||
#ifndef HAVE_GAI_STRERROR
|
||||
char *gai_strerror(int ecode);
|
||||
#endif /* !HAVE_GAI_STRERROR */
|
||||
|
||||
#ifndef HAVE_FREEADDRINFO
|
||||
void freeaddrinfo(struct addrinfo *ai);
|
||||
#endif /* !HAVE_FREEADDRINFO */
|
||||
|
||||
#endif /* _FAKE_GETADDRINFO_H */
|
61
fake-getnameinfo.c
Normal file
61
fake-getnameinfo.c
Normal file
@ -0,0 +1,61 @@
|
||||
/*
|
||||
* fake library for ssh
|
||||
*
|
||||
* This file includes getnameinfo().
|
||||
* These funtions are defined in rfc2133.
|
||||
*
|
||||
* But these functions are not implemented correctly. The minimum subset
|
||||
* is implemented for ssh use only. For exapmle, this routine assumes
|
||||
* that ai_family is AF_INET. Don't use it for another purpose.
|
||||
*
|
||||
* In the case not using 'configure --enable-ipv6', this getnameinfo.c
|
||||
* will be used if you have broken getnameinfo or no getnameinfo.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
#include "ssh.h"
|
||||
|
||||
#ifndef HAVE_GETNAMEINFO
|
||||
int
|
||||
getnameinfo(sa, salen, host, hostlen, serv, servlen, flags)
|
||||
const struct sockaddr *sa;
|
||||
size_t salen;
|
||||
char *host;
|
||||
size_t hostlen;
|
||||
char *serv;
|
||||
size_t servlen;
|
||||
int flags;
|
||||
{
|
||||
struct sockaddr_in *sin = (struct sockaddr_in *)sa;
|
||||
struct hostent *hp;
|
||||
char tmpserv[16];
|
||||
|
||||
if (serv) {
|
||||
sprintf(tmpserv, "%d", ntohs(sin->sin_port));
|
||||
if (strlen(tmpserv) > servlen)
|
||||
return EAI_MEMORY;
|
||||
else
|
||||
strcpy(serv, tmpserv);
|
||||
}
|
||||
if (host)
|
||||
if (flags & NI_NUMERICHOST)
|
||||
if (strlen(inet_ntoa(sin->sin_addr)) > hostlen)
|
||||
return EAI_MEMORY;
|
||||
else {
|
||||
strcpy(host, inet_ntoa(sin->sin_addr));
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
if (hp = gethostbyaddr((char *)&sin->sin_addr, sizeof(struct in_addr),
|
||||
AF_INET))
|
||||
if (strlen(hp->h_name) > hostlen)
|
||||
return EAI_MEMORY;
|
||||
else {
|
||||
strcpy(host, hp->h_name);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
return EAI_NODATA;
|
||||
return 0;
|
||||
}
|
||||
#endif /* !HAVE_GETNAMEINFO */
|
17
fake-getnameinfo.h
Normal file
17
fake-getnameinfo.h
Normal file
@ -0,0 +1,17 @@
|
||||
#ifndef _FAKE_GETNAMEINFO_H
|
||||
#define _FAKE_GETNAMEINFO_H
|
||||
|
||||
#include "config.h"
|
||||
#ifndef HAVE_GETNAMEINFO
|
||||
int getnameinfo(const struct sockaddr *sa, size_t salen, char *host,
|
||||
size_t hostlen, char *serv, size_t servlen, int flags);
|
||||
#endif /* !HAVE_GETNAMEINFO */
|
||||
|
||||
#ifndef NI_MAXSERV
|
||||
# define NI_MAXSERV 32
|
||||
#endif /* !NI_MAXSERV */
|
||||
#ifndef NI_MAXHOST
|
||||
# define NI_MAXHOST 1025
|
||||
#endif /* !NI_MAXHOST */
|
||||
|
||||
#endif /* _FAKE_GETNAMEINFO_H */
|
49
fake-socket.h
Normal file
49
fake-socket.h
Normal file
@ -0,0 +1,49 @@
|
||||
#ifndef _FAKE_SOCKET_H
|
||||
#define _FAKE_SOCKET_H
|
||||
|
||||
#include "config.h"
|
||||
#include "sys/types.h"
|
||||
|
||||
#ifndef HAVE_STRUCT_SOCKADDR_STORAGE
|
||||
#define _SS_MAXSIZE 128 /* Implementation specific max size */
|
||||
#define _SS_ALIGNSIZE (sizeof(int))
|
||||
#define _SS_PAD1SIZE (_SS_ALIGNSIZE - sizeof(u_short))
|
||||
#define _SS_PAD2SIZE (_SS_MAXSIZE - (sizeof(u_short) + \
|
||||
_SS_PAD1SIZE + _SS_ALIGNSIZE))
|
||||
|
||||
struct sockaddr_storage {
|
||||
u_short ss_family;
|
||||
char __ss_pad1[_SS_PAD1SIZE];
|
||||
int __ss_align;
|
||||
char __ss_pad2[_SS_PAD2SIZE];
|
||||
};
|
||||
#endif /* !HAVE_STRUCT_SOCKADDR_STORAGE */
|
||||
|
||||
#ifndef IN6_IS_ADDR_LOOPBACK
|
||||
#define IN6_IS_ADDR_LOOPBACK(a) \
|
||||
(((u_int32_t *) (a))[0] == 0 && ((u_int32_t *) (a))[1] == 0 && \
|
||||
((u_int32_t *) (a))[2] == 0 && ((u_int32_t *) (a))[3] == htonl (1))
|
||||
#endif /* !IN6_IS_ADDR_LOOPBACK */
|
||||
|
||||
#ifndef HAVE_STRUCT_IN6_ADDR
|
||||
struct in6_addr {
|
||||
u_int8_t s6_addr[16];
|
||||
};
|
||||
#endif /* !HAVE_STRUCT_IN6_ADDR */
|
||||
|
||||
#ifndef HAVE_STRUCT_SOCKADDR_IN6
|
||||
struct sockaddr_in6 {
|
||||
unsigned short sin6_family;
|
||||
u_int16_t sin6_port;
|
||||
u_int32_t sin6_flowinfo;
|
||||
struct in6_addr sin6_addr;
|
||||
};
|
||||
#endif /* !HAVE_STRUCT_SOCKADDR_IN6 */
|
||||
|
||||
#ifndef AF_INET6
|
||||
/* Define it to something that should never appear */
|
||||
#define AF_INET6 AF_MAX
|
||||
#endif
|
||||
|
||||
#endif /* !_FAKE_SOCKET_H */
|
||||
|
2
fixpaths
2
fixpaths
@ -31,8 +31,6 @@ for $f (@ARGV) {
|
||||
$f =~ /(.*\/)*(.*)$/;
|
||||
$of = $2; $of =~ s/.in$//;
|
||||
|
||||
print("Making substitutions for $of\n");
|
||||
|
||||
open(IN, "<$f") || die ("$0: input file $f missing!\n");
|
||||
if (open(OUT, ">$of")) {
|
||||
while (<IN>) {
|
||||
|
@ -14,7 +14,7 @@
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
RCSID("$OpenBSD: hostfile.c,v 1.10 1999/12/02 20:18:59 markus Exp $");
|
||||
RCSID("$OpenBSD: hostfile.c,v 1.11 2000/01/04 00:07:59 markus Exp $");
|
||||
|
||||
#include "packet.h"
|
||||
#include "ssh.h"
|
||||
|
@ -88,6 +88,10 @@ static /**/const char *const rcsid[] = { (char *)rcsid, "\100(#)" msg }
|
||||
#endif
|
||||
|
||||
#include "version.h"
|
||||
|
||||
/* BSD function replacements */
|
||||
#include "bsd-bindresvport.h"
|
||||
#include "bsd-rresvport.h"
|
||||
#include "bsd-misc.h"
|
||||
#include "bsd-strlcpy.h"
|
||||
#include "bsd-strlcat.h"
|
||||
@ -96,6 +100,11 @@ static /**/const char *const rcsid[] = { (char *)rcsid, "\100(#)" msg }
|
||||
#include "bsd-daemon.h"
|
||||
#include "bsd-login.h"
|
||||
|
||||
/* rfc2553 socket API replacements */
|
||||
#include "fake-getaddrinfo.h"
|
||||
#include "fake-getnameinfo.h"
|
||||
#include "fake-socket.h"
|
||||
|
||||
/* Define this to be the path of the xauth program. */
|
||||
#ifndef XAUTH_PATH
|
||||
#define XAUTH_PATH "/usr/X11R6/bin/xauth"
|
||||
|
2
log.c
2
log.c
@ -3,7 +3,7 @@
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
RCSID("$OpenBSD: log.c,v 1.6 1999/11/24 19:53:47 markus Exp $");
|
||||
RCSID("$OpenBSD: log.c,v 1.7 2000/01/04 00:07:59 markus Exp $");
|
||||
|
||||
#include "ssh.h"
|
||||
#include "xmalloc.h"
|
||||
|
42
login.c
42
login.c
@ -18,7 +18,7 @@
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
RCSID("$Id: login.c,v 1.17 2000/01/02 00:45:33 damien Exp $");
|
||||
RCSID("$Id: login.c,v 1.18 2000/01/14 04:45:50 damien Exp $");
|
||||
|
||||
#if defined(HAVE_UTMPX_H) && defined(USE_UTMPX)
|
||||
# include <utmpx.h>
|
||||
@ -137,7 +137,7 @@ get_last_login_time(uid_t uid, const char *logname,
|
||||
|
||||
void
|
||||
record_login(int pid, const char *ttyname, const char *user, uid_t uid,
|
||||
const char *host, struct sockaddr_in * addr)
|
||||
const char *host, struct sockaddr * addr)
|
||||
{
|
||||
#if defined(_PATH_LASTLOG) && !defined(DISABLE_LASTLOG)
|
||||
struct lastlog ll;
|
||||
@ -173,7 +173,22 @@ record_login(int pid, const char *ttyname, const char *user, uid_t uid,
|
||||
strncpy(u.ut_host, host, sizeof(u.ut_host));
|
||||
#endif
|
||||
#if defined(HAVE_ADDR_IN_UTMP)
|
||||
u.ut_addr = addr->sin_addr.s_addr;
|
||||
switch (addr->sa_family) {
|
||||
case AF_INET: {
|
||||
struct sockaddr_in *in = (struct sockaddr_in*)addr;
|
||||
memcpy(&(u.ut_addr), &(in->sin_addr), sizeof(&(in->sin_addr)));
|
||||
break;
|
||||
}
|
||||
#if defined(HAVE_ADDR_V6_IN_UTMP)
|
||||
case AF_INET6: {
|
||||
struct sockaddr_in6 *in6 = (struct sockaddr_in6*)addr;
|
||||
memcpy(u.ut_addr_v6, &(in6->sin6_addr), sizeof(&(in6->sin6_addr)));
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_UTMPX_H) && defined(USE_UTMPX)
|
||||
@ -192,9 +207,24 @@ record_login(int pid, const char *ttyname, const char *user, uid_t uid,
|
||||
strncpy(utx.ut_host, host, sizeof(utx.ut_host));
|
||||
# endif /* HAVE_SYSLEN_IN_UTMPX */
|
||||
# endif
|
||||
# if defined(HAVE_ADDR_IN_UTMPX)
|
||||
utx.ut_addr = addr->sin_addr.s_addr;
|
||||
# endif
|
||||
#if defined(HAVE_ADDR_IN_UTMPX)
|
||||
switch (addr->sa_family) {
|
||||
case AF_INET: {
|
||||
struct sockaddr_in *in = (struct sockaddr_in*)addr;
|
||||
memcpy(&(utx.ut_addr), &(in->sin_addr), sizeof(&(in->sin_addr)));
|
||||
break;
|
||||
}
|
||||
#if defined(HAVE_ADDR_V6_IN_UTMPX)
|
||||
case AF_INET6: {
|
||||
struct sockaddr_in6 *in6 = (struct sockaddr_in6*)addr;
|
||||
memcpy(utx.ut_addr_v6, &(in6->sin6_addr), sizeof(&(in6->sin6_addr)));
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#endif /* defined(HAVE_UTMPX_H) && defined(USE_UTMPX) */
|
||||
|
||||
/*#if defined(HAVE_UTMPX_H) && defined(USE_UTMPX) && !defined(HAVE_LOGIN)*/
|
||||
|
30
nchan.c
30
nchan.c
@ -28,7 +28,7 @@
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
RCSID("$Id: nchan.c,v 1.4 1999/12/06 00:47:29 damien Exp $");
|
||||
RCSID("$Id: nchan.c,v 1.5 2000/01/14 04:45:50 damien Exp $");
|
||||
|
||||
#include "ssh.h"
|
||||
|
||||
@ -41,7 +41,7 @@ static void chan_send_ieof(Channel *c);
|
||||
static void chan_send_oclose(Channel *c);
|
||||
static void chan_shutdown_write(Channel *c);
|
||||
static void chan_shutdown_read(Channel *c);
|
||||
static void chan_delele_if_full_closed(Channel *c);
|
||||
static void chan_delete_if_full_closed(Channel *c);
|
||||
|
||||
/*
|
||||
* EVENTS update channel input/output states execute ACTIONS
|
||||
@ -55,19 +55,25 @@ chan_rcvd_oclose(Channel *c)
|
||||
case CHAN_INPUT_WAIT_OCLOSE:
|
||||
debug("channel %d: INPUT_WAIT_OCLOSE -> INPUT_CLOSED [rcvd OCLOSE]", c->self);
|
||||
c->istate = CHAN_INPUT_CLOSED;
|
||||
chan_delele_if_full_closed(c);
|
||||
break;
|
||||
case CHAN_INPUT_OPEN:
|
||||
debug("channel %d: INPUT_OPEN -> INPUT_CLOSED [rvcd OCLOSE, send IEOF]", c->self);
|
||||
chan_shutdown_read(c);
|
||||
chan_send_ieof(c);
|
||||
c->istate = CHAN_INPUT_CLOSED;
|
||||
chan_delele_if_full_closed(c);
|
||||
break;
|
||||
case CHAN_INPUT_WAIT_DRAIN:
|
||||
/* both local read_failed and remote write_failed */
|
||||
log("channel %d: INPUT_WAIT_DRAIN -> INPUT_CLOSED [rvcd OCLOSE, send IEOF]", c->self);
|
||||
debug("channel %d: INPUT_WAIT_DRAIN -> INPUT_CLOSED [rvcd OCLOSE, send IEOF]", c->self);
|
||||
chan_send_ieof(c);
|
||||
c->istate = CHAN_INPUT_CLOSED;
|
||||
break;
|
||||
default:
|
||||
error("protocol error: chan_rcvd_oclose %d for istate %d", c->self, c->istate);
|
||||
break;
|
||||
return;
|
||||
}
|
||||
chan_delete_if_full_closed(c);
|
||||
}
|
||||
void
|
||||
chan_read_failed(Channel *c)
|
||||
@ -115,7 +121,7 @@ chan_rcvd_ieof(Channel *c)
|
||||
case CHAN_OUTPUT_WAIT_IEOF:
|
||||
debug("channel %d: OUTPUT_WAIT_IEOF -> OUTPUT_CLOSED [rvcd IEOF]", c->self);
|
||||
c->ostate = CHAN_OUTPUT_CLOSED;
|
||||
chan_delele_if_full_closed(c);
|
||||
chan_delete_if_full_closed(c);
|
||||
break;
|
||||
default:
|
||||
error("protocol error: chan_rcvd_ieof %d for ostate %d", c->self, c->ostate);
|
||||
@ -135,7 +141,7 @@ chan_write_failed(Channel *c)
|
||||
debug("channel %d: OUTPUT_WAIT_DRAIN -> OUTPUT_CLOSED [write failed]", c->self);
|
||||
chan_send_oclose(c);
|
||||
c->ostate = CHAN_OUTPUT_CLOSED;
|
||||
chan_delele_if_full_closed(c);
|
||||
chan_delete_if_full_closed(c);
|
||||
break;
|
||||
default:
|
||||
error("internal error: chan_write_failed %d for ostate %d", c->self, c->ostate);
|
||||
@ -154,7 +160,7 @@ chan_obuf_empty(Channel *c)
|
||||
debug("channel %d: OUTPUT_WAIT_DRAIN -> OUTPUT_CLOSED [obuf empty, send OCLOSE]", c->self);
|
||||
chan_send_oclose(c);
|
||||
c->ostate = CHAN_OUTPUT_CLOSED;
|
||||
chan_delele_if_full_closed(c);
|
||||
chan_delete_if_full_closed(c);
|
||||
break;
|
||||
default:
|
||||
error("internal error: chan_obuf_empty %d for ostate %d", c->self, c->ostate);
|
||||
@ -213,14 +219,14 @@ chan_shutdown_read(Channel *c)
|
||||
{
|
||||
debug("channel %d: shutdown_read", c->self);
|
||||
if (shutdown(c->sock, SHUT_RD) < 0)
|
||||
error("chan_shutdown_read failed for #%d/fd%d: %.100s",
|
||||
c->self, c->sock, strerror(errno));
|
||||
error("chan_shutdown_read failed for #%d/fd%d [i%d o%d]: %.100s",
|
||||
c->self, c->sock, c->istate, c->ostate, strerror(errno));
|
||||
}
|
||||
static void
|
||||
chan_delele_if_full_closed(Channel *c)
|
||||
chan_delete_if_full_closed(Channel *c)
|
||||
{
|
||||
if (c->istate == CHAN_INPUT_CLOSED && c->ostate == CHAN_OUTPUT_CLOSED) {
|
||||
debug("channel %d: closing", c->self);
|
||||
debug("channel %d: full closed", c->self);
|
||||
channel_free(c->self);
|
||||
}
|
||||
}
|
||||
|
9
nchan.ms
9
nchan.ms
@ -52,6 +52,9 @@ arrow from S3.n to S4.s
|
||||
box invis "rcvd OCLOSE/" "-" with .w at last arrow.c
|
||||
ellipse wid .9*ellipsewid ht .9*ellipseht at S4
|
||||
arrow "start" "" from S1.w+(-0.5,0) to S1.w
|
||||
arrow from S2.ne to S4.sw
|
||||
box invis "rcvd OCLOSE/ " with .e at last arrow.c
|
||||
box invis " send IEOF" with .w at last arrow.c
|
||||
.PE
|
||||
.SH
|
||||
Channel Output State Diagram
|
||||
@ -76,7 +79,7 @@ arrow "start" "" from S1.w+(-0.5,0) to S1.w
|
||||
Notes
|
||||
.PP
|
||||
The input buffer is filled with data from the socket
|
||||
(the socket represents the local comsumer/producer of the
|
||||
(the socket represents the local consumer/producer of the
|
||||
forwarded channel).
|
||||
The data is then sent over the INPUT-end (transmit-end) of the channel to the
|
||||
remote peer.
|
||||
@ -85,7 +88,7 @@ saved in the output buffer and written to the socket.
|
||||
.PP
|
||||
If the local protocol instance has forwarded all data on the
|
||||
INPUT-end of the channel, it sends an IEOF message to the peer.
|
||||
If the peer receives the IEOF and has comsumed all
|
||||
If the peer receives the IEOF and has consumed all
|
||||
data he replies with an OCLOSE.
|
||||
When the local instance receives the OCLOSE
|
||||
he considers the INPUT-half of the channel closed.
|
||||
@ -94,6 +97,6 @@ The peer has his OUTOUT-half closed.
|
||||
A channel can be deallocated by a protocol instance
|
||||
if both the INPUT- and the OUTOUT-half on his
|
||||
side of the channel are closed.
|
||||
Note that when an instance is unable to comsume the
|
||||
Note that when an instance is unable to consume the
|
||||
received data, he is permitted to send an OCLOSE
|
||||
before the matching IEOF is received.
|
||||
|
65
packet.c
65
packet.c
@ -15,7 +15,7 @@
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
RCSID("$Id: packet.c,v 1.8 1999/12/16 02:18:04 damien Exp $");
|
||||
RCSID("$Id: packet.c,v 1.9 2000/01/14 04:45:50 damien Exp $");
|
||||
|
||||
#include "xmalloc.h"
|
||||
#include "buffer.h"
|
||||
@ -104,6 +104,48 @@ packet_set_connection(int fd_in, int fd_out)
|
||||
fatal_add_cleanup((void (*) (void *)) packet_close, NULL);
|
||||
}
|
||||
|
||||
/* Returns 1 if remote host is connected via socket, 0 if not. */
|
||||
|
||||
int
|
||||
packet_connection_is_on_socket()
|
||||
{
|
||||
struct sockaddr_storage from, to;
|
||||
socklen_t fromlen, tolen;
|
||||
|
||||
/* filedescriptors in and out are the same, so it's a socket */
|
||||
if (connection_in == connection_out)
|
||||
return 1;
|
||||
fromlen = sizeof(from);
|
||||
memset(&from, 0, sizeof(from));
|
||||
if (getpeername(connection_in, (struct sockaddr *) & from, &fromlen) < 0)
|
||||
return 0;
|
||||
tolen = sizeof(to);
|
||||
memset(&to, 0, sizeof(to));
|
||||
if (getsockname(connection_out, (struct sockaddr *)&to, &tolen) < 0)
|
||||
return 0;
|
||||
if (fromlen != tolen || memcmp(&from, &to, fromlen) != 0)
|
||||
return 0;
|
||||
if (from.ss_family != AF_INET && from.ss_family != AF_INET6)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* returns 1 if connection is via ipv4 */
|
||||
|
||||
int
|
||||
packet_connection_is_ipv4()
|
||||
{
|
||||
struct sockaddr_storage to;
|
||||
socklen_t tolen;
|
||||
|
||||
memset(&to, 0, sizeof(to));
|
||||
if (getsockname(connection_out, (struct sockaddr *)&to, &tolen) < 0)
|
||||
return 0;
|
||||
if (to.ss_family != AF_INET)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Sets the connection into non-blocking mode. */
|
||||
|
||||
void
|
||||
@ -735,19 +777,20 @@ packet_set_interactive(int interactive, int keepalives)
|
||||
/* Record that we are in interactive mode. */
|
||||
interactive_mode = interactive;
|
||||
|
||||
/*
|
||||
* Only set socket options if using a socket (as indicated by the
|
||||
* descriptors being the same).
|
||||
*/
|
||||
if (connection_in != connection_out)
|
||||
/* Only set socket options if using a socket. */
|
||||
if (!packet_connection_is_on_socket())
|
||||
return;
|
||||
|
||||
if (keepalives) {
|
||||
/* Set keepalives if requested. */
|
||||
if (setsockopt(connection_in, SOL_SOCKET, SO_KEEPALIVE, (void *) &on,
|
||||
sizeof(on)) < 0)
|
||||
sizeof(on)) < 0)
|
||||
error("setsockopt SO_KEEPALIVE: %.100s", strerror(errno));
|
||||
}
|
||||
/*
|
||||
* IPTOS_LOWDELAY, TCP_NODELAY and IPTOS_THROUGHPUT are IPv4 only
|
||||
*/
|
||||
if (!packet_connection_is_ipv4())
|
||||
return;
|
||||
if (interactive) {
|
||||
/*
|
||||
* Set IP options for an interactive connection. Use
|
||||
@ -755,10 +798,10 @@ packet_set_interactive(int interactive, int keepalives)
|
||||
*/
|
||||
int lowdelay = IPTOS_LOWDELAY;
|
||||
if (setsockopt(connection_in, IPPROTO_IP, IP_TOS, (void *) &lowdelay,
|
||||
sizeof(lowdelay)) < 0)
|
||||
sizeof(lowdelay)) < 0)
|
||||
error("setsockopt IPTOS_LOWDELAY: %.100s", strerror(errno));
|
||||
if (setsockopt(connection_in, IPPROTO_TCP, TCP_NODELAY, (void *) &on,
|
||||
sizeof(on)) < 0)
|
||||
sizeof(on)) < 0)
|
||||
error("setsockopt TCP_NODELAY: %.100s", strerror(errno));
|
||||
} else {
|
||||
/*
|
||||
@ -767,7 +810,7 @@ packet_set_interactive(int interactive, int keepalives)
|
||||
*/
|
||||
int throughput = IPTOS_THROUGHPUT;
|
||||
if (setsockopt(connection_in, IPPROTO_IP, IP_TOS, (void *) &throughput,
|
||||
sizeof(throughput)) < 0)
|
||||
sizeof(throughput)) < 0)
|
||||
error("setsockopt IPTOS_THROUGHPUT: %.100s", strerror(errno));
|
||||
}
|
||||
}
|
||||
|
6
packet.h
6
packet.h
@ -13,7 +13,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
/* RCSID("$Id: packet.h,v 1.8 1999/12/27 12:54:55 damien Exp $"); */
|
||||
/* RCSID("$Id: packet.h,v 1.9 2000/01/14 04:45:51 damien Exp $"); */
|
||||
|
||||
#ifndef PACKET_H
|
||||
#define PACKET_H
|
||||
@ -198,4 +198,8 @@ do { \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/* remote host is connected via a socket/ipv4 */
|
||||
int packet_connection_is_on_socket(void);
|
||||
int packet_connection_is_ipv4(void);
|
||||
|
||||
#endif /* PACKET_H */
|
||||
|
12
scp.1.in
12
scp.1.in
@ -9,7 +9,7 @@
|
||||
.\"
|
||||
.\" Created: Sun May 7 00:14:37 1995 ylo
|
||||
.\"
|
||||
.\" $Id: scp.1.in,v 1.1 1999/12/26 22:23:58 damien Exp $
|
||||
.\" $Id: scp.1.in,v 1.2 2000/01/14 04:45:51 damien Exp $
|
||||
.\"
|
||||
.Dd September 25, 1999
|
||||
.Dt SCP 1
|
||||
@ -19,7 +19,7 @@
|
||||
.Nd secure copy (remote file copy program)
|
||||
.Sh SYNOPSIS
|
||||
.Nm scp
|
||||
.Op Fl pqrvC
|
||||
.Op Fl pqrvC46
|
||||
.Op Fl P Ar port
|
||||
.Op Fl c Ar cipher
|
||||
.Op Fl i Ar identity_file
|
||||
@ -93,6 +93,14 @@ because
|
||||
.Fl p
|
||||
is already reserved for preserving the times and modes of the file in
|
||||
.Xr rcp 1 .
|
||||
.It Fl 4
|
||||
Forces
|
||||
.Nm
|
||||
to use IPv4 addresses only.
|
||||
.It Fl 6
|
||||
Forces
|
||||
.Nm
|
||||
to use IPv6 addresses only.
|
||||
.Sh AUTHORS
|
||||
Timo Rinne <tri@iki.fi> and Tatu Ylonen <ylo@cs.hut.fi>
|
||||
.Sh HISTORY
|
||||
|
56
scp.c
56
scp.c
@ -45,7 +45,7 @@
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
RCSID("$Id: scp.c,v 1.15 1999/12/30 22:16:40 damien Exp $");
|
||||
RCSID("$Id: scp.c,v 1.16 2000/01/14 04:45:51 damien Exp $");
|
||||
|
||||
#include "ssh.h"
|
||||
#include "xmalloc.h"
|
||||
@ -74,6 +74,12 @@ off_t totalbytes = 0;
|
||||
/* Name of current file being transferred. */
|
||||
char *curfile;
|
||||
|
||||
/* This is set to non-zero if IPv4 is desired. */
|
||||
int IPv4 = 0;
|
||||
|
||||
/* This is set to non-zero if IPv6 is desired. */
|
||||
int IPv6 = 0;
|
||||
|
||||
/* This is set to non-zero to enable verbose mode. */
|
||||
int verbose_mode = 0;
|
||||
|
||||
@ -145,6 +151,11 @@ do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout)
|
||||
args[i++] = SSH_PROGRAM;
|
||||
args[i++] = "-x";
|
||||
args[i++] = "-oFallBackToRsh no";
|
||||
if (IPv4)
|
||||
args[i++] = "-4";
|
||||
if (IPv6)
|
||||
args[i++] = "-6";
|
||||
args[i++] = "-oFallBackToRsh no";
|
||||
if (verbose_mode)
|
||||
args[i++] = "-v";
|
||||
if (compress_flag)
|
||||
@ -242,9 +253,15 @@ main(argc, argv)
|
||||
extern int optind;
|
||||
|
||||
fflag = tflag = 0;
|
||||
while ((ch = getopt(argc, argv, "dfprtvBCc:i:P:q")) != EOF)
|
||||
while ((ch = getopt(argc, argv, "dfprtvBCc:i:P:q46")) != EOF)
|
||||
switch (ch) {
|
||||
/* User-visible flags. */
|
||||
case '4':
|
||||
IPv4 = 1;
|
||||
break;
|
||||
case '6':
|
||||
IPv6 = 1;
|
||||
break;
|
||||
case 'p':
|
||||
pflag = 1;
|
||||
break;
|
||||
@ -334,6 +351,17 @@ main(argc, argv)
|
||||
exit(errs != 0);
|
||||
}
|
||||
|
||||
char *
|
||||
cleanhostname(host)
|
||||
char *host;
|
||||
{
|
||||
if (*host == '[' && host[strlen(host) - 1] == ']') {
|
||||
host[strlen(host) - 1] = '\0';
|
||||
return (host + 1);
|
||||
} else
|
||||
return host;
|
||||
}
|
||||
|
||||
void
|
||||
toremote(targ, argc, argv)
|
||||
char *targ, *argv[];
|
||||
@ -372,6 +400,7 @@ toremote(targ, argc, argv)
|
||||
bp = xmalloc(len);
|
||||
if (host) {
|
||||
*host++ = 0;
|
||||
host = cleanhostname(host);
|
||||
suser = argv[i];
|
||||
if (*suser == '\0')
|
||||
suser = pwd->pw_name;
|
||||
@ -383,13 +412,15 @@ toremote(targ, argc, argv)
|
||||
suser, host, cmd, src,
|
||||
tuser ? tuser : "", tuser ? "@" : "",
|
||||
thost, targ);
|
||||
} else
|
||||
} else {
|
||||
host = cleanhostname(argv[i]);
|
||||
(void) sprintf(bp,
|
||||
"exec %s%s -x -o'FallBackToRsh no' -n %s %s %s '%s%s%s:%s'",
|
||||
SSH_PROGRAM, verbose_mode ? " -v" : "",
|
||||
argv[i], cmd, src,
|
||||
host, cmd, src,
|
||||
tuser ? tuser : "", tuser ? "@" : "",
|
||||
thost, targ);
|
||||
}
|
||||
if (verbose_mode)
|
||||
fprintf(stderr, "Executing: %s\n", bp);
|
||||
(void) system(bp);
|
||||
@ -399,7 +430,7 @@ toremote(targ, argc, argv)
|
||||
len = strlen(targ) + CMDNEEDS + 20;
|
||||
bp = xmalloc(len);
|
||||
(void) sprintf(bp, "%s -t %s", cmd, targ);
|
||||
host = thost;
|
||||
host = cleanhostname(thost);
|
||||
if (do_cmd(host, tuser,
|
||||
bp, &remin, &remout) < 0)
|
||||
exit(1);
|
||||
@ -449,6 +480,7 @@ tolocal(argc, argv)
|
||||
else if (!okname(suser))
|
||||
continue;
|
||||
}
|
||||
host = cleanhostname(host);
|
||||
len = strlen(src) + CMDNEEDS + 20;
|
||||
bp = xmalloc(len);
|
||||
(void) sprintf(bp, "%s -f %s", cmd, src);
|
||||
@ -913,7 +945,7 @@ void
|
||||
usage()
|
||||
{
|
||||
(void) fprintf(stderr,
|
||||
"usage: scp [-pqrvC] [-P port] [-c cipher] [-i identity] f1 f2; or:\n scp [options] f1 ... fn directory\n");
|
||||
"usage: scp [-pqrvC46] [-P port] [-c cipher] [-i identity] f1 f2; or:\n scp [options] f1 ... fn directory\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@ -976,18 +1008,26 @@ run_err(const char *fmt,...)
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: scp.c,v 1.15 1999/12/30 22:16:40 damien Exp $
|
||||
* $Id: scp.c,v 1.16 2000/01/14 04:45:51 damien Exp $
|
||||
*/
|
||||
|
||||
char *
|
||||
colon(cp)
|
||||
char *cp;
|
||||
{
|
||||
int flag = 0;
|
||||
|
||||
if (*cp == ':') /* Leading colon is part of file name. */
|
||||
return (0);
|
||||
if (*cp == '[')
|
||||
flag = 1;
|
||||
|
||||
for (; *cp; ++cp) {
|
||||
if (*cp == ':')
|
||||
if (*cp == '@' && *(cp+1) == '[')
|
||||
flag = 1;
|
||||
if (*cp == ']' && *(cp+1) == ':' && flag)
|
||||
return (cp+1);
|
||||
if (*cp == ':' && !flag)
|
||||
return (cp);
|
||||
if (*cp == '/')
|
||||
return (0);
|
||||
|
88
servconf.c
88
servconf.c
@ -12,20 +12,24 @@
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
RCSID("$Id: servconf.c,v 1.7 1999/11/25 00:54:59 damien Exp $");
|
||||
RCSID("$Id: servconf.c,v 1.8 2000/01/14 04:45:51 damien Exp $");
|
||||
|
||||
#include "ssh.h"
|
||||
#include "servconf.h"
|
||||
#include "xmalloc.h"
|
||||
|
||||
/* add listen address */
|
||||
void add_listen_addr(ServerOptions *options, char *addr);
|
||||
|
||||
/* Initializes the server options to their default values. */
|
||||
|
||||
void
|
||||
initialize_server_options(ServerOptions *options)
|
||||
{
|
||||
memset(options, 0, sizeof(*options));
|
||||
options->port = -1;
|
||||
options->listen_addr.s_addr = htonl(INADDR_ANY);
|
||||
options->num_ports = 0;
|
||||
options->ports_from_cmdline = 0;
|
||||
options->listen_addrs = NULL;
|
||||
options->host_key_file = NULL;
|
||||
options->server_key_bits = -1;
|
||||
options->login_grace_time = -1;
|
||||
@ -68,16 +72,10 @@ initialize_server_options(ServerOptions *options)
|
||||
void
|
||||
fill_default_server_options(ServerOptions *options)
|
||||
{
|
||||
if (options->port == -1) {
|
||||
struct servent *sp;
|
||||
|
||||
sp = getservbyname(SSH_SERVICE_NAME, "tcp");
|
||||
if (sp)
|
||||
options->port = ntohs(sp->s_port);
|
||||
else
|
||||
options->port = SSH_DEFAULT_PORT;
|
||||
endservent();
|
||||
}
|
||||
if (options->num_ports == 0)
|
||||
options->ports[options->num_ports++] = SSH_DEFAULT_PORT;
|
||||
if (options->listen_addrs == NULL)
|
||||
add_listen_addr(options, NULL);
|
||||
if (options->host_key_file == NULL)
|
||||
options->host_key_file = HOST_KEY_FILE;
|
||||
if (options->server_key_bits == -1)
|
||||
@ -232,6 +230,37 @@ parse_token(const char *cp, const char *filename,
|
||||
return sBadOption;
|
||||
}
|
||||
|
||||
/*
|
||||
* add listen address
|
||||
*/
|
||||
void
|
||||
add_listen_addr(ServerOptions *options, char *addr)
|
||||
{
|
||||
extern int IPv4or6;
|
||||
struct addrinfo hints, *ai, *aitop;
|
||||
char strport[NI_MAXSERV];
|
||||
int gaierr;
|
||||
int i;
|
||||
|
||||
if (options->num_ports == 0)
|
||||
options->ports[options->num_ports++] = SSH_DEFAULT_PORT;
|
||||
for (i = 0; i < options->num_ports; i++) {
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_family = IPv4or6;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
hints.ai_flags = (addr == NULL) ? AI_PASSIVE : 0;
|
||||
snprintf(strport, sizeof strport, "%d", options->ports[i]);
|
||||
if ((gaierr = getaddrinfo(addr, strport, &hints, &aitop)) != 0)
|
||||
fatal("bad addr or host: %s (%s)\n",
|
||||
addr ? addr : "<NULL>",
|
||||
gai_strerror(gaierr));
|
||||
for (ai = aitop; ai->ai_next; ai = ai->ai_next)
|
||||
;
|
||||
ai->ai_next = options->listen_addrs;
|
||||
options->listen_addrs = aitop;
|
||||
}
|
||||
}
|
||||
|
||||
/* Reads the server configuration file. */
|
||||
|
||||
void
|
||||
@ -262,7 +291,24 @@ read_server_config(ServerOptions *options, const char *filename)
|
||||
bad_options++;
|
||||
continue;
|
||||
case sPort:
|
||||
intptr = &options->port;
|
||||
/* ignore ports from configfile if cmdline specifies ports */
|
||||
if (options->ports_from_cmdline)
|
||||
continue;
|
||||
if (options->listen_addrs != NULL)
|
||||
fatal("%s line %d: ports must be specified before "
|
||||
"ListenAdress.\n", filename, linenum);
|
||||
if (options->num_ports >= MAX_PORTS)
|
||||
fatal("%s line %d: too many ports.\n",
|
||||
filename, linenum);
|
||||
cp = strtok(NULL, WHITESPACE);
|
||||
if (!cp)
|
||||
fatal("%s line %d: missing port number.\n",
|
||||
filename, linenum);
|
||||
options->ports[options->num_ports++] = atoi(cp);
|
||||
break;
|
||||
|
||||
case sServerKeyBits:
|
||||
intptr = &options->server_key_bits;
|
||||
parse_int:
|
||||
cp = strtok(NULL, WHITESPACE);
|
||||
if (!cp) {
|
||||
@ -275,10 +321,6 @@ parse_int:
|
||||
*intptr = value;
|
||||
break;
|
||||
|
||||
case sServerKeyBits:
|
||||
intptr = &options->server_key_bits;
|
||||
goto parse_int;
|
||||
|
||||
case sLoginGraceTime:
|
||||
intptr = &options->login_grace_time;
|
||||
goto parse_int;
|
||||
@ -289,12 +331,10 @@ parse_int:
|
||||
|
||||
case sListenAddress:
|
||||
cp = strtok(NULL, WHITESPACE);
|
||||
if (!cp) {
|
||||
fprintf(stderr, "%s line %d: missing inet addr.\n",
|
||||
filename, linenum);
|
||||
exit(1);
|
||||
}
|
||||
options->listen_addr.s_addr = inet_addr(cp);
|
||||
if (!cp)
|
||||
fatal("%s line %d: missing inet addr.\n",
|
||||
filename, linenum);
|
||||
add_listen_addr(options, cp);
|
||||
break;
|
||||
|
||||
case sHostKeyFile:
|
||||
|
12
servconf.h
12
servconf.h
@ -13,20 +13,24 @@
|
||||
*
|
||||
*/
|
||||
|
||||
/* RCSID("$Id: servconf.h,v 1.5 1999/11/25 00:54:59 damien Exp $"); */
|
||||
/* RCSID("$Id: servconf.h,v 1.6 2000/01/14 04:45:51 damien Exp $"); */
|
||||
|
||||
#ifndef SERVCONF_H
|
||||
#define SERVCONF_H
|
||||
|
||||
#define MAX_PORTS 256 /* Max # ports. */
|
||||
|
||||
#define MAX_ALLOW_USERS 256 /* Max # users on allow list. */
|
||||
#define MAX_DENY_USERS 256 /* Max # users on deny list. */
|
||||
#define MAX_ALLOW_GROUPS 256 /* Max # groups on allow list. */
|
||||
#define MAX_DENY_GROUPS 256 /* Max # groups on deny list. */
|
||||
|
||||
typedef struct {
|
||||
int port; /* Port number to listen on. */
|
||||
struct in_addr listen_addr; /* Address on which the server
|
||||
* listens. */
|
||||
unsigned int num_ports;
|
||||
unsigned int ports_from_cmdline;
|
||||
u_short ports[MAX_PORTS]; /* Port number to listen on. */
|
||||
char *listen_addr; /* Address on which the server listens. */
|
||||
struct addrinfo *listen_addrs; /* Addresses on which the server listens. */
|
||||
char *host_key_file; /* File containing host key. */
|
||||
int server_key_bits;/* Size of the server key. */
|
||||
int login_grace_time; /* Disconnect if no auth in this time
|
||||
|
22
ssh.1.in
22
ssh.1.in
@ -9,7 +9,7 @@
|
||||
.\"
|
||||
.\" Created: Sat Apr 22 21:55:14 1995 ylo
|
||||
.\"
|
||||
.\" $Id: ssh.1.in,v 1.1 1999/12/26 22:23:58 damien Exp $
|
||||
.\" $Id: ssh.1.in,v 1.2 2000/01/14 04:45:51 damien Exp $
|
||||
.\"
|
||||
.Dd September 25, 1999
|
||||
.Dt SSH 1
|
||||
@ -24,7 +24,7 @@
|
||||
.Op Ar command
|
||||
.Pp
|
||||
.Nm ssh
|
||||
.Op Fl afgknqtvxCPX
|
||||
.Op Fl afgknqtvxCPX46
|
||||
.Op Fl c Ar blowfish | 3des
|
||||
.Op Fl e Ar escape_char
|
||||
.Op Fl i Ar identity_file
|
||||
@ -396,9 +396,13 @@ by allocating a socket to listen to
|
||||
on the local side, and whenever a connection is made to this port, the
|
||||
connection is forwarded over the secure channel, and a connection is
|
||||
made to
|
||||
.Ar host:hostport
|
||||
.Ar host
|
||||
port
|
||||
.Ar hostport
|
||||
from the remote machine. Port forwardings can also be specified in the
|
||||
configuration file. Only root can forward privileged ports.
|
||||
IPv6 addresses can be specified with an alternative syntax:
|
||||
.Ar port/host/hostport
|
||||
.It Fl R Ar port:host:hostport
|
||||
Specifies that the given port on the remote (server) host is to be
|
||||
forwarded to the given host and port on the local side. This works
|
||||
@ -407,10 +411,20 @@ by allocating a socket to listen to
|
||||
on the remote side, and whenever a connection is made to this port, the
|
||||
connection is forwarded over the secure channel, and a connection is
|
||||
made to
|
||||
.Ar host:hostport
|
||||
.Ar host
|
||||
port
|
||||
.Ar hostport
|
||||
from the local machine. Port forwardings can also be specified in the
|
||||
configuration file. Privileged ports can be forwarded only when
|
||||
logging in as root on the remote machine.
|
||||
.It Fl 4
|
||||
Forces
|
||||
.Nm
|
||||
to use IPv4 addresses only.
|
||||
.It Fl 6
|
||||
Forces
|
||||
.Nm
|
||||
to use IPv6 addresses only.
|
||||
.El
|
||||
.Sh CONFIGURATION FILES
|
||||
.Nm
|
||||
|
54
ssh.c
54
ssh.c
@ -11,7 +11,7 @@
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
RCSID("$Id: ssh.c,v 1.15 1999/12/28 23:17:09 damien Exp $");
|
||||
RCSID("$Id: ssh.c,v 1.16 2000/01/14 04:45:51 damien Exp $");
|
||||
|
||||
#include "xmalloc.h"
|
||||
#include "ssh.h"
|
||||
@ -27,6 +27,10 @@ extern char *__progname;
|
||||
const char *__progname = "ssh";
|
||||
#endif /* HAVE___PROGNAME */
|
||||
|
||||
/* Flag indicating whether IPv4 or IPv6. This can be set on the command line.
|
||||
Default value is AF_UNSPEC means both IPv4 and IPv6. */
|
||||
int IPv4or6 = AF_UNSPEC;
|
||||
|
||||
/* Flag indicating whether debug mode is on. This can be set on the command line. */
|
||||
int debug_flag = 0;
|
||||
|
||||
@ -59,7 +63,7 @@ Options options;
|
||||
char *host;
|
||||
|
||||
/* socket address the host resolves to */
|
||||
struct sockaddr_in hostaddr;
|
||||
struct sockaddr_storage hostaddr;
|
||||
|
||||
/*
|
||||
* Flag to indicate that we have received a window change signal which has
|
||||
@ -114,6 +118,8 @@ usage()
|
||||
fprintf(stderr, " forward them to the other side by connecting to host:port.\n");
|
||||
fprintf(stderr, " -C Enable compression.\n");
|
||||
fprintf(stderr, " -g Allow remote hosts to connect to forwarded ports.\n");
|
||||
fprintf(stderr, " -4 Use IPv4 only.\n");
|
||||
fprintf(stderr, " -6 Use IPv6 only.\n");
|
||||
fprintf(stderr, " -o 'option' Process the option as if it was read from a configuration file.\n");
|
||||
exit(1);
|
||||
}
|
||||
@ -227,6 +233,8 @@ main(int ac, char **av)
|
||||
if (host)
|
||||
break;
|
||||
if ((cp = strchr(av[optind], '@'))) {
|
||||
if(cp == av[optind])
|
||||
usage();
|
||||
options.user = av[optind];
|
||||
*cp = '\0';
|
||||
host = ++cp;
|
||||
@ -250,6 +258,14 @@ main(int ac, char **av)
|
||||
optarg = NULL;
|
||||
}
|
||||
switch (opt) {
|
||||
case '4':
|
||||
IPv4or6 = AF_INET;
|
||||
break;
|
||||
|
||||
case '6':
|
||||
IPv4or6 = AF_INET6;
|
||||
break;
|
||||
|
||||
case 'n':
|
||||
stdin_null_flag = 1;
|
||||
break;
|
||||
@ -351,8 +367,10 @@ main(int ac, char **av)
|
||||
break;
|
||||
|
||||
case 'R':
|
||||
if (sscanf(optarg, "%hu:%255[^:]:%hu", &fwd_port, buf,
|
||||
&fwd_host_port) != 3) {
|
||||
if (sscanf(optarg, "%hu/%255[^/]/%hu", &fwd_port, buf,
|
||||
&fwd_host_port) != 3 &&
|
||||
sscanf(optarg, "%hu:%255[^:]:%hu", &fwd_port, buf,
|
||||
&fwd_host_port) != 3) {
|
||||
fprintf(stderr, "Bad forwarding specification '%s'.\n", optarg);
|
||||
usage();
|
||||
/* NOTREACHED */
|
||||
@ -361,8 +379,10 @@ main(int ac, char **av)
|
||||
break;
|
||||
|
||||
case 'L':
|
||||
if (sscanf(optarg, "%hu:%255[^:]:%hu", &fwd_port, buf,
|
||||
&fwd_host_port) != 3) {
|
||||
if (sscanf(optarg, "%hu/%255[^/]/%hu", &fwd_port, buf,
|
||||
&fwd_host_port) != 3 &&
|
||||
sscanf(optarg, "%hu:%255[^:]:%hu", &fwd_port, buf,
|
||||
&fwd_host_port) != 3) {
|
||||
fprintf(stderr, "Bad forwarding specification '%s'.\n", optarg);
|
||||
usage();
|
||||
/* NOTREACHED */
|
||||
@ -473,14 +493,18 @@ main(int ac, char **av)
|
||||
|
||||
/* Find canonic host name. */
|
||||
if (strchr(host, '.') == 0) {
|
||||
struct hostent *hp = gethostbyname(host);
|
||||
if (hp != 0) {
|
||||
if (strchr(hp->h_name, '.') != 0)
|
||||
host = xstrdup(hp->h_name);
|
||||
else if (hp->h_aliases != 0
|
||||
&& hp->h_aliases[0] != 0
|
||||
&& strchr(hp->h_aliases[0], '.') != 0)
|
||||
host = xstrdup(hp->h_aliases[0]);
|
||||
struct addrinfo hints;
|
||||
struct addrinfo *ai = NULL;
|
||||
int errgai;
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_family = AF_UNSPEC;
|
||||
hints.ai_flags = AI_CANONNAME;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
errgai = getaddrinfo(host, NULL, &hints, &ai);
|
||||
if (errgai == 0) {
|
||||
if (ai->ai_canonname != NULL)
|
||||
host = xstrdup(ai->ai_canonname);
|
||||
freeaddrinfo(ai);
|
||||
}
|
||||
}
|
||||
/* Disable rhosts authentication if not running as root. */
|
||||
@ -587,7 +611,7 @@ main(int ac, char **av)
|
||||
|
||||
/* Log into the remote system. This never returns if the login fails. */
|
||||
ssh_login(host_private_key_loaded, host_private_key,
|
||||
host, &hostaddr, original_real_uid);
|
||||
host, (struct sockaddr *)&hostaddr, original_real_uid);
|
||||
|
||||
/* We no longer need the host private key. Clear it now. */
|
||||
if (host_private_key_loaded)
|
||||
|
17
ssh.h
17
ssh.h
@ -13,7 +13,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
/* RCSID("$Id: ssh.h,v 1.23 1999/12/30 04:50:55 damien Exp $"); */
|
||||
/* RCSID("$Id: ssh.h,v 1.24 2000/01/14 04:45:52 damien Exp $"); */
|
||||
|
||||
#ifndef SSH_H
|
||||
#define SSH_H
|
||||
@ -21,6 +21,8 @@
|
||||
#include <netinet/in.h> /* For struct sockaddr_in */
|
||||
#include <pwd.h> /* For struct pw */
|
||||
#include <stdarg.h> /* For va_list */
|
||||
#include <sys/socket.h> /* For struct sockaddr_storage */
|
||||
#include "fake-socket.h" /* For struct sockaddr_storage */
|
||||
#ifdef HAVE_SYS_SELECT_H
|
||||
# include <sys/select.h>
|
||||
#endif
|
||||
@ -284,7 +286,7 @@ get_last_login_time(uid_t uid, const char *logname,
|
||||
*/
|
||||
void
|
||||
record_login(int pid, const char *ttyname, const char *user, uid_t uid,
|
||||
const char *host, struct sockaddr_in * addr);
|
||||
const char *host, struct sockaddr *addr);
|
||||
|
||||
/*
|
||||
* Records that the user has logged out. This does many thigs normally done
|
||||
@ -304,7 +306,7 @@ void record_logout(int pid, const char *ttyname);
|
||||
* packet_set_connection for the connection.
|
||||
*/
|
||||
int
|
||||
ssh_connect(const char *host, struct sockaddr_in * hostaddr,
|
||||
ssh_connect(const char *host, struct sockaddr_storage * hostaddr,
|
||||
u_short port, int connection_attempts,
|
||||
int anonymous, uid_t original_real_uid,
|
||||
const char *proxy_command);
|
||||
@ -320,7 +322,7 @@ ssh_connect(const char *host, struct sockaddr_in * hostaddr,
|
||||
|
||||
void
|
||||
ssh_login(int host_key_valid, RSA * host_key, const char *host,
|
||||
struct sockaddr_in * hostaddr, uid_t original_real_uid);
|
||||
struct sockaddr * hostaddr, uid_t original_real_uid);
|
||||
|
||||
/*------------ Definitions for various authentication methods. -------*/
|
||||
|
||||
@ -380,8 +382,10 @@ const char *get_remote_ipaddr(void);
|
||||
/* Returns the port number of the peer of the socket. */
|
||||
int get_peer_port(int sock);
|
||||
|
||||
/* Returns the port number of the remote host. */
|
||||
/* Returns the port number of the remote/local host. */
|
||||
int get_remote_port(void);
|
||||
int get_local_port(void);
|
||||
|
||||
|
||||
/*
|
||||
* Tries to match the host name (which must be in all lowercase) against the
|
||||
@ -741,6 +745,9 @@ char *skey_fake_keyinfo(char *username);
|
||||
int auth_skey_password(struct passwd * pw, const char *password);
|
||||
#endif /* SKEY */
|
||||
|
||||
/* AF_UNSPEC or AF_INET or AF_INET6 */
|
||||
extern int IPv4or6;
|
||||
|
||||
#ifdef USE_PAM
|
||||
#include "auth-pam.h"
|
||||
#endif /* USE_PAM */
|
||||
|
203
sshconnect.c
203
sshconnect.c
@ -8,7 +8,7 @@
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
RCSID("$Id: sshconnect.c,v 1.20 2000/01/03 12:41:05 damien Exp $");
|
||||
RCSID("$Id: sshconnect.c,v 1.21 2000/01/14 04:45:52 damien Exp $");
|
||||
|
||||
#ifdef HAVE_OPENSSL
|
||||
#include <openssl/bn.h>
|
||||
@ -35,6 +35,7 @@ RCSID("$Id: sshconnect.c,v 1.20 2000/01/03 12:41:05 damien Exp $");
|
||||
unsigned char session_id[16];
|
||||
|
||||
extern Options options;
|
||||
extern char *__progname;
|
||||
|
||||
/*
|
||||
* Connect to the given ssh server using a proxy command.
|
||||
@ -48,10 +49,10 @@ ssh_proxy_connect(const char *host, u_short port, uid_t original_real_uid,
|
||||
char *command_string;
|
||||
int pin[2], pout[2];
|
||||
int pid;
|
||||
char portstring[100];
|
||||
char strport[NI_MAXSERV];
|
||||
|
||||
/* Convert the port number into a string. */
|
||||
snprintf(portstring, sizeof portstring, "%hu", port);
|
||||
snprintf(strport, sizeof strport, "%hu", port);
|
||||
|
||||
/* Build the final command string in the buffer by making the
|
||||
appropriate substitutions to the given proxy command. */
|
||||
@ -68,7 +69,7 @@ ssh_proxy_connect(const char *host, u_short port, uid_t original_real_uid,
|
||||
continue;
|
||||
}
|
||||
if (cp[0] == '%' && cp[1] == 'p') {
|
||||
buffer_append(&command, portstring, strlen(portstring));
|
||||
buffer_append(&command, strport, strlen(strport));
|
||||
cp++;
|
||||
continue;
|
||||
}
|
||||
@ -140,7 +141,7 @@ ssh_proxy_connect(const char *host, u_short port, uid_t original_real_uid,
|
||||
* Creates a (possibly privileged) socket for use as the ssh connection.
|
||||
*/
|
||||
int
|
||||
ssh_create_socket(uid_t original_real_uid, int privileged)
|
||||
ssh_create_socket(uid_t original_real_uid, int privileged, int family)
|
||||
{
|
||||
int sock;
|
||||
|
||||
@ -150,10 +151,9 @@ ssh_create_socket(uid_t original_real_uid, int privileged)
|
||||
*/
|
||||
if (privileged) {
|
||||
int p = IPPORT_RESERVED - 1;
|
||||
|
||||
sock = rresvport(&p);
|
||||
sock = rresvport_af(&p, family);
|
||||
if (sock < 0)
|
||||
fatal("rresvport: %.100s", strerror(errno));
|
||||
fatal("rresvport: af=%d %.100s", family, strerror(errno));
|
||||
debug("Allocated local port %d.", p);
|
||||
} else {
|
||||
/*
|
||||
@ -161,17 +161,18 @@ ssh_create_socket(uid_t original_real_uid, int privileged)
|
||||
* the user's uid to create the socket.
|
||||
*/
|
||||
temporarily_use_uid(original_real_uid);
|
||||
sock = socket(AF_INET, SOCK_STREAM, 0);
|
||||
sock = socket(family, SOCK_STREAM, 0);
|
||||
if (sock < 0)
|
||||
fatal("socket: %.100s", strerror(errno));
|
||||
error("socket: %.100s", strerror(errno));
|
||||
restore_uid();
|
||||
}
|
||||
return sock;
|
||||
}
|
||||
|
||||
/*
|
||||
* Opens a TCP/IP connection to the remote server on the given host. If
|
||||
* port is 0, the default port will be used. If anonymous is zero,
|
||||
* Opens a TCP/IP connection to the remote server on the given host.
|
||||
* The address of the remote host will be returned in hostaddr.
|
||||
* If port is 0, the default port will be used. If anonymous is zero,
|
||||
* a privileged port will be allocated to make the connection.
|
||||
* This requires super-user privileges if anonymous is false.
|
||||
* Connection_attempts specifies the maximum number of tries (one per
|
||||
@ -180,15 +181,16 @@ ssh_create_socket(uid_t original_real_uid, int privileged)
|
||||
* the daemon.
|
||||
*/
|
||||
int
|
||||
ssh_connect(const char *host, struct sockaddr_in * hostaddr,
|
||||
ssh_connect(const char *host, struct sockaddr_storage * hostaddr,
|
||||
u_short port, int connection_attempts,
|
||||
int anonymous, uid_t original_real_uid,
|
||||
const char *proxy_command)
|
||||
{
|
||||
int sock = -1, attempt, i;
|
||||
int on = 1;
|
||||
int sock = -1, attempt;
|
||||
struct servent *sp;
|
||||
struct hostent *hp;
|
||||
struct addrinfo hints, *ai, *aitop;
|
||||
char ntop[NI_MAXHOST], strport[NI_MAXSERV];
|
||||
int gaierr;
|
||||
struct linger linger;
|
||||
|
||||
debug("ssh_connect: getuid %d geteuid %d anon %d",
|
||||
@ -208,8 +210,13 @@ ssh_connect(const char *host, struct sockaddr_in * hostaddr,
|
||||
|
||||
/* No proxy command. */
|
||||
|
||||
/* No host lookup made yet. */
|
||||
hp = NULL;
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_family = IPv4or6;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
snprintf(strport, sizeof strport, "%d", port);
|
||||
if ((gaierr = getaddrinfo(host, strport, &hints, &aitop)) != 0)
|
||||
fatal("%s: %.100s: %s", __progname, host,
|
||||
gai_strerror(gaierr));
|
||||
|
||||
/*
|
||||
* Try to connect several times. On some machines, the first time
|
||||
@ -220,82 +227,40 @@ ssh_connect(const char *host, struct sockaddr_in * hostaddr,
|
||||
if (attempt > 0)
|
||||
debug("Trying again...");
|
||||
|
||||
/* Try to parse the host name as a numeric inet address. */
|
||||
memset(hostaddr, 0, sizeof(hostaddr));
|
||||
hostaddr->sin_family = AF_INET;
|
||||
hostaddr->sin_port = htons(port);
|
||||
hostaddr->sin_addr.s_addr = inet_addr(host);
|
||||
if ((hostaddr->sin_addr.s_addr & 0xffffffff) != 0xffffffff) {
|
||||
/* Valid numeric IP address */
|
||||
debug("Connecting to %.100s port %d.",
|
||||
inet_ntoa(hostaddr->sin_addr), port);
|
||||
/* Loop through addresses for this host, and try each one in
|
||||
sequence until the connection succeeds. */
|
||||
for (ai = aitop; ai; ai = ai->ai_next) {
|
||||
if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6)
|
||||
continue;
|
||||
if (getnameinfo(ai->ai_addr, ai->ai_addrlen,
|
||||
ntop, sizeof(ntop), strport, sizeof(strport),
|
||||
NI_NUMERICHOST|NI_NUMERICSERV) != 0) {
|
||||
error("ssh_connect: getnameinfo failed");
|
||||
continue;
|
||||
}
|
||||
debug("Connecting to %.200s [%.100s] port %s.",
|
||||
host, ntop, strport);
|
||||
|
||||
/* Create a socket. */
|
||||
sock = ssh_create_socket(original_real_uid,
|
||||
!anonymous && geteuid() == 0 &&
|
||||
port < IPPORT_RESERVED);
|
||||
/* Create a socket for connecting. */
|
||||
sock = ssh_create_socket(original_real_uid,
|
||||
!anonymous && geteuid() == 0 && port < IPPORT_RESERVED,
|
||||
ai->ai_family);
|
||||
if (sock < 0)
|
||||
continue;
|
||||
|
||||
/*
|
||||
* Connect to the host. We use the user's uid in the
|
||||
* hope that it will help with the problems of
|
||||
* tcp_wrappers showing the remote uid as root.
|
||||
/* Connect to the host. We use the user's uid in the
|
||||
* hope that it will help with tcp_wrappers showing
|
||||
* the remote uid as root.
|
||||
*/
|
||||
temporarily_use_uid(original_real_uid);
|
||||
if (connect(sock, (struct sockaddr *) hostaddr, sizeof(*hostaddr))
|
||||
>= 0) {
|
||||
/* Successful connect. */
|
||||
if (connect(sock, ai->ai_addr, ai->ai_addrlen) >= 0) {
|
||||
/* Successful connection. */
|
||||
memcpy(hostaddr, ai->ai_addr, sizeof(*(ai->ai_addr)));
|
||||
restore_uid();
|
||||
break;
|
||||
}
|
||||
debug("connect: %.100s", strerror(errno));
|
||||
restore_uid();
|
||||
|
||||
/* Destroy the failed socket. */
|
||||
shutdown(sock, SHUT_RDWR);
|
||||
close(sock);
|
||||
} else {
|
||||
/* Not a valid numeric inet address. */
|
||||
/* Map host name to an address. */
|
||||
if (!hp)
|
||||
hp = gethostbyname(host);
|
||||
if (!hp)
|
||||
fatal("Bad host name: %.100s", host);
|
||||
if (!hp->h_addr_list[0])
|
||||
fatal("Host does not have an IP address: %.100s", host);
|
||||
|
||||
/* Loop through addresses for this host, and try
|
||||
each one in sequence until the connection
|
||||
succeeds. */
|
||||
for (i = 0; hp->h_addr_list[i]; i++) {
|
||||
/* Set the address to connect to. */
|
||||
hostaddr->sin_family = hp->h_addrtype;
|
||||
memcpy(&hostaddr->sin_addr, hp->h_addr_list[i],
|
||||
sizeof(hostaddr->sin_addr));
|
||||
|
||||
debug("Connecting to %.200s [%.100s] port %d.",
|
||||
host, inet_ntoa(hostaddr->sin_addr), port);
|
||||
|
||||
/* Create a socket for connecting. */
|
||||
sock = ssh_create_socket(original_real_uid,
|
||||
!anonymous && geteuid() == 0 &&
|
||||
port < IPPORT_RESERVED);
|
||||
|
||||
/*
|
||||
* Connect to the host. We use the user's
|
||||
* uid in the hope that it will help with
|
||||
* tcp_wrappers showing the remote uid as
|
||||
* root.
|
||||
*/
|
||||
temporarily_use_uid(original_real_uid);
|
||||
if (connect(sock, (struct sockaddr *) hostaddr,
|
||||
sizeof(*hostaddr)) >= 0) {
|
||||
/* Successful connection. */
|
||||
restore_uid();
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
debug("connect: %.100s", strerror(errno));
|
||||
restore_uid();
|
||||
|
||||
/*
|
||||
* Close the failed socket; there appear to
|
||||
* be some problems when reusing a socket for
|
||||
@ -305,13 +270,16 @@ ssh_connect(const char *host, struct sockaddr_in * hostaddr,
|
||||
shutdown(sock, SHUT_RDWR);
|
||||
close(sock);
|
||||
}
|
||||
if (hp->h_addr_list[i])
|
||||
break; /* Successful connection. */
|
||||
}
|
||||
if (ai)
|
||||
break; /* Successful connection. */
|
||||
|
||||
/* Sleep a moment before retrying. */
|
||||
sleep(1);
|
||||
}
|
||||
|
||||
freeaddrinfo(aitop);
|
||||
|
||||
/* Return failure if we didn't get a successful connection. */
|
||||
if (attempt >= connection_attempts)
|
||||
return 0;
|
||||
@ -323,7 +291,6 @@ ssh_connect(const char *host, struct sockaddr_in * hostaddr,
|
||||
* as it has been closed for whatever reason.
|
||||
*/
|
||||
/* setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void *)&on, sizeof(on)); */
|
||||
setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (void *) &on, sizeof(on));
|
||||
linger.l_onoff = 1;
|
||||
linger.l_linger = 5;
|
||||
setsockopt(sock, SOL_SOCKET, SO_LINGER, (void *) &linger, sizeof(linger));
|
||||
@ -1095,17 +1062,43 @@ read_yes_or_no(const char *prompt, int defval)
|
||||
*/
|
||||
|
||||
void
|
||||
check_host_key(char *host,
|
||||
struct sockaddr_in *hostaddr,
|
||||
RSA *host_key)
|
||||
check_host_key(char *host, struct sockaddr *hostaddr, RSA *host_key)
|
||||
{
|
||||
RSA *file_key;
|
||||
char *ip = NULL;
|
||||
char hostline[1000], *hostp;
|
||||
HostStatus host_status;
|
||||
HostStatus ip_status;
|
||||
int host_ip_differ = 0;
|
||||
int local = (ntohl(hostaddr->sin_addr.s_addr) >> 24) == IN_LOOPBACKNET;
|
||||
int local = 0, host_ip_differ = 0;
|
||||
int sa_len;
|
||||
char ntop[NI_MAXHOST];
|
||||
|
||||
/*
|
||||
* Force accepting of the host key for loopback/localhost. The
|
||||
* problem is that if the home directory is NFS-mounted to multiple
|
||||
* machines, localhost will refer to a different machine in each of
|
||||
* them, and the user will get bogus HOST_CHANGED warnings. This
|
||||
* essentially disables host authentication for localhost; however,
|
||||
* this is probably not a real problem.
|
||||
*/
|
||||
switch (hostaddr->sa_family) {
|
||||
case AF_INET:
|
||||
local = (ntohl(((struct sockaddr_in *)hostaddr)->sin_addr.s_addr) >> 24) == IN_LOOPBACKNET;
|
||||
sa_len = sizeof(struct sockaddr_in);
|
||||
break;
|
||||
case AF_INET6:
|
||||
local = IN6_IS_ADDR_LOOPBACK(&(((struct sockaddr_in6 *)hostaddr)->sin6_addr));
|
||||
sa_len = sizeof(struct sockaddr_in6);
|
||||
break;
|
||||
default:
|
||||
local = 0;
|
||||
sa_len = sizeof(struct sockaddr_storage);
|
||||
break;
|
||||
}
|
||||
if (local) {
|
||||
debug("Forcing accepting of host key for loopback/localhost.");
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Turn off check_host_ip for proxy connects, since
|
||||
@ -1114,8 +1107,12 @@ check_host_key(char *host,
|
||||
if (options.proxy_command != NULL && options.check_host_ip)
|
||||
options.check_host_ip = 0;
|
||||
|
||||
if (options.check_host_ip)
|
||||
ip = xstrdup(inet_ntoa(hostaddr->sin_addr));
|
||||
if (options.check_host_ip) {
|
||||
if (getnameinfo(hostaddr, sa_len, ntop, sizeof(ntop),
|
||||
NULL, 0, NI_NUMERICHOST) != 0)
|
||||
fatal("check_host_key: getnameinfo failed");
|
||||
ip = xstrdup(ntop);
|
||||
}
|
||||
|
||||
/*
|
||||
* Store the host key from the known host file in here so that we can
|
||||
@ -1136,18 +1133,6 @@ check_host_key(char *host,
|
||||
host_status = check_host_in_hostfile(options.system_hostfile, host,
|
||||
host_key->e, host_key->n,
|
||||
file_key->e, file_key->n);
|
||||
/*
|
||||
* Force accepting of the host key for localhost and 127.0.0.1. The
|
||||
* problem is that if the home directory is NFS-mounted to multiple
|
||||
* machines, localhost will refer to a different machine in each of
|
||||
* them, and the user will get bogus HOST_CHANGED warnings. This
|
||||
* essentially disables host authentication for localhost; however,
|
||||
* this is probably not a real problem.
|
||||
*/
|
||||
if (local) {
|
||||
debug("Forcing accepting of host key for localhost.");
|
||||
host_status = HOST_OK;
|
||||
}
|
||||
/*
|
||||
* Also perform check for the ip address, skip the check if we are
|
||||
* localhost or the hostname was an ip address to begin with
|
||||
@ -1301,7 +1286,7 @@ void
|
||||
ssh_login(int host_key_valid,
|
||||
RSA *own_host_key,
|
||||
const char *orighost,
|
||||
struct sockaddr_in *hostaddr,
|
||||
struct sockaddr *hostaddr,
|
||||
uid_t original_real_uid)
|
||||
{
|
||||
int i, type;
|
||||
|
17
sshd.8.in
17
sshd.8.in
@ -9,7 +9,7 @@
|
||||
.\"
|
||||
.\" Created: Sat Apr 22 21:55:14 1995 ylo
|
||||
.\"
|
||||
.\" $Id: sshd.8.in,v 1.1 1999/12/26 22:23:59 damien Exp $
|
||||
.\" $Id: sshd.8.in,v 1.2 2000/01/14 04:45:52 damien Exp $
|
||||
.\"
|
||||
.Dd September 25, 1999
|
||||
.Dt SSHD 8
|
||||
@ -19,7 +19,7 @@
|
||||
.Nd secure shell daemon
|
||||
.Sh SYNOPSIS
|
||||
.Nm sshd
|
||||
.Op Fl diqQ
|
||||
.Op Fl diqQ46
|
||||
.Op Fl b Ar bits
|
||||
.Op Fl f Ar config_file
|
||||
.Op Fl g Ar login_grace_time
|
||||
@ -173,6 +173,14 @@ When this options is specified
|
||||
assumes the client has sent the given version string
|
||||
and skips the
|
||||
Protocol Version Identification Exchange.
|
||||
.It Fl 4
|
||||
Forces
|
||||
.Nm
|
||||
to use IPv4 addresses only.
|
||||
.It Fl 6
|
||||
Forces
|
||||
.Nm
|
||||
to use IPv6 addresses only.
|
||||
.El
|
||||
.Sh CONFIGURATION FILE
|
||||
.Nm
|
||||
@ -320,6 +328,10 @@ Specifies what local address
|
||||
.Nm
|
||||
should listen on.
|
||||
The default is to listen to all local addresses.
|
||||
Multiple options of this type are permitted.
|
||||
Additionally, the
|
||||
.Cm Ports
|
||||
options must precede this option.
|
||||
.It Cm LoginGraceTime
|
||||
The server disconnects after this time if the user has not
|
||||
successfully logged in. If the value is 0, there is no time limit.
|
||||
@ -365,6 +377,7 @@ normally not allowed).
|
||||
Specifies the port number that
|
||||
.Nm
|
||||
listens on. The default is 22.
|
||||
Multiple options of this type are permitted.
|
||||
.It Cm PrintMotd
|
||||
Specifies whether
|
||||
.Nm
|
||||
|
243
sshd.c
243
sshd.c
@ -11,7 +11,7 @@
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
RCSID("$Id: sshd.c,v 1.49 1999/12/30 04:08:44 damien Exp $");
|
||||
RCSID("$Id: sshd.c,v 1.50 2000/01/14 04:45:52 damien Exp $");
|
||||
|
||||
#include "xmalloc.h"
|
||||
#include "rsa.h"
|
||||
@ -45,6 +45,12 @@ ServerOptions options;
|
||||
/* Name of the server configuration file. */
|
||||
char *config_file_name = SERVER_CONFIG_FILE;
|
||||
|
||||
/*
|
||||
* Flag indicating whether IPv4 or IPv6. This can be set on the command line.
|
||||
* Default value is AF_UNSPEC means both IPv4 and IPv6.
|
||||
*/
|
||||
int IPv4or6 = AF_UNSPEC;
|
||||
|
||||
/*
|
||||
* Debug mode flag. This can be set on the command line. If debug
|
||||
* mode is enabled, extra debugging output will be sent to the system
|
||||
@ -66,10 +72,12 @@ char *av0;
|
||||
char **saved_argv;
|
||||
|
||||
/*
|
||||
* This is set to the socket that the server is listening; this is used in
|
||||
* the SIGHUP signal handler.
|
||||
* The sockets that the server is listening; this is used in the SIGHUP
|
||||
* signal handler.
|
||||
*/
|
||||
int listen_sock;
|
||||
#define MAX_LISTEN_SOCKS 16
|
||||
int listen_socks[MAX_LISTEN_SOCKS];
|
||||
int num_listen_socks = 0;
|
||||
|
||||
/*
|
||||
* the client's version string, passed by sshd2 in compat mode. if != NULL,
|
||||
@ -135,6 +143,18 @@ void do_child(const char *command, struct passwd * pw, const char *term,
|
||||
const char *display, const char *auth_proto,
|
||||
const char *auth_data, const char *ttyname);
|
||||
|
||||
/*
|
||||
* Close all listening sockets
|
||||
*/
|
||||
void
|
||||
close_listen_socks(void)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < num_listen_socks; i++)
|
||||
close(listen_socks[i]);
|
||||
num_listen_socks = -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Signal handler for SIGHUP. Sshd execs itself when it receives SIGHUP;
|
||||
* the effect is to reread the configuration file (and to regenerate
|
||||
@ -155,7 +175,7 @@ void
|
||||
sighup_restart()
|
||||
{
|
||||
log("Received SIGHUP; restarting.");
|
||||
close(listen_sock);
|
||||
close_listen_socks();
|
||||
execv(saved_argv[0], saved_argv);
|
||||
log("RESTART FAILED: av0='%s', error: %s.", av0, strerror(errno));
|
||||
exit(1);
|
||||
@ -170,7 +190,7 @@ void
|
||||
sigterm_handler(int sig)
|
||||
{
|
||||
log("Received signal %d; terminating.", sig);
|
||||
close(listen_sock);
|
||||
close_listen_socks();
|
||||
exit(255);
|
||||
}
|
||||
|
||||
@ -277,11 +297,12 @@ main(int ac, char **av)
|
||||
{
|
||||
extern char *optarg;
|
||||
extern int optind;
|
||||
int opt, aux, sock_in, sock_out, newsock, i, pid, on = 1;
|
||||
int opt, sock_in = 0, sock_out = 0, newsock, i, fdsetsz, pid, on = 1;
|
||||
socklen_t fromlen;
|
||||
int remote_major, remote_minor;
|
||||
int silentrsa = 0;
|
||||
struct pollfd fds;
|
||||
struct sockaddr_in sin;
|
||||
fd_set *fdset;
|
||||
struct sockaddr_storage from;
|
||||
char buf[100]; /* Must not be larger than remote_version. */
|
||||
char remote_version[100]; /* Must be at least as big as buf. */
|
||||
const char *remote_ip;
|
||||
@ -289,6 +310,9 @@ main(int ac, char **av)
|
||||
char *comment;
|
||||
FILE *f;
|
||||
struct linger linger;
|
||||
struct addrinfo *ai;
|
||||
char ntop[NI_MAXHOST], strport[NI_MAXSERV];
|
||||
int listen_sock, maxfd;
|
||||
|
||||
/* Save argv[0]. */
|
||||
saved_argv = av;
|
||||
@ -301,8 +325,14 @@ main(int ac, char **av)
|
||||
initialize_server_options(&options);
|
||||
|
||||
/* Parse command-line arguments. */
|
||||
while ((opt = getopt(ac, av, "f:p:b:k:h:g:V:diqQ")) != EOF) {
|
||||
while ((opt = getopt(ac, av, "f:p:b:k:h:g:V:diqQ46")) != EOF) {
|
||||
switch (opt) {
|
||||
case '4':
|
||||
IPv4or6 = AF_INET;
|
||||
break;
|
||||
case '6':
|
||||
IPv4or6 = AF_INET6;
|
||||
break;
|
||||
case 'f':
|
||||
config_file_name = optarg;
|
||||
break;
|
||||
@ -323,7 +353,10 @@ main(int ac, char **av)
|
||||
options.server_key_bits = atoi(optarg);
|
||||
break;
|
||||
case 'p':
|
||||
options.port = atoi(optarg);
|
||||
options.ports_from_cmdline = 1;
|
||||
if (options.num_ports >= MAX_PORTS)
|
||||
fatal("too many ports.\n");
|
||||
options.ports[options.num_ports++] = atoi(optarg);
|
||||
break;
|
||||
case 'g':
|
||||
options.login_grace_time = atoi(optarg);
|
||||
@ -356,11 +389,22 @@ main(int ac, char **av)
|
||||
fprintf(stderr, " -g seconds Grace period for authentication (default: 300)\n");
|
||||
fprintf(stderr, " -b bits Size of server RSA key (default: 768 bits)\n");
|
||||
fprintf(stderr, " -h file File from which to read host key (default: %s)\n",
|
||||
HOST_KEY_FILE);
|
||||
HOST_KEY_FILE);
|
||||
fprintf(stderr, " -4 Use IPv4 only\n");
|
||||
fprintf(stderr, " -6 Use IPv6 only\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Force logging to stderr until we have loaded the private host
|
||||
* key (unless started from inetd)
|
||||
*/
|
||||
log_init(av0,
|
||||
options.log_level == -1 ? SYSLOG_LEVEL_INFO : options.log_level,
|
||||
options.log_facility == -1 ? SYSLOG_FACILITY_AUTH : options.log_facility,
|
||||
!inetd_flag);
|
||||
|
||||
/* check if RSA support exists */
|
||||
if (rsa_alive() == 0) {
|
||||
if (silentrsa == 0)
|
||||
@ -380,18 +424,11 @@ main(int ac, char **av)
|
||||
fprintf(stderr, "Bad server key size.\n");
|
||||
exit(1);
|
||||
}
|
||||
if (options.port < 1 || options.port > 65535) {
|
||||
fprintf(stderr, "Bad port number.\n");
|
||||
exit(1);
|
||||
}
|
||||
/* Check that there are no remaining arguments. */
|
||||
if (optind < ac) {
|
||||
fprintf(stderr, "Extra argument %s.\n", av[optind]);
|
||||
exit(1);
|
||||
}
|
||||
/* Force logging to stderr while loading the private host key
|
||||
unless started from inetd */
|
||||
log_init(av0, options.log_level, options.log_facility, !inetd_flag);
|
||||
|
||||
debug("sshd version %.100s", SSH_VERSION);
|
||||
|
||||
@ -480,32 +517,66 @@ main(int ac, char **av)
|
||||
arc4random_stir();
|
||||
log("RSA key generation complete.");
|
||||
} else {
|
||||
/* Create socket for listening. */
|
||||
listen_sock = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if (listen_sock < 0)
|
||||
fatal("socket: %.100s", strerror(errno));
|
||||
for (ai = options.listen_addrs; ai; ai = ai->ai_next) {
|
||||
if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6)
|
||||
continue;
|
||||
if (num_listen_socks >= MAX_LISTEN_SOCKS)
|
||||
fatal("Too many listen sockets. "
|
||||
"Enlarge MAX_LISTEN_SOCKS");
|
||||
if (getnameinfo(ai->ai_addr, ai->ai_addrlen,
|
||||
ntop, sizeof(ntop), strport, sizeof(strport),
|
||||
NI_NUMERICHOST|NI_NUMERICSERV) != 0) {
|
||||
error("getnameinfo failed");
|
||||
continue;
|
||||
}
|
||||
/* Create socket for listening. */
|
||||
listen_sock = socket(ai->ai_family, SOCK_STREAM, 0);
|
||||
if (listen_sock < 0) {
|
||||
/* kernel may not support ipv6 */
|
||||
verbose("socket: %.100s", strerror(errno));
|
||||
continue;
|
||||
}
|
||||
if (fcntl(listen_sock, F_SETFL, O_NONBLOCK) < 0) {
|
||||
error("listen_sock O_NONBLOCK: %s", strerror(errno));
|
||||
close(listen_sock);
|
||||
continue;
|
||||
}
|
||||
/*
|
||||
* Set socket options. We try to make the port
|
||||
* reusable and have it close as fast as possible
|
||||
* without waiting in unnecessary wait states on
|
||||
* close.
|
||||
*/
|
||||
setsockopt(listen_sock, SOL_SOCKET, SO_REUSEADDR,
|
||||
(void *) &on, sizeof(on));
|
||||
linger.l_onoff = 1;
|
||||
linger.l_linger = 5;
|
||||
setsockopt(listen_sock, SOL_SOCKET, SO_LINGER,
|
||||
(void *) &linger, sizeof(linger));
|
||||
|
||||
/* Set socket options. We try to make the port reusable
|
||||
and have it close as fast as possible without waiting
|
||||
in unnecessary wait states on close. */
|
||||
setsockopt(listen_sock, SOL_SOCKET, SO_REUSEADDR, (void *) &on,
|
||||
sizeof(on));
|
||||
linger.l_onoff = 1;
|
||||
linger.l_linger = 5;
|
||||
setsockopt(listen_sock, SOL_SOCKET, SO_LINGER, (void *) &linger,
|
||||
sizeof(linger));
|
||||
debug("Bind to port %s on %s.", strport, ntop);
|
||||
|
||||
memset(&sin, 0, sizeof(sin));
|
||||
sin.sin_family = AF_INET;
|
||||
sin.sin_addr = options.listen_addr;
|
||||
sin.sin_port = htons(options.port);
|
||||
/* Bind the socket to the desired port. */
|
||||
if (bind(listen_sock, ai->ai_addr, ai->ai_addrlen) < 0) {
|
||||
error("Bind to port %s on %s failed: %.200s.",
|
||||
strport, ntop, strerror(errno));
|
||||
close(listen_sock);
|
||||
continue;
|
||||
}
|
||||
listen_socks[num_listen_socks] = listen_sock;
|
||||
num_listen_socks++;
|
||||
|
||||
/* Start listening on the port. */
|
||||
log("Server listening on %s port %s.", ntop, strport);
|
||||
if (listen(listen_sock, 5) < 0)
|
||||
fatal("listen: %.100s", strerror(errno));
|
||||
|
||||
if (bind(listen_sock, (struct sockaddr *) & sin, sizeof(sin)) < 0) {
|
||||
error("bind: %.100s", strerror(errno));
|
||||
shutdown(listen_sock, SHUT_RDWR);
|
||||
close(listen_sock);
|
||||
fatal("Bind to port %d failed.", options.port);
|
||||
}
|
||||
freeaddrinfo(options.listen_addrs);
|
||||
|
||||
if (!num_listen_socks)
|
||||
fatal("Cannot bind any address.");
|
||||
|
||||
if (!debug_flag) {
|
||||
/*
|
||||
* Record our pid in /etc/sshd_pid to make it easier
|
||||
@ -521,10 +592,6 @@ main(int ac, char **av)
|
||||
}
|
||||
}
|
||||
|
||||
log("Server listening on port %d.", options.port);
|
||||
if (listen(listen_sock, 5) < 0)
|
||||
fatal("listen: %.100s", strerror(errno));
|
||||
|
||||
public_key = RSA_new();
|
||||
sensitive_data.private_key = RSA_new();
|
||||
|
||||
@ -546,6 +613,14 @@ main(int ac, char **av)
|
||||
/* Arrange SIGCHLD to be caught. */
|
||||
signal(SIGCHLD, main_sigchld_handler);
|
||||
|
||||
/* setup fd set for listen */
|
||||
maxfd = 0;
|
||||
for (i = 0; i < num_listen_socks; i++)
|
||||
if (listen_socks[i] > maxfd)
|
||||
maxfd = listen_socks[i];
|
||||
fdsetsz = howmany(maxfd, NFDBITS) * sizeof(fd_mask);
|
||||
fdset = (fd_set *)xmalloc(fdsetsz);
|
||||
|
||||
/*
|
||||
* Stay listening for connections until the system crashes or
|
||||
* the daemon is killed with a signal.
|
||||
@ -553,26 +628,28 @@ main(int ac, char **av)
|
||||
for (;;) {
|
||||
if (received_sighup)
|
||||
sighup_restart();
|
||||
/* Wait in poll until there is a connection. */
|
||||
memset(&fds, 0, sizeof(fds));
|
||||
fds.fd = listen_sock;
|
||||
fds.events = POLLIN;
|
||||
if (poll(&fds, 1, -1) == -1) {
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
fatal("poll: %.100s", strerror(errno));
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
if (fds.revents == 0)
|
||||
/* Wait in select until there is a connection. */
|
||||
memset(fdset, 0, fdsetsz);
|
||||
for (i = 0; i < num_listen_socks; i++)
|
||||
FD_SET(listen_socks[i], fdset);
|
||||
if (select(maxfd + 1, fdset, NULL, NULL, NULL) < 0) {
|
||||
if (errno != EINTR)
|
||||
error("select: %.100s", strerror(errno));
|
||||
continue;
|
||||
aux = sizeof(sin);
|
||||
newsock = accept(listen_sock, (struct sockaddr *) & sin, &aux);
|
||||
if (received_sighup)
|
||||
sighup_restart();
|
||||
if (newsock < 0) {
|
||||
if (errno == EINTR)
|
||||
}
|
||||
for (i = 0; i < num_listen_socks; i++) {
|
||||
if (!FD_ISSET(listen_socks[i], fdset))
|
||||
continue;
|
||||
error("accept: %.100s", strerror(errno));
|
||||
fromlen = sizeof(from);
|
||||
newsock = accept(listen_socks[i], (struct sockaddr *)&from,
|
||||
&fromlen);
|
||||
if (newsock < 0) {
|
||||
if (errno != EINTR && errno != EWOULDBLOCK)
|
||||
error("accept: %.100s", strerror(errno));
|
||||
continue;
|
||||
}
|
||||
if (fcntl(newsock, F_SETFL, 0) < 0) {
|
||||
error("newsock del O_NONBLOCK: %s", strerror(errno));
|
||||
continue;
|
||||
}
|
||||
/*
|
||||
@ -586,7 +663,7 @@ main(int ac, char **av)
|
||||
* connection without forking.
|
||||
*/
|
||||
debug("Server will not fork when running in debugging mode.");
|
||||
close(listen_sock);
|
||||
close_listen_socks();
|
||||
sock_in = newsock;
|
||||
sock_out = newsock;
|
||||
pid = getpid();
|
||||
@ -603,7 +680,7 @@ main(int ac, char **av)
|
||||
* accepted socket. Reinitialize logging (since our pid has
|
||||
* changed). We break out of the loop to handle the connection.
|
||||
*/
|
||||
close(listen_sock);
|
||||
close_listen_socks();
|
||||
sock_in = newsock;
|
||||
sock_out = newsock;
|
||||
log_init(av0, options.log_level, options.log_facility, log_stderr);
|
||||
@ -624,6 +701,10 @@ main(int ac, char **av)
|
||||
|
||||
/* Close the new socket (the child is now taking care of it). */
|
||||
close(newsock);
|
||||
} /* for (i = 0; i < num_listen_socks; i++) */
|
||||
/* child process check (or debug mode) */
|
||||
if (num_listen_socks < 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -662,6 +743,7 @@ main(int ac, char **av)
|
||||
|
||||
/* Check whether logins are denied from this host. */
|
||||
#ifdef LIBWRAP
|
||||
/* XXX LIBWRAP noes not know about IPv6 */
|
||||
{
|
||||
struct request_info req;
|
||||
|
||||
@ -673,12 +755,11 @@ main(int ac, char **av)
|
||||
close(sock_out);
|
||||
refuse(&req);
|
||||
}
|
||||
verbose("Connection from %.500s port %d", eval_client(&req), remote_port);
|
||||
/*XXX IPv6 verbose("Connection from %.500s port %d", eval_client(&req), remote_port); */
|
||||
}
|
||||
#else
|
||||
#endif /* LIBWRAP */
|
||||
/* Log the connection. */
|
||||
verbose("Connection from %.500s port %d", remote_ip, remote_port);
|
||||
#endif /* LIBWRAP */
|
||||
|
||||
/*
|
||||
* We don\'t want to listen forever unless the other side
|
||||
@ -700,12 +781,12 @@ main(int ac, char **av)
|
||||
snprintf(buf, sizeof buf, "SSH-%d.%d-%.100s\n",
|
||||
PROTOCOL_MAJOR, PROTOCOL_MINOR, SSH_VERSION);
|
||||
if (atomicio(write, sock_out, buf, strlen(buf)) != strlen(buf))
|
||||
fatal("Could not write ident string to %s.", get_remote_ipaddr());
|
||||
fatal("Could not write ident string to %s.", remote_ip);
|
||||
|
||||
/* Read other side\'s version identification. */
|
||||
for (i = 0; i < sizeof(buf) - 1; i++) {
|
||||
if (read(sock_in, &buf[i], 1) != 1)
|
||||
fatal("Did not receive ident string from %s.", get_remote_ipaddr());
|
||||
fatal("Did not receive ident string from %s.", remote_ip);
|
||||
if (buf[i] == '\r') {
|
||||
buf[i] = '\n';
|
||||
buf[i + 1] = 0;
|
||||
@ -732,7 +813,7 @@ main(int ac, char **av)
|
||||
close(sock_in);
|
||||
close(sock_out);
|
||||
fatal("Bad protocol version identification '%.100s' from %s",
|
||||
buf, get_remote_ipaddr());
|
||||
buf, remote_ip);
|
||||
}
|
||||
debug("Client protocol version %d.%d; client software version %.100s",
|
||||
remote_major, remote_minor, remote_version);
|
||||
@ -743,8 +824,7 @@ main(int ac, char **av)
|
||||
close(sock_in);
|
||||
close(sock_out);
|
||||
fatal("Protocol major versions differ for %s: %d vs. %d",
|
||||
get_remote_ipaddr(),
|
||||
PROTOCOL_MAJOR, remote_major);
|
||||
remote_ip, PROTOCOL_MAJOR, remote_major);
|
||||
}
|
||||
/* Check that the client has sufficiently high software version. */
|
||||
if (remote_major == 1 && remote_minor < 3)
|
||||
@ -769,6 +849,14 @@ main(int ac, char **av)
|
||||
options.rhosts_authentication = 0;
|
||||
options.rhosts_rsa_authentication = 0;
|
||||
}
|
||||
#ifdef KRB4
|
||||
if (!packet_connection_is_ipv4() &&
|
||||
options.kerberos_authentication) {
|
||||
debug("Kerberos Authentication disabled, only available for IPv4.");
|
||||
options.kerberos_authentication = 0;
|
||||
}
|
||||
#endif /* KRB4 */
|
||||
|
||||
packet_set_nonblocking();
|
||||
|
||||
/* Handle the connection. */
|
||||
@ -1935,8 +2023,8 @@ do_exec_pty(const char *command, int ptyfd, int ttyfd,
|
||||
char line[256];
|
||||
struct stat st;
|
||||
int quiet_login;
|
||||
struct sockaddr_in from;
|
||||
int fromlen;
|
||||
struct sockaddr_storage from;
|
||||
socklen_t fromlen;
|
||||
struct pty_cleanup_context cleanup_context;
|
||||
|
||||
/* Get remote host name. */
|
||||
@ -1997,7 +2085,7 @@ do_exec_pty(const char *command, int ptyfd, int ttyfd,
|
||||
}
|
||||
/* Record that there was a login on that terminal. */
|
||||
record_login(pid, ttyname, pw->pw_name, pw->pw_uid, hostname,
|
||||
&from);
|
||||
(struct sockaddr *)&from);
|
||||
|
||||
/* Check if .hushlogin exists. */
|
||||
snprintf(line, sizeof line, "%.200s/.hushlogin", pw->pw_dir);
|
||||
@ -2318,7 +2406,7 @@ do_child(const char *command, struct passwd * pw, const char *term,
|
||||
}
|
||||
|
||||
snprintf(buf, sizeof buf, "%.50s %d %d",
|
||||
get_remote_ipaddr(), get_remote_port(), options.port);
|
||||
get_remote_ipaddr(), get_remote_port(), get_local_port());
|
||||
child_set_env(&env, &envsize, "SSH_CLIENT", buf);
|
||||
|
||||
if (ttyname)
|
||||
@ -2385,7 +2473,6 @@ do_child(const char *command, struct passwd * pw, const char *term,
|
||||
* descriptors left by system functions. They will be closed later.
|
||||
*/
|
||||
endpwent();
|
||||
endhostent();
|
||||
|
||||
/*
|
||||
* Close any extra open file descriptors so that we don\'t have them
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
Port 22
|
||||
ListenAddress 0.0.0.0
|
||||
#ListenAddress ::
|
||||
HostKey @sysconfdir@/ssh_host_key
|
||||
ServerKeyBits 768
|
||||
LoginGraceTime 600
|
||||
|
Loading…
Reference in New Issue
Block a user