several tcp apps IPv6 update
-inetd -rshd -rlogind -telnetd -rsh -rlogin Reviewed by: freebsd-arch, cvs-committers Obtained from: KAME project
This commit is contained in:
parent
02c2ad9db1
commit
7c069c8355
@ -165,6 +165,8 @@ int profil __P((char *, size_t, vm_offset_t, int));
|
||||
ssize_t pwrite __P((int, const void *, size_t, off_t));
|
||||
int rcmd __P((char **, int, const char *,
|
||||
const char *, const char *, int *));
|
||||
int rcmd_af __P((char **, int, const char *,
|
||||
const char *, const char *, int *, int));
|
||||
char *re_comp __P((const char *));
|
||||
int re_exec __P((const char *));
|
||||
int readlink __P((const char *, char *, int));
|
||||
|
@ -58,7 +58,9 @@ MLINKS+=if_indextoname.3 if_nametoindex.3 if_indextoname.3 if_nameindex.3 \
|
||||
if_indextoname.3 if_freenameindex.3
|
||||
MLINKS+=linkaddr.3 link_addr.3 linkaddr.3 link_ntoa.3
|
||||
#MLINKS+=ns.3 ns_addr.3 ns.3 ns_ntoa.3
|
||||
MLINKS+=rcmd.3 iruserok.3 rcmd.3 rresvport.3 rcmd.3 ruserok.3
|
||||
MLINKS+=rcmd.3 iruserok.3 rcmd.3 rresvport.3 rcmd.3 ruserok.3 \
|
||||
rcmd.3 iruserok_af.3 rcmd.3 rresvport_af.3 rcmd.3 ruserok_af.3 \
|
||||
rcmd.3 rcmd_af.3
|
||||
MLINKS+=resolver.3 dn_comp.3 resolver.3 dn_expand.3 resolver.3 res_init.3 \
|
||||
resolver.3 res_mkquery.3 resolver.3 res_query.3 \
|
||||
resolver.3 res_search.3 resolver.3 res_send.3
|
||||
|
@ -40,6 +40,7 @@
|
||||
.Nm rresvport ,
|
||||
.Nm iruserok ,
|
||||
.Nm ruserok ,
|
||||
.Nm rcmd_af ,
|
||||
.Nm rresvport_af ,
|
||||
.Nm iruserok_af ,
|
||||
.Nm ruserok_af
|
||||
@ -55,7 +56,9 @@
|
||||
.Ft int
|
||||
.Fn ruserok "const char *rhost" "int superuser" "const char *ruser" "const char *luser"
|
||||
.Ft int
|
||||
.Fn rresvport_af "int *port" "int family"
|
||||
.Fn rcmd_af "char **ahost" "int inport" "const char *locuser" "const char *remuser" "const char *cmd" "int *fd2p" "int af"
|
||||
.Ft int
|
||||
.Fn rresvport_af "int *port" "int af"
|
||||
.Ft int
|
||||
.Fn iruserok_af "void *raddr" "int superuser" "const char *ruser" "const char *luser" "int af"
|
||||
.Ft int
|
||||
@ -184,17 +187,26 @@ It requires trusting the local DNS at most, while the
|
||||
function requires trusting the entire DNS, which can be spoofed.
|
||||
.Pp
|
||||
Functions with ``_af'' suffix, i.e.
|
||||
.Fn rcmd_af ,
|
||||
.Fn rresvport_af ,
|
||||
.Fn iruserok_af and
|
||||
.Fn iruserok_af
|
||||
and
|
||||
.Fn ruserok_af ,
|
||||
works just as same as functions without ``_af'', and is capable of
|
||||
handling both IPv6 port and IPv4 port.
|
||||
Functions without
|
||||
.Dq Li _af
|
||||
works for IPv4 only.
|
||||
To switch address family,
|
||||
.Fa af
|
||||
argument must be filled with
|
||||
.Dv AF_INET
|
||||
.Dv AF_INET ,
|
||||
or
|
||||
.Dv AF_INET6 .
|
||||
For
|
||||
.Fn rcmd_af ,
|
||||
.Dv PF_UNSPEC
|
||||
is also allowed.
|
||||
.Sh DIAGNOSTICS
|
||||
The
|
||||
.Fn rcmd
|
||||
@ -230,6 +242,9 @@ functions appeared in
|
||||
.Fn rresvport_af
|
||||
appeared in RFC2292, and implemented by WIDE project
|
||||
for Hydrangea IPv6 protocol stack kit.
|
||||
.Fn rcmd_af
|
||||
appeared in draft-ietf-ipngwg-rfc2292bis-01.txt,
|
||||
and implemented by WIDE/KAME IPv6 protocol stack kit.
|
||||
.Fn iruserok_af
|
||||
and
|
||||
.Fn rusreok_af
|
||||
|
@ -79,6 +79,17 @@ rcmd(ahost, rport, locuser, remuser, cmd, fd2p)
|
||||
u_short rport;
|
||||
const char *locuser, *remuser, *cmd;
|
||||
int *fd2p;
|
||||
{
|
||||
return rcmd_af(ahost, rport, locuser, remuser, cmd, fd2p, AF_INET);
|
||||
}
|
||||
|
||||
int
|
||||
rcmd_af(ahost, rport, locuser, remuser, cmd, fd2p, af)
|
||||
char **ahost;
|
||||
u_short rport;
|
||||
const char *locuser, *remuser, *cmd;
|
||||
int *fd2p;
|
||||
int af;
|
||||
{
|
||||
struct addrinfo hints, *res, *ai;
|
||||
struct sockaddr_storage from;
|
||||
@ -94,7 +105,7 @@ rcmd(ahost, rport, locuser, remuser, cmd, fd2p)
|
||||
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_flags = AI_CANONNAME;
|
||||
hints.ai_family = AF_UNSPEC;
|
||||
hints.ai_family = af;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
hints.ai_protocol = 0;
|
||||
(void)snprintf(num, sizeof(num), "%d", ntohs(rport));
|
||||
|
@ -5,6 +5,7 @@ LIB= util
|
||||
SHLIB_MAJOR= 2
|
||||
SHLIB_MINOR= 2
|
||||
CFLAGS+=-Wall -DLIBC_SCCS -I${.CURDIR} -I${.CURDIR}/../../sys
|
||||
CFLAGS+=-DINET6
|
||||
SRCS= login.c login_tty.c logout.c logwtmp.c pty.c setproctitle.c \
|
||||
login_cap.c login_class.c login_auth.c login_times.c login_ok.c \
|
||||
_secure_path.c uucplock.c property.c auth.c realhostname.c fparseln.c \
|
||||
@ -13,7 +14,7 @@ INCS= libutil.h login_cap.h
|
||||
MAN3+= login.3 login_auth.3 login_tty.3 logout.3 logwtmp.3 pty.3 \
|
||||
setproctitle.3 login_cap.3 login_class.3 login_times.3 login_ok.3 \
|
||||
_secure_path.3 uucplock.3 property.3 auth.3 realhostname.3 \
|
||||
trimdomain.3 fparseln.3
|
||||
realhostname_sa.3 trimdomain.3 fparseln.3
|
||||
MAN5+= login.conf.5 auth.conf.5
|
||||
MLINKS+= property.3 properties_read.3 property.3 properties_free.3
|
||||
MLINKS+= property.3 property_find.3
|
||||
|
@ -60,6 +60,9 @@ void properties_free __P((properties list));
|
||||
char *property_find __P((properties list, const char *name));
|
||||
char *auth_getval __P((const char *name));
|
||||
int realhostname __P((char *host, size_t hsize, const struct in_addr *ip));
|
||||
struct sockaddr;
|
||||
int realhostname_sa __P((char *host, size_t hsize, struct sockaddr *addr,
|
||||
int addrlen));
|
||||
#ifdef _STDIO_H_ /* avoid adding new includes */
|
||||
char *fparseln __P((FILE *, size_t *, size_t *, const char[3], int));
|
||||
#endif
|
||||
|
@ -103,4 +103,5 @@ now contains the numeric value of
|
||||
.Sh SEE ALSO
|
||||
.Xr gethostbyaddr 3 ,
|
||||
.Xr gethostbyname 3 ,
|
||||
.Xr inet_ntoa 3
|
||||
.Xr inet_ntoa 3 ,
|
||||
.Xr realhostname_sa 3
|
||||
|
@ -38,6 +38,17 @@
|
||||
|
||||
#include "libutil.h"
|
||||
|
||||
/* wrapper for KAME-special getnameinfo() */
|
||||
#ifndef NI_WITHSCOPEID
|
||||
#define NI_WITHSCOPEID 0
|
||||
#endif
|
||||
|
||||
struct sockinet {
|
||||
u_char si_len;
|
||||
u_char si_family;
|
||||
u_short si_port;
|
||||
};
|
||||
|
||||
int
|
||||
realhostname(char *host, size_t hsize, const struct in_addr *ip)
|
||||
{
|
||||
@ -71,3 +82,87 @@ realhostname(char *host, size_t hsize, const struct in_addr *ip)
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int
|
||||
realhostname_sa(char *host, size_t hsize, struct sockaddr *addr, int addrlen)
|
||||
{
|
||||
int result, error;
|
||||
|
||||
result = HOSTNAME_INVALIDADDR;
|
||||
|
||||
error = getnameinfo(addr, addrlen, host, hsize, NULL, 0, 0);
|
||||
if (error == NULL) {
|
||||
struct addrinfo hints, *res, *ores;
|
||||
struct sockaddr *sa;
|
||||
|
||||
memset(&hints, 0, sizeof(struct addrinfo));
|
||||
hints.ai_family = AF_UNSPEC;
|
||||
hints.ai_flags = AI_CANONNAME;
|
||||
|
||||
error = getaddrinfo(host, NULL, &hints, &res);
|
||||
if (error) {
|
||||
result = HOSTNAME_INVALIDNAME;
|
||||
goto numeric;
|
||||
} else for (ores = res; ; res = res->ai_next) {
|
||||
if (res == NULL) {
|
||||
freeaddrinfo(ores);
|
||||
result = HOSTNAME_INCORRECTNAME;
|
||||
goto numeric;
|
||||
}
|
||||
sa = res->ai_addr;
|
||||
if (sa == NULL) {
|
||||
freeaddrinfo(ores);
|
||||
result = HOSTNAME_INCORRECTNAME;
|
||||
goto numeric;
|
||||
}
|
||||
if (sa->sa_len == addrlen &&
|
||||
sa->sa_family == addr->sa_family) {
|
||||
u_int16_t port;
|
||||
|
||||
port = ((struct sockinet *)addr)->si_port;
|
||||
((struct sockinet *)addr)->si_port = 0;
|
||||
if (!memcmp(sa, addr, sa->sa_len)) {
|
||||
strncpy(host, res->ai_canonname,
|
||||
hsize);
|
||||
result = HOSTNAME_FOUND;
|
||||
((struct sockinet *)addr)->si_port =
|
||||
port;
|
||||
break;
|
||||
}
|
||||
((struct sockinet *)addr)->si_port = port;
|
||||
}
|
||||
#ifdef INET6
|
||||
/*
|
||||
* XXX IPv4 mapped IPv6 addr consideraton,
|
||||
* specified in rfc2373.
|
||||
*/
|
||||
if (sa->sa_family == AF_INET &&
|
||||
addr->sa_family == AF_INET6) {
|
||||
struct in_addr *in;
|
||||
struct in6_addr *in6;
|
||||
|
||||
in = &((struct sockaddr_in *)sa)->sin_addr;
|
||||
in6 = &((struct sockaddr_in6 *)addr)->sin6_addr;
|
||||
if (IN6_IS_ADDR_V4MAPPED(in6) &&
|
||||
!memcmp(&in6->s6_addr[12], in,
|
||||
sizeof(*in))) {
|
||||
strncpy(host, res->ai_canonname,
|
||||
hsize);
|
||||
result = HOSTNAME_FOUND;
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
freeaddrinfo(ores);
|
||||
} else {
|
||||
numeric:
|
||||
getnameinfo(addr, addrlen, host, hsize, NULL, 0,
|
||||
NI_NUMERICHOST|NI_WITHSCOPEID);
|
||||
/* XXX: do 'error' check */
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
135
lib/libutil/realhostname_sa.3
Normal file
135
lib/libutil/realhostname_sa.3
Normal file
@ -0,0 +1,135 @@
|
||||
.\" Copyright (C) 1995, 1996, 1997, 1998, 1999, and 2000 WIDE Project.
|
||||
.\" 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. Neither the name of the project 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 PROJECT 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 PROJECT 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.
|
||||
.\"
|
||||
.\" Copyright (c) 1999 Brian Somers <brian@Awfulhak.org>
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd January 11, 2000
|
||||
.Os
|
||||
.Dt REALHOSTNAME_SA 3
|
||||
.Sh NAME
|
||||
.Nm realhostname_sa
|
||||
.Nd "convert an struct sockaddr to the real host name"
|
||||
.Sh SYNOPSIS
|
||||
.Fd #include <sys/types.h>
|
||||
.Fd #include <netinet/in.h>
|
||||
.Fd #include <libutil.h>
|
||||
.Ft int
|
||||
.Fn realhostname_sa "char *host" "size_t hsize" "struct sockaddr *addr" \
|
||||
"int addrlen"
|
||||
.Pp
|
||||
Link with
|
||||
.Va -lutil
|
||||
on the
|
||||
.Xr cc 1
|
||||
command line.
|
||||
.Sh DESCRIPTION
|
||||
The function
|
||||
.Fn realhostname_sa
|
||||
converts
|
||||
.Ar addr
|
||||
to the corresponding host name. This is done by resolving
|
||||
.Ar addr
|
||||
to a host name and then ensuring that the host name resolves
|
||||
back to
|
||||
.Ar addr .
|
||||
.Pp
|
||||
.Ar host
|
||||
must point to a buffer of at least
|
||||
.Ar hsize
|
||||
bytes, and will always be written to by this function.
|
||||
.Pp
|
||||
If the name resolution doesn't work both ways or if the host name is longer
|
||||
than
|
||||
.Ar hsize
|
||||
bytes,
|
||||
.Xr getnameinfo 3
|
||||
with NI_NUMERICHOST specified, is used to convert
|
||||
.Ar addr
|
||||
to an ASCII form.
|
||||
.Pp
|
||||
If the string written to
|
||||
.Ar host
|
||||
is
|
||||
.Ar hsize
|
||||
bytes long,
|
||||
.Ar host
|
||||
will not be NUL terminated.
|
||||
.Sh RETURN VALUES
|
||||
.Fn realhostname_sa
|
||||
will return one of the following constants which are defined in
|
||||
.Pa libutil.h :
|
||||
.Pp
|
||||
.Bl -tag -width XXX -offset XXX
|
||||
.It Li HOSTNAME_FOUND
|
||||
A valid host name was found.
|
||||
.It Li HOSTNAME_INCORRECTNAME
|
||||
A host name was found, but it did not resolve back to the passed
|
||||
.Ar ip .
|
||||
.Ar host
|
||||
now contains the numeric value of
|
||||
.Ar ip .
|
||||
.It Li HOSTNAME_INVALIDADDR
|
||||
.Ar ip
|
||||
could not be resolved.
|
||||
.Ar host
|
||||
now contains the numeric value of
|
||||
.Ar ip .
|
||||
.It Li HOSTNAME_INVALIDNAME
|
||||
A host name was found, but it could not be resolved back to any ip number.
|
||||
.Ar host
|
||||
now contains the numeric value of
|
||||
.Ar ip .
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr getaddrinfo 3 ,
|
||||
.Xr getnameinfo 3 ,
|
||||
.Xr realhostname 3
|
||||
|
@ -6,7 +6,7 @@ SRCS= rlogind.c
|
||||
MAN8= rlogind.8
|
||||
DPADD= ${LIBUTIL}
|
||||
LDADD= -lutil
|
||||
CFLAGS+= -Wall
|
||||
CFLAGS+= -Wall -DINET6
|
||||
|
||||
.if defined(NOPAM)
|
||||
CFLAGS+= -DNO_PAM
|
||||
|
@ -204,3 +204,5 @@ The
|
||||
.Nm
|
||||
command appeared in
|
||||
.Bx 4.2 .
|
||||
.Pp
|
||||
IPv6 support was added by WIDE/KAME project.
|
@ -91,6 +91,11 @@ static const char rcsid[] =
|
||||
|
||||
#define ARGSTR "Dalnx"
|
||||
|
||||
/* wrapper for KAME-special getnameinfo() */
|
||||
#ifndef NI_WITHSCOPEID
|
||||
#define NI_WITHSCOPEID 0
|
||||
#endif
|
||||
|
||||
char *env[2];
|
||||
#define NMAX 30
|
||||
char lusername[NMAX+1], rusername[NMAX+1];
|
||||
@ -102,12 +107,25 @@ int no_delay;
|
||||
|
||||
struct passwd *pwd;
|
||||
|
||||
void doit __P((int, struct sockaddr_in *));
|
||||
union sockunion {
|
||||
struct sockinet {
|
||||
u_char si_len;
|
||||
u_char si_family;
|
||||
u_short si_port;
|
||||
} su_si;
|
||||
struct sockaddr_in su_sin;
|
||||
struct sockaddr_in6 su_sin6;
|
||||
};
|
||||
#define su_len su_si.si_len
|
||||
#define su_family su_si.si_family
|
||||
#define su_port su_si.si_port
|
||||
|
||||
void doit __P((int, union sockunion *));
|
||||
int control __P((int, char *, int));
|
||||
void protocol __P((int, int));
|
||||
void cleanup __P((int));
|
||||
void fatal __P((int, char *, int));
|
||||
int do_rlogin __P((struct sockaddr_in *));
|
||||
int do_rlogin __P((union sockunion *));
|
||||
void getstr __P((char *, int, char *));
|
||||
void setup_term __P((int));
|
||||
int do_krb_login __P((struct sockaddr_in *));
|
||||
@ -123,7 +141,7 @@ main(argc, argv)
|
||||
char *argv[];
|
||||
{
|
||||
extern int __check_rhosts_file;
|
||||
struct sockaddr_in from;
|
||||
union sockunion from;
|
||||
int ch, fromlen, on;
|
||||
|
||||
openlog("rlogind", LOG_PID | LOG_CONS, LOG_AUTH);
|
||||
@ -168,9 +186,12 @@ main(argc, argv)
|
||||
if (no_delay &&
|
||||
setsockopt(0, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on)) < 0)
|
||||
syslog(LOG_WARNING, "setsockopt (TCP_NODELAY): %m");
|
||||
if (from.su_family == AF_INET)
|
||||
{
|
||||
on = IPTOS_LOWDELAY;
|
||||
if (setsockopt(0, IPPROTO_IP, IP_TOS, (char *)&on, sizeof(int)) < 0)
|
||||
syslog(LOG_WARNING, "setsockopt (IP_TOS): %m");
|
||||
}
|
||||
|
||||
doit(0, &from);
|
||||
return 0;
|
||||
@ -187,11 +208,12 @@ struct winsize win = { 0, 0, 0, 0 };
|
||||
void
|
||||
doit(f, fromp)
|
||||
int f;
|
||||
struct sockaddr_in *fromp;
|
||||
union sockunion *fromp;
|
||||
{
|
||||
int master, pid, on = 1;
|
||||
int authenticated = 0;
|
||||
char hostname[MAXHOSTNAMELEN];
|
||||
char hostname[2 * MAXHOSTNAMELEN + 1];
|
||||
char nameinfo[2 * INET6_ADDRSTRLEN + 1];
|
||||
char c;
|
||||
|
||||
alarm(60);
|
||||
@ -201,20 +223,33 @@ doit(f, fromp)
|
||||
exit(1);
|
||||
|
||||
alarm(0);
|
||||
fromp->sin_port = ntohs((u_short)fromp->sin_port);
|
||||
realhostname(hostname, sizeof(hostname) - 1, &fromp->sin_addr);
|
||||
|
||||
realhostname_sa(hostname, sizeof(hostname) - 1,
|
||||
(struct sockaddr *)fromp, fromp->su_len);
|
||||
/* error check ? */
|
||||
fromp->su_port = ntohs((u_short)fromp->su_port);
|
||||
hostname[sizeof(hostname) - 1] = '\0';
|
||||
|
||||
{
|
||||
if (fromp->sin_family != AF_INET ||
|
||||
fromp->sin_port >= IPPORT_RESERVED ||
|
||||
fromp->sin_port < IPPORT_RESERVED/2) {
|
||||
if ((fromp->su_family != AF_INET &&
|
||||
#ifdef INET6
|
||||
fromp->su_family != AF_INET6
|
||||
#endif
|
||||
) ||
|
||||
fromp->su_port >= IPPORT_RESERVED ||
|
||||
fromp->su_port < IPPORT_RESERVED/2) {
|
||||
getnameinfo((struct sockaddr *)fromp,
|
||||
fromp->su_len,
|
||||
nameinfo, sizeof(nameinfo), NULL, 0,
|
||||
NI_NUMERICHOST|NI_WITHSCOPEID);
|
||||
/* error check ? */
|
||||
syslog(LOG_NOTICE, "Connection from %s on illegal port",
|
||||
inet_ntoa(fromp->sin_addr));
|
||||
nameinfo);
|
||||
fatal(f, "Permission denied", 0);
|
||||
}
|
||||
#ifdef IP_OPTIONS
|
||||
{
|
||||
if (fromp->su_family == AF_INET)
|
||||
{
|
||||
u_char optbuf[BUFSIZ/3];
|
||||
int optsize = sizeof(optbuf), ipproto, i;
|
||||
struct protoent *ip;
|
||||
@ -230,7 +265,7 @@ doit(f, fromp)
|
||||
if (c == IPOPT_LSRR || c == IPOPT_SSRR) {
|
||||
syslog(LOG_NOTICE,
|
||||
"Connection refused from %s with IP option %s",
|
||||
inet_ntoa(fromp->sin_addr),
|
||||
inet_ntoa(fromp->su_sin.sin_addr),
|
||||
c == IPOPT_LSRR ? "LSRR" : "SSRR");
|
||||
exit(1);
|
||||
}
|
||||
@ -239,7 +274,7 @@ doit(f, fromp)
|
||||
i += (c == IPOPT_NOP) ? 1 : optbuf[i+1];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (do_rlogin(fromp) == 0)
|
||||
authenticated++;
|
||||
@ -533,9 +568,11 @@ fatal(f, msg, syserr)
|
||||
|
||||
int
|
||||
do_rlogin(dest)
|
||||
struct sockaddr_in *dest;
|
||||
union sockunion *dest;
|
||||
{
|
||||
int retval;
|
||||
int af;
|
||||
char *addr;
|
||||
|
||||
getstr(rusername, sizeof(rusername), "remuser too long");
|
||||
getstr(lusername, sizeof(lusername), "locuser too long");
|
||||
@ -559,8 +596,22 @@ do_rlogin(dest)
|
||||
if (pwd == NULL)
|
||||
return (-1);
|
||||
/* XXX why don't we syslog() failure? */
|
||||
return (iruserok(dest->sin_addr.s_addr, pwd->pw_uid == 0,
|
||||
rusername, lusername));
|
||||
|
||||
af = dest->su_family;
|
||||
switch (af) {
|
||||
case AF_INET:
|
||||
addr = (char *)&dest->su_sin.sin_addr;
|
||||
break;
|
||||
#ifdef INET6
|
||||
case AF_INET6:
|
||||
addr = (char *)&dest->su_sin6.sin6_addr;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
return -1; /*EAFNOSUPPORT*/
|
||||
}
|
||||
|
||||
return (iruserok_af(addr, pwd->pw_uid == 0, rusername, lusername, af));
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -19,6 +19,9 @@ CFLAGS+=-DLOGIN_CAP -Wall
|
||||
DPADD+= ${LIBUTIL}
|
||||
LDADD+= -lutil
|
||||
|
||||
# IPv6 support
|
||||
CFLAGS+= -DINET6
|
||||
|
||||
.include <bsd.prog.mk>
|
||||
|
||||
.PATH: ${.CURDIR}/../rlogind
|
||||
|
@ -250,3 +250,5 @@ A facility to allow all data exchanges to be encrypted should be
|
||||
present.
|
||||
.Pp
|
||||
A more extensible protocol (such as Telnet) should be used.
|
||||
.Sh HISTORY
|
||||
IPv6 support was added by WIDE/KAME project.
|
||||
|
@ -80,6 +80,11 @@ static const char rcsid[] =
|
||||
#include <login_cap.h>
|
||||
#endif
|
||||
|
||||
/* wrapper for KAME-special getnameinfo() */
|
||||
#ifndef NI_WITHSCOPEID
|
||||
#define NI_WITHSCOPEID 0
|
||||
#endif
|
||||
|
||||
int keepalive = 1;
|
||||
int log_success; /* If TRUE, log all successful accesses */
|
||||
int sent_null;
|
||||
@ -88,7 +93,20 @@ int no_delay;
|
||||
int doencrypt = 0;
|
||||
#endif
|
||||
|
||||
void doit __P((struct sockaddr_in *));
|
||||
union sockunion {
|
||||
struct sockinet {
|
||||
u_char si_len;
|
||||
u_char si_family;
|
||||
u_short si_port;
|
||||
} su_si;
|
||||
struct sockaddr_in su_sin;
|
||||
struct sockaddr_in6 su_sin6;
|
||||
};
|
||||
#define su_len su_si.si_len
|
||||
#define su_family su_si.si_family
|
||||
#define su_port su_si.si_port
|
||||
|
||||
void doit __P((union sockunion *));
|
||||
void error __P((const char *, ...));
|
||||
void getstr __P((char *, int, char *));
|
||||
int local_domain __P((char *));
|
||||
@ -109,7 +127,7 @@ main(argc, argv)
|
||||
extern int __check_rhosts_file;
|
||||
struct linger linger;
|
||||
int ch, on = 1, fromlen;
|
||||
struct sockaddr_in from;
|
||||
struct sockaddr_storage from;
|
||||
|
||||
openlog("rshd", LOG_PID | LOG_ODELAY, LOG_DAEMON);
|
||||
|
||||
@ -169,7 +187,7 @@ main(argc, argv)
|
||||
if (no_delay &&
|
||||
setsockopt(0, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on)) < 0)
|
||||
syslog(LOG_WARNING, "setsockopt (TCP_NODELAY): %m");
|
||||
doit(&from);
|
||||
doit((union sockunion *)&from);
|
||||
/* NOTREACHED */
|
||||
return(0);
|
||||
}
|
||||
@ -184,7 +202,7 @@ char **environ;
|
||||
|
||||
void
|
||||
doit(fromp)
|
||||
struct sockaddr_in *fromp;
|
||||
union sockunion *fromp;
|
||||
{
|
||||
extern char *__rcmd_errstr; /* syslog hook from libc/net/rcmd.c. */
|
||||
struct passwd *pwd;
|
||||
@ -195,7 +213,9 @@ doit(fromp)
|
||||
char *errorstr;
|
||||
char *cp, sig, buf[BUFSIZ];
|
||||
char cmdbuf[NCARGS+1], locuser[16], remuser[16];
|
||||
char fromhost[MAXHOSTNAMELEN];
|
||||
char fromhost[2 * MAXHOSTNAMELEN + 1];
|
||||
char numericname[INET6_ADDRSTRLEN];
|
||||
int af = fromp->su_family, err;
|
||||
int retval;
|
||||
#ifdef CRYPT
|
||||
int rc;
|
||||
@ -216,14 +236,21 @@ doit(fromp)
|
||||
}
|
||||
}
|
||||
#endif
|
||||
fromp->sin_port = ntohs((u_short)fromp->sin_port);
|
||||
if (fromp->sin_family != AF_INET) {
|
||||
syslog(LOG_ERR, "malformed \"from\" address (af %d)",
|
||||
fromp->sin_family);
|
||||
fromp->su_port = ntohs((u_short)fromp->su_port);
|
||||
if (af != AF_INET
|
||||
#ifdef INET6
|
||||
&& af != AF_INET6
|
||||
#endif
|
||||
) {
|
||||
syslog(LOG_ERR, "malformed \"from\" address (af %d)\n", af);
|
||||
exit(1);
|
||||
}
|
||||
err = getnameinfo((struct sockaddr *)fromp, fromp->su_len, numericname,
|
||||
sizeof(numericname), NULL, 0,
|
||||
NI_NUMERICHOST|NI_WITHSCOPEID);
|
||||
/* XXX: do 'err' check */
|
||||
#ifdef IP_OPTIONS
|
||||
{
|
||||
if (af == AF_INET) {
|
||||
u_char optbuf[BUFSIZ/3];
|
||||
int optsize = sizeof(optbuf), ipproto, i;
|
||||
struct protoent *ip;
|
||||
@ -239,7 +266,7 @@ doit(fromp)
|
||||
if (c == IPOPT_LSRR || c == IPOPT_SSRR) {
|
||||
syslog(LOG_NOTICE,
|
||||
"connection refused from %s with IP option %s",
|
||||
inet_ntoa(fromp->sin_addr),
|
||||
numericname,
|
||||
c == IPOPT_LSRR ? "LSRR" : "SSRR");
|
||||
exit(1);
|
||||
}
|
||||
@ -251,12 +278,12 @@ doit(fromp)
|
||||
}
|
||||
#endif
|
||||
|
||||
if (fromp->sin_port >= IPPORT_RESERVED ||
|
||||
fromp->sin_port < IPPORT_RESERVED/2) {
|
||||
if (fromp->su_port >= IPPORT_RESERVED ||
|
||||
fromp->su_port < IPPORT_RESERVED/2) {
|
||||
syslog(LOG_NOTICE|LOG_AUTH,
|
||||
"connection from %s on illegal port %u",
|
||||
inet_ntoa(fromp->sin_addr),
|
||||
fromp->sin_port);
|
||||
numericname,
|
||||
fromp->su_port);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@ -279,7 +306,7 @@ doit(fromp)
|
||||
(void) alarm(0);
|
||||
if (port != 0) {
|
||||
int lport = IPPORT_RESERVED - 1;
|
||||
s = rresvport(&lport);
|
||||
s = rresvport_af(&lport, af);
|
||||
if (s < 0) {
|
||||
syslog(LOG_ERR, "can't get stderr port: %m");
|
||||
exit(1);
|
||||
@ -288,11 +315,11 @@ doit(fromp)
|
||||
port < IPPORT_RESERVED/2) {
|
||||
syslog(LOG_NOTICE|LOG_AUTH,
|
||||
"2nd socket from %s on unreserved port %u",
|
||||
inet_ntoa(fromp->sin_addr),
|
||||
numericname,
|
||||
port);
|
||||
exit(1);
|
||||
}
|
||||
fromp->sin_port = htons(port);
|
||||
fromp->su_port = htons(port);
|
||||
if (connect(s, (struct sockaddr *)fromp, sizeof (*fromp)) < 0) {
|
||||
syslog(LOG_INFO, "connect second port %d: %m", port);
|
||||
exit(1);
|
||||
@ -300,11 +327,13 @@ doit(fromp)
|
||||
}
|
||||
|
||||
errorstr = NULL;
|
||||
realhostname(fromhost, sizeof(fromhost) - 1, &fromp->sin_addr);
|
||||
realhostname_sa(fromhost, sizeof(fromhost) - 1,
|
||||
(struct sockaddr *)fromp,
|
||||
fromp->su_len);
|
||||
fromhost[sizeof(fromhost) - 1] = '\0';
|
||||
|
||||
#ifdef CRYPT
|
||||
if (doencrypt) {
|
||||
if (doencrypt && af == AF_INET) {
|
||||
struct sockaddr_in local_addr;
|
||||
rc = sizeof(local_addr);
|
||||
if (getsockname(0, (struct sockaddr *)&local_addr,
|
||||
@ -379,8 +408,14 @@ doit(fromp)
|
||||
if (errorstr ||
|
||||
(pwd->pw_expire && time(NULL) >= pwd->pw_expire) ||
|
||||
(pwd->pw_passwd != 0 && *pwd->pw_passwd != '\0' &&
|
||||
iruserok(fromp->sin_addr.s_addr, pwd->pw_uid == 0,
|
||||
remuser, locuser) < 0)) {
|
||||
iruserok_af(
|
||||
#ifdef INET6
|
||||
(af == AF_INET6)
|
||||
? (void *)&fromp->su_sin6.sin6_addr :
|
||||
#endif
|
||||
(void *)&fromp->su_sin.sin_addr,
|
||||
pwd->pw_uid == 0,
|
||||
remuser, locuser, af) < 0)) {
|
||||
if (__rcmd_errstr)
|
||||
syslog(LOG_INFO|LOG_AUTH,
|
||||
"%s@%s as %s: permission denied (%s). cmd='%.80s'",
|
||||
@ -402,10 +437,10 @@ doit(fromp)
|
||||
exit(1);
|
||||
}
|
||||
#ifdef LOGIN_CAP
|
||||
if (lc != NULL) {
|
||||
if (lc != NULL && fromp->su_family == AF_INET) { /*XXX*/
|
||||
char remote_ip[MAXHOSTNAMELEN];
|
||||
|
||||
strncpy(remote_ip, inet_ntoa(fromp->sin_addr),
|
||||
strncpy(remote_ip, numericname,
|
||||
sizeof(remote_ip) - 1);
|
||||
remote_ip[sizeof(remote_ip) - 1] = 0;
|
||||
if (!auth_hostok(lc, fromhost, remote_ip)) {
|
||||
|
@ -6,6 +6,7 @@ CFLAGS+=-DLINEMODE -DUSE_TERMIO -DDIAGNOSTICS
|
||||
#CFLAGS+=-DKLUDGELINEMODE
|
||||
CFLAGS+=-DOLD_ENVIRON -DENV_HACK
|
||||
CFLAGS+=-I${.CURDIR}/../../lib
|
||||
CFLAGS+=-DINET6
|
||||
SRCS= global.c slc.c state.c sys_term.c telnetd.c \
|
||||
termstat.c utility.c
|
||||
DPADD= ${LIBUTIL} ${LIBTERMCAP} ${LIBTELNET}
|
||||
|
@ -623,3 +623,5 @@ never sends
|
||||
.Tn TELNET
|
||||
.Dv IAC GA
|
||||
(go ahead) commands.
|
||||
.Sh HISTORY
|
||||
IPv6 support was added by WIDE/KAME project.
|
@ -71,6 +71,12 @@ static const char rcsid[] =
|
||||
#include <sys/secparm.h>
|
||||
#include <sys/usrv.h>
|
||||
# endif /* SO_SEC_MULTI */
|
||||
|
||||
/* wrapper for KAME-special getnameinfo() */
|
||||
#ifndef NI_WITHSCOPEID
|
||||
#define NI_WITHSCOPEID 0
|
||||
#endif
|
||||
|
||||
int secflag;
|
||||
char tty_dev[16];
|
||||
struct secdev dv;
|
||||
@ -137,7 +143,7 @@ int debug = 0;
|
||||
int keepalive = 1;
|
||||
char *altlogin;
|
||||
|
||||
void doit __P((struct sockaddr_in *));
|
||||
void doit __P((struct sockaddr *));
|
||||
int terminaltypeok __P((char *));
|
||||
void startslave __P((char *, int, char *));
|
||||
extern void usage P((void));
|
||||
@ -149,6 +155,7 @@ extern void usage P((void));
|
||||
*/
|
||||
char valid_opts[] = {
|
||||
'd', ':', 'h', 'k', 'n', 'p', ':', 'S', ':', 'u', ':', 'U',
|
||||
'4', '6',
|
||||
#ifdef AUTHENTICATION
|
||||
'a', ':', 'X', ':',
|
||||
#endif
|
||||
@ -173,11 +180,13 @@ char valid_opts[] = {
|
||||
'\0'
|
||||
};
|
||||
|
||||
int
|
||||
int family = AF_INET;
|
||||
|
||||
int
|
||||
main(argc, argv)
|
||||
char *argv[];
|
||||
{
|
||||
struct sockaddr_in from;
|
||||
struct sockaddr_storage from;
|
||||
int on = 1, fromlen;
|
||||
register int ch;
|
||||
#if defined(IPPROTO_IP) && defined(IP_TOS)
|
||||
@ -381,6 +390,16 @@ main(argc, argv)
|
||||
break;
|
||||
#endif /* AUTHENTICATION */
|
||||
|
||||
case '4':
|
||||
family = AF_INET;
|
||||
break;
|
||||
|
||||
#ifdef INET6
|
||||
case '6':
|
||||
family = AF_INET6;
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
warnx("%c: unknown option", ch);
|
||||
/* FALLTHROUGH */
|
||||
@ -394,43 +413,41 @@ main(argc, argv)
|
||||
argv += optind;
|
||||
|
||||
if (debug) {
|
||||
int s, ns, foo;
|
||||
struct servent *sp;
|
||||
static struct sockaddr_in sin = { AF_INET };
|
||||
int s, ns, foo, error;
|
||||
char *service = "telnet";
|
||||
struct addrinfo hints, *res;
|
||||
|
||||
if (argc > 1) {
|
||||
usage();
|
||||
/* NOT REACHED */
|
||||
} else if (argc == 1) {
|
||||
if ((sp = getservbyname(*argv, "tcp"))) {
|
||||
sin.sin_port = sp->s_port;
|
||||
} else {
|
||||
sin.sin_port = atoi(*argv);
|
||||
if ((int)sin.sin_port <= 0) {
|
||||
warnx("%s: bad port #", *argv);
|
||||
usage();
|
||||
/* NOT REACHED */
|
||||
}
|
||||
sin.sin_port = htons((u_short)sin.sin_port);
|
||||
}
|
||||
} else {
|
||||
sp = getservbyname("telnet", "tcp");
|
||||
if (sp == 0)
|
||||
errx(1, "tcp/telnet: unknown service");
|
||||
sin.sin_port = sp->s_port;
|
||||
} else if (argc == 1)
|
||||
service = *argv;
|
||||
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_flags = AI_PASSIVE;
|
||||
hints.ai_family = family;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
hints.ai_protocol = 0;
|
||||
error = getaddrinfo(NULL, service, &hints, &res);
|
||||
|
||||
if (error) {
|
||||
errx(1, "tcp/%s: %s\n", service, gai_strerror(error));
|
||||
if (error == EAI_SYSTEM)
|
||||
errx(1, "tcp/%s: %s\n", service, strerror(errno));
|
||||
usage();
|
||||
}
|
||||
|
||||
s = socket(AF_INET, SOCK_STREAM, 0);
|
||||
s = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
|
||||
if (s < 0)
|
||||
err(1, "socket");
|
||||
(void) setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
|
||||
(char *)&on, sizeof(on));
|
||||
if (bind(s, (struct sockaddr *)&sin, sizeof sin) < 0)
|
||||
if (bind(s, res->ai_addr, res->ai_addrlen) < 0)
|
||||
err(1, "bind");
|
||||
if (listen(s, 1) < 0)
|
||||
err(1, "listen");
|
||||
foo = sizeof sin;
|
||||
ns = accept(s, (struct sockaddr *)&sin, &foo);
|
||||
foo = res->ai_addrlen;
|
||||
ns = accept(s, res->ai_addr, &foo);
|
||||
if (ns < 0)
|
||||
err(1, "accept");
|
||||
(void) dup2(ns, 0);
|
||||
@ -512,7 +529,7 @@ main(argc, argv)
|
||||
}
|
||||
|
||||
#if defined(IPPROTO_IP) && defined(IP_TOS)
|
||||
{
|
||||
if (from.ss_family == AF_INET) {
|
||||
# if defined(HAS_GETTOS)
|
||||
struct tosent *tp;
|
||||
if (tos < 0 && (tp = gettosbyname("telnet", "tcp")))
|
||||
@ -528,7 +545,7 @@ main(argc, argv)
|
||||
}
|
||||
#endif /* defined(IPPROTO_IP) && defined(IP_TOS) */
|
||||
net = 0;
|
||||
doit(&from);
|
||||
doit((struct sockaddr *)&from);
|
||||
/* NOTREACHED */
|
||||
return(0);
|
||||
} /* end of main */
|
||||
@ -773,8 +790,9 @@ char user_name[256];
|
||||
*/
|
||||
void
|
||||
doit(who)
|
||||
struct sockaddr_in *who;
|
||||
struct sockaddr *who;
|
||||
{
|
||||
int err;
|
||||
int ptynum;
|
||||
|
||||
/*
|
||||
@ -817,16 +835,18 @@ doit(who)
|
||||
#endif /* _SC_CRAY_SECURE_SYS */
|
||||
|
||||
/* get name of connected client */
|
||||
if (realhostname(remote_hostname, sizeof(remote_hostname) - 1,
|
||||
&who->sin_addr) == HOSTNAME_INVALIDADDR && registerd_host_only)
|
||||
if (realhostname_sa(remote_hostname, sizeof(remote_hostname) - 1,
|
||||
who, who->sa_len) == HOSTNAME_INVALIDADDR && registerd_host_only)
|
||||
fatal(net, "Couldn't resolve your address into a host name.\r\n\
|
||||
Please contact your net administrator");
|
||||
remote_hostname[sizeof(remote_hostname) - 1] = '\0';
|
||||
|
||||
trimdomain(remote_hostname, UT_HOSTSIZE);
|
||||
if (!isdigit(remote_hostname[0]) && strlen(remote_hostname) > utmp_len)
|
||||
strncpy(remote_hostname, inet_ntoa(who->sin_addr),
|
||||
sizeof(remote_hostname) - 1);
|
||||
err = getnameinfo(who, who->sa_len, remote_hostname,
|
||||
sizeof(remote_hostname), NULL, 0,
|
||||
NI_NUMERICHOST|NI_WITHSCOPEID);
|
||||
/* XXX: do 'err' check */
|
||||
|
||||
(void) gethostname(host_name, sizeof(host_name) - 1);
|
||||
host_name[sizeof(host_name) - 1] = '\0';
|
||||
|
@ -226,6 +226,8 @@ The
|
||||
.Nm
|
||||
command appeared in
|
||||
.Bx 4.2 .
|
||||
.Pp
|
||||
IPv6 support was added by WIDE/KAME project.
|
||||
.Sh BUGS
|
||||
.Nm Rlogin
|
||||
will be replaced by
|
||||
|
@ -154,6 +154,8 @@ main(argc, argv)
|
||||
#ifdef KERBEROS
|
||||
char *k;
|
||||
#endif
|
||||
struct sockaddr_storage ss;
|
||||
int sslen;
|
||||
|
||||
argoff = dflag = Dflag = 0;
|
||||
one = 1;
|
||||
@ -331,10 +333,11 @@ main(argc, argv)
|
||||
if (doencrypt)
|
||||
errx(1, "the -x flag requires Kerberos authentication");
|
||||
#endif /* CRYPT */
|
||||
rem = rcmd(&host, sp->s_port, localname, user, term, 0);
|
||||
rem = rcmd_af(&host, sp->s_port, localname, user, term, 0,
|
||||
PF_UNSPEC);
|
||||
}
|
||||
#else
|
||||
rem = rcmd(&host, sp->s_port, localname, user, term, 0);
|
||||
rem = rcmd_af(&host, sp->s_port, localname, user, term, 0, PF_UNSPEC);
|
||||
#endif /* KERBEROS */
|
||||
|
||||
if (rem < 0)
|
||||
@ -347,9 +350,16 @@ main(argc, argv)
|
||||
setsockopt(rem, IPPROTO_TCP, TCP_NODELAY, &one, sizeof(one)) < 0)
|
||||
warn("setsockopt NODELAY (ignored)");
|
||||
|
||||
sslen = sizeof(ss);
|
||||
one = IPTOS_LOWDELAY;
|
||||
if (setsockopt(rem, IPPROTO_IP, IP_TOS, (char *)&one, sizeof(int)) < 0)
|
||||
warn("setsockopt TOS (ignored)");
|
||||
if (getsockname(rem, (struct sockaddr *)&ss, &sslen) == 0 &&
|
||||
ss.ss_family == AF_INET) {
|
||||
if (setsockopt(rem, IPPROTO_IP, IP_TOS, (char *)&one,
|
||||
sizeof(int)) < 0)
|
||||
warn("setsockopt TOS (ignored)");
|
||||
} else
|
||||
if (ss.ss_family == AF_INET)
|
||||
warn("setsockopt getsockname failed");
|
||||
|
||||
(void)setuid(uid);
|
||||
doit(omask);
|
||||
|
@ -269,10 +269,12 @@ main(argc, argv)
|
||||
} else {
|
||||
if (doencrypt)
|
||||
errx(1, "the -x flag requires Kerberos authentication");
|
||||
rem = rcmd(&host, sp->s_port, pw->pw_name, user, args, &rfd2);
|
||||
rem = rcmd_af(&host, sp->s_port, pw->pw_name, user, args,
|
||||
&rfd2, PF_UNSPEC);
|
||||
}
|
||||
#else
|
||||
rem = rcmd(&host, sp->s_port, pw->pw_name, user, args, &rfd2);
|
||||
rem = rcmd_af(&host, sp->s_port, pw->pw_name, user, args, &rfd2,
|
||||
PF_UNSPEC);
|
||||
#endif
|
||||
|
||||
if (rem < 0)
|
||||
|
@ -10,7 +10,8 @@ MAINTAINER=des@freebsd.org
|
||||
COPTS+= -Wall -DLOGIN_CAP
|
||||
#COPTS+= -DSANITY_CHECK
|
||||
|
||||
DPADD+= ${LIBUTIL} ${LIBWRAP}
|
||||
LDADD+= -lutil -lwrap
|
||||
CFLAGS+=-DINET6 -DIPSEC
|
||||
DPADD+= ${LIBUTIL} ${LIBWRAP} ${LIBIPSEC}
|
||||
LDADD+= -lutil -lwrap -lipsec
|
||||
|
||||
.include <bsd.prog.mk>
|
||||
|
@ -57,7 +57,7 @@ extern struct servtab *servtab;
|
||||
char ring[128];
|
||||
char *endring;
|
||||
|
||||
int check_loop __P((struct sockaddr_in *, struct servtab *sep));
|
||||
int check_loop __P((struct sockaddr *, struct servtab *sep));
|
||||
void inetd_setproctitle __P((char *, int));
|
||||
|
||||
struct biltin biltins[] = {
|
||||
@ -111,7 +111,7 @@ chargen_dg(s, sep) /* Character generator */
|
||||
int s;
|
||||
struct servtab *sep;
|
||||
{
|
||||
struct sockaddr_in sin;
|
||||
struct sockaddr_storage ss;
|
||||
static char *rs;
|
||||
int len, size;
|
||||
char text[LINESIZ+2];
|
||||
@ -121,12 +121,12 @@ chargen_dg(s, sep) /* Character generator */
|
||||
rs = ring;
|
||||
}
|
||||
|
||||
size = sizeof(sin);
|
||||
size = sizeof(ss);
|
||||
if (recvfrom(s, text, sizeof(text), 0,
|
||||
(struct sockaddr *)&sin, &size) < 0)
|
||||
(struct sockaddr *)&ss, &size) < 0)
|
||||
return;
|
||||
|
||||
if (check_loop(&sin, sep))
|
||||
if (check_loop((struct sockaddr *)&ss, sep))
|
||||
return;
|
||||
|
||||
if ((len = endring - rs) >= LINESIZ)
|
||||
@ -140,7 +140,7 @@ chargen_dg(s, sep) /* Character generator */
|
||||
text[LINESIZ] = '\r';
|
||||
text[LINESIZ + 1] = '\n';
|
||||
(void) sendto(s, text, sizeof(text), 0,
|
||||
(struct sockaddr *)&sin, sizeof(sin));
|
||||
(struct sockaddr *)&ss, sizeof(ss));
|
||||
}
|
||||
|
||||
/* ARGSUSED */
|
||||
@ -189,22 +189,22 @@ daytime_dg(s, sep) /* Return human-readable time of day */
|
||||
{
|
||||
char buffer[256];
|
||||
time_t clock;
|
||||
struct sockaddr_in sin;
|
||||
struct sockaddr_storage ss;
|
||||
int size;
|
||||
|
||||
clock = time((time_t *) 0);
|
||||
|
||||
size = sizeof(sin);
|
||||
size = sizeof(ss);
|
||||
if (recvfrom(s, buffer, sizeof(buffer), 0,
|
||||
(struct sockaddr *)&sin, &size) < 0)
|
||||
(struct sockaddr *)&ss, &size) < 0)
|
||||
return;
|
||||
|
||||
if (check_loop(&sin, sep))
|
||||
if (check_loop((struct sockaddr *)&ss, sep))
|
||||
return;
|
||||
|
||||
(void) sprintf(buffer, "%.24s\r\n", ctime(&clock));
|
||||
(void) sendto(s, buffer, strlen(buffer), 0,
|
||||
(struct sockaddr *)&sin, sizeof(sin));
|
||||
(struct sockaddr *)&ss, sizeof(ss));
|
||||
}
|
||||
|
||||
/* ARGSUSED */
|
||||
@ -270,18 +270,18 @@ echo_dg(s, sep) /* Echo service -- echo data back */
|
||||
{
|
||||
char buffer[BUFSIZE];
|
||||
int i, size;
|
||||
struct sockaddr_in sin;
|
||||
struct sockaddr_storage ss;
|
||||
|
||||
size = sizeof(sin);
|
||||
size = sizeof(ss);
|
||||
if ((i = recvfrom(s, buffer, sizeof(buffer), 0,
|
||||
(struct sockaddr *)&sin, &size)) < 0)
|
||||
(struct sockaddr *)&ss, &size)) < 0)
|
||||
return;
|
||||
|
||||
if (check_loop(&sin, sep))
|
||||
if (check_loop((struct sockaddr *)&ss, sep))
|
||||
return;
|
||||
|
||||
(void) sendto(s, buffer, i, 0, (struct sockaddr *)&sin,
|
||||
sizeof(sin));
|
||||
(void) sendto(s, buffer, i, 0, (struct sockaddr *)&ss,
|
||||
sizeof(ss));
|
||||
}
|
||||
|
||||
/* ARGSUSED */
|
||||
@ -335,6 +335,8 @@ ident_stream(s, sep) /* Ident service (AKA "auth") */
|
||||
struct utsname un;
|
||||
struct stat sb;
|
||||
struct sockaddr_in sin[2];
|
||||
struct sockaddr_in6 sin6[2];
|
||||
struct sockaddr_storage ss[2];
|
||||
struct ucred uc;
|
||||
struct timeval tv = {
|
||||
10,
|
||||
@ -345,7 +347,7 @@ ident_stream(s, sep) /* Ident service (AKA "auth") */
|
||||
char buf[BUFSIZE], *cp = NULL, *p, **av, *osname = NULL, garbage[7];
|
||||
char *fallback = NULL;
|
||||
int len, c, fflag = 0, nflag = 0, rflag = 0, argc = 0, usedfallback = 0;
|
||||
int gflag = 0, Rflag = 0;
|
||||
int gflag = 0, Rflag = 0, getcredfail = 0;
|
||||
u_short lport, fport;
|
||||
|
||||
inetd_setproctitle(sep->se_service, s);
|
||||
@ -434,11 +436,11 @@ ident_stream(s, sep) /* Ident service (AKA "auth") */
|
||||
iderror(0, 0, s, errno);
|
||||
osname = un.sysname;
|
||||
}
|
||||
len = sizeof(sin[0]);
|
||||
if (getsockname(s, (struct sockaddr *)&sin[0], &len) == -1)
|
||||
len = sizeof(ss[0]);
|
||||
if (getsockname(s, (struct sockaddr *)&ss[0], &len) == -1)
|
||||
iderror(0, 0, s, errno);
|
||||
len = sizeof(sin[1]);
|
||||
if (getpeername(s, (struct sockaddr *)&sin[1], &len) == -1)
|
||||
len = sizeof(ss[1]);
|
||||
if (getpeername(s, (struct sockaddr *)&ss[1], &len) == -1)
|
||||
iderror(0, 0, s, errno);
|
||||
/*
|
||||
* We're going to prepare for and execute reception of a
|
||||
@ -476,11 +478,35 @@ ident_stream(s, sep) /* Ident service (AKA "auth") */
|
||||
* arrays have been filled in above via get{peer,sock}name(),
|
||||
* so right here we are only setting the ports.
|
||||
*/
|
||||
sin[0].sin_port = htons(lport);
|
||||
sin[1].sin_port = htons(fport);
|
||||
if (ss[0].ss_family != ss[1].ss_family)
|
||||
iderror(lport, fport, s, errno);
|
||||
len = sizeof(uc);
|
||||
if (sysctlbyname("net.inet.tcp.getcred", &uc, &len, sin,
|
||||
sizeof(sin)) == -1) {
|
||||
switch (ss[0].ss_family) {
|
||||
case AF_INET:
|
||||
sin[0] = *(struct sockaddr_in *)&ss[0];
|
||||
sin[0].sin_port = htons(lport);
|
||||
sin[1] = *(struct sockaddr_in *)&ss[1];
|
||||
sin[1].sin_port = htons(fport);
|
||||
if (sysctlbyname("net.inet.tcp.getcred", &uc, &len, sin,
|
||||
sizeof(sin)) == -1)
|
||||
getcredfail = 1;
|
||||
break;
|
||||
#ifdef INET6
|
||||
case AF_INET6:
|
||||
sin6[0] = *(struct sockaddr_in6 *)&ss[0];
|
||||
sin6[0].sin6_port = htons(lport);
|
||||
sin6[1] = *(struct sockaddr_in6 *)&ss[1];
|
||||
sin6[1].sin6_port = htons(fport);
|
||||
if (sysctlbyname("net.inet6.tcp6.getcred", &uc, &len, sin6,
|
||||
sizeof(sin6)) == -1)
|
||||
getcredfail = 1;
|
||||
break;
|
||||
#endif
|
||||
default: /* should not reach here */
|
||||
getcredfail = 1;
|
||||
break;
|
||||
}
|
||||
if (getcredfail != 0) {
|
||||
if (fallback == NULL) /* Use a default, if asked to */
|
||||
iderror(lport, fport, s, errno);
|
||||
usedfallback = 1;
|
||||
@ -611,20 +637,20 @@ machtime_dg(s, sep)
|
||||
struct servtab *sep;
|
||||
{
|
||||
unsigned long result;
|
||||
struct sockaddr_in sin;
|
||||
struct sockaddr_storage ss;
|
||||
int size;
|
||||
|
||||
size = sizeof(sin);
|
||||
size = sizeof(ss);
|
||||
if (recvfrom(s, (char *)&result, sizeof(result), 0,
|
||||
(struct sockaddr *)&sin, &size) < 0)
|
||||
(struct sockaddr *)&ss, &size) < 0)
|
||||
return;
|
||||
|
||||
if (check_loop(&sin, sep))
|
||||
if (check_loop((struct sockaddr *)&ss, sep))
|
||||
return;
|
||||
|
||||
result = machtime();
|
||||
(void) sendto(s, (char *) &result, sizeof(result), 0,
|
||||
(struct sockaddr *)&sin, sizeof(sin));
|
||||
(struct sockaddr *)&ss, sizeof(ss));
|
||||
}
|
||||
|
||||
/* ARGSUSED */
|
||||
|
@ -47,7 +47,7 @@
|
||||
.Op Fl W
|
||||
.Op Fl c Ar maximum
|
||||
.Op Fl C Ar rate
|
||||
.Op Fl a Ar address
|
||||
.Op Fl a Ar address|hostname
|
||||
.Op Fl p Ar filename
|
||||
.Op Fl R Ar rate
|
||||
.Op Ar configuration file
|
||||
@ -101,6 +101,22 @@ Specify the maximum number of times a service can be invoked
|
||||
in one minute; the default is 256.
|
||||
.It Fl a
|
||||
Specify a specific IP address to bind to.
|
||||
Or a hostname can also be specified, and then an IP address and/or an
|
||||
IPv6 address corresponds to the hostname is used. Usually hostname
|
||||
specification is used in conjunction with
|
||||
.Xr jail 8 ,
|
||||
where the hostname corresponds to a jail environment.
|
||||
|
||||
When hostname specification is used and either of IPv4 bind and IPv6
|
||||
bind is desired, you need to specify 2 entry for each service, one for
|
||||
IPv4 and one for IPv6, in /etc/inetd.conf.
|
||||
For example,
|
||||
.Bd -literal
|
||||
telnet stream tcp4 nowait root /usr/libexec/telnetd telnetd
|
||||
telnet stream tcp6 nowait root /usr/libexec/telnetd telnetd
|
||||
.Ed
|
||||
|
||||
See explanation for protocol field in /etc/inetd.conf for details.
|
||||
.It Fl p
|
||||
Specify an alternate file in which to store the process ID.
|
||||
.El
|
||||
@ -221,14 +237,39 @@ Examples might be
|
||||
.Dq tcp
|
||||
or
|
||||
.Dq udp .
|
||||
In this case, this entry only accept IPv4 to keep backword
|
||||
compatibility.
|
||||
The names
|
||||
.Dq tcp4 ,
|
||||
.Dq udp4
|
||||
specialized the entry to IPv4 only.
|
||||
The names
|
||||
.Dq tcp6 ,
|
||||
.Dq udp6
|
||||
specialized the entry to IPv6 only.
|
||||
The names
|
||||
.Dq tcp46 ,
|
||||
.Dq udp46
|
||||
let the entry accept each of IPv4 and IPv6 via AF_INET6 wildcard binded socket.
|
||||
If it is desired that the service is reachable via T/TCP, one should
|
||||
specify
|
||||
.Dq tcp/ttcp .
|
||||
This entry only accept IPv4 to keep backword compatibility.
|
||||
The name
|
||||
.Dq tcp4/ttcp ,
|
||||
specialized the entry to IPv4 only.
|
||||
The name
|
||||
.Dq tcp6/ttcp ,
|
||||
specialized the entry to IPv6 only.
|
||||
The name
|
||||
.Dq tcp46/ttcp ,
|
||||
let the entry accept each of IPv4 and IPv6 via AF_INET6 wildcard binded socket.
|
||||
Rpc based services are specified with the
|
||||
.Dq rpc/tcp
|
||||
or
|
||||
.Dq rpc/udp
|
||||
service type.
|
||||
Currently only IPv4 is supported for rpc services.
|
||||
TCPMUX services must use
|
||||
.Dq tcp .
|
||||
.Pp
|
||||
@ -436,6 +477,9 @@ in
|
||||
tcpmux stream tcp nowait root internal
|
||||
.Ed
|
||||
.Pp
|
||||
Or if you wish to provide TCPMUX services also over IPv6, you can
|
||||
specify tcp46 or tcp6 instead of tcp above.
|
||||
.Pp
|
||||
When given the
|
||||
.Fl l
|
||||
option
|
||||
@ -528,6 +572,30 @@ causes
|
||||
.Nm
|
||||
to list TCPMUX services in
|
||||
.Pa inetd.conf .
|
||||
.Sh IPSEC
|
||||
The implementation includes tiny hack to support IPsec policy setting for
|
||||
each of the socket.
|
||||
A special form of comment line, starting with
|
||||
.Dq Li "#@" ,
|
||||
will work as policy specifier.
|
||||
The content of the above comment line will be treated as IPsec policy string,
|
||||
as described in
|
||||
.Xr ipsec_set_policy 3 .
|
||||
A
|
||||
.Li "#@"
|
||||
line will affect all the following lines in
|
||||
.Pa inetd.conf ,
|
||||
so you may want to reset IPsec policy by using a comment line with
|
||||
.Li "#@"
|
||||
only
|
||||
.Pq with no policy string .
|
||||
.Pp
|
||||
If invalid IPsec policy string appears on
|
||||
.Pa inetd.conf ,
|
||||
.Nm
|
||||
will leave error message using
|
||||
.Xr syslog 3 ,
|
||||
and terminates itself.
|
||||
.Sh "FILES"
|
||||
.Bl -tag -width /var/run/inetd.pid -compact
|
||||
.It Pa /etc/inetd.conf
|
||||
@ -546,9 +614,14 @@ Here are several example service entries for the various types of services:
|
||||
.Bd -literal
|
||||
ftp stream tcp nowait root /usr/libexec/ftpd ftpd -l
|
||||
ntalk dgram udp wait root /usr/libexec/ntalkd ntalkd
|
||||
telnet stream tcp6 nowait root /usr/libexec/telnetd telnetd
|
||||
shell stream tcp46 nowait root /usr/libexec/rshd rshd
|
||||
tcpmux/+date stream tcp nowait guest /bin/date date
|
||||
tcpmux/phonebook stream tcp nowait guest /usr/local/bin/phonebook phonebook
|
||||
rstatd/1-3 dgram rpc/udp wait root /usr/libexec/rpc.rstatd rpc.rstatd
|
||||
#@ ipsec ah/require
|
||||
chargen stream tcp nowait root internal
|
||||
#@
|
||||
.Ed
|
||||
.Sh "ERROR MESSAGES"
|
||||
The
|
||||
@ -632,6 +705,7 @@ socket but was unable to.
|
||||
.Sh SEE ALSO
|
||||
.Xr hosts_access 5 ,
|
||||
.Xr hosts_options 5 ,
|
||||
.Xr ipsec_set_policy 3 ,
|
||||
.Xr login.conf 5 ,
|
||||
.Xr passwd 5 ,
|
||||
.Xr rpc 5 ,
|
||||
@ -662,6 +736,7 @@ based services is modeled after that
|
||||
provided by
|
||||
.Tn SunOS
|
||||
4.1.
|
||||
IPsec hack was made by KAME project, in 1999.
|
||||
The
|
||||
.Tn FreeBSD
|
||||
TCP Wrappers support first appeared in
|
||||
|
@ -102,6 +102,13 @@ static const char rcsid[] =
|
||||
* server program arguments maximum of MAXARGS
|
||||
*
|
||||
* Comment lines are indicated by a `#' in column 1.
|
||||
*
|
||||
* #ifdef IPSEC
|
||||
* Comment lines that start with "#@" denote IPsec policy string, as described
|
||||
* in ipsec_set_policy(3). This will affect all the following items in
|
||||
* inetd.conf(8). To reset the policy, just use "#@" line. By default,
|
||||
* there's no IPsec policy.
|
||||
* #endif
|
||||
*/
|
||||
#include <sys/param.h>
|
||||
#include <sys/ioctl.h>
|
||||
@ -130,10 +137,23 @@ static const char rcsid[] =
|
||||
#include <unistd.h>
|
||||
#include <libutil.h>
|
||||
#include <sysexits.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "inetd.h"
|
||||
#include "pathnames.h"
|
||||
|
||||
#ifdef IPSEC
|
||||
#include <netinet6/ipsec.h>
|
||||
#ifndef IPSEC_POLICY_IPSEC /* no ipsec support on old ipsec */
|
||||
#undef IPSEC
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* wrapper for KAME-special getnameinfo() */
|
||||
#ifndef NI_WITHSCOPEID
|
||||
#define NI_WITHSCOPEID 0
|
||||
#endif
|
||||
|
||||
#ifndef LIBWRAP_ALLOW_FACILITY
|
||||
# define LIBWRAP_ALLOW_FACILITY LOG_AUTH
|
||||
#endif
|
||||
@ -193,7 +213,13 @@ int maxchild = MAXCHILD;
|
||||
int maxcpm = MAXCPM;
|
||||
struct servent *sp;
|
||||
struct rpcent *rpc;
|
||||
struct in_addr bind_address;
|
||||
char *hostname = NULL;
|
||||
struct sockaddr_in *bind_sa4;
|
||||
int no_v4bind = 1;
|
||||
#ifdef INET6
|
||||
struct sockaddr_in6 *bind_sa6;
|
||||
int no_v6bind = 1;
|
||||
#endif
|
||||
int signalpipe[2];
|
||||
#ifdef SANITY_CHECK
|
||||
int nsock;
|
||||
@ -248,8 +274,20 @@ main(argc, argv, envp)
|
||||
int denied;
|
||||
char *service = NULL;
|
||||
char *pnm;
|
||||
struct sockaddr_in peer;
|
||||
union {
|
||||
struct sockaddr peer_un;
|
||||
struct sockaddr_in peer_un4;
|
||||
struct sockaddr_in6 peer_un6;
|
||||
struct sockaddr_storage peer_max;
|
||||
} p_un;
|
||||
#define peer p_un.peer_un
|
||||
#define peer4 p_un.peer_un4
|
||||
#define peer6 p_un.peer_un6
|
||||
#define peermax p_un.peer_max
|
||||
int i;
|
||||
struct addrinfo hints, *res;
|
||||
char *servname;
|
||||
int error;
|
||||
|
||||
|
||||
#ifdef OLD_SETPROCTITLE
|
||||
@ -263,7 +301,6 @@ main(argc, argv, envp)
|
||||
|
||||
openlog("inetd", LOG_PID | LOG_NOWAIT, LOG_DAEMON);
|
||||
|
||||
bind_address.s_addr = htonl(INADDR_ANY);
|
||||
while ((ch = getopt(argc, argv, "dlwWR:a:c:C:p:")) != -1)
|
||||
switch(ch) {
|
||||
case 'd':
|
||||
@ -286,11 +323,7 @@ main(argc, argv, envp)
|
||||
"-C %s: bad value for maximum children/minute");
|
||||
break;
|
||||
case 'a':
|
||||
if (!inet_aton(optarg, &bind_address)) {
|
||||
syslog(LOG_ERR,
|
||||
"-a %s: invalid IP address", optarg);
|
||||
exit(EX_USAGE);
|
||||
}
|
||||
hostname = optarg;
|
||||
break;
|
||||
case 'p':
|
||||
pid_file = optarg;
|
||||
@ -309,6 +342,66 @@ main(argc, argv, envp)
|
||||
" [-p pidfile] [conf-file]");
|
||||
exit(EX_USAGE);
|
||||
}
|
||||
/*
|
||||
* Initialize Bind Addrs.
|
||||
* When hostname is NULL, wild card bind addrs are obtained from
|
||||
* getaddrinfo(). But getaddrinfo() requires at least one of
|
||||
* hostname or servname is non NULL.
|
||||
* So when hostname is NULL, set dummy value to servname.
|
||||
*/
|
||||
servname = (hostname == NULL) ? "discard" /* dummy */ : NULL;
|
||||
|
||||
bzero(&hints, sizeof(struct addrinfo));
|
||||
hints.ai_flags = AI_PASSIVE;
|
||||
hints.ai_family = AF_UNSPEC;
|
||||
error = getaddrinfo(hostname, servname, &hints, &res);
|
||||
if (error != 0) {
|
||||
syslog(LOG_ERR, "-a %s: %s", hostname, gai_strerror(error));
|
||||
if (error == EAI_SYSTEM)
|
||||
syslog(LOG_ERR, "%s", strerror(errno));
|
||||
exit(EX_USAGE);
|
||||
}
|
||||
do {
|
||||
if (res->ai_addr == NULL) {
|
||||
syslog(LOG_ERR, "-a %s: getaddrinfo failed", hostname);
|
||||
exit(EX_USAGE);
|
||||
}
|
||||
switch (res->ai_addr->sa_family) {
|
||||
case AF_INET:
|
||||
if (no_v4bind == 0)
|
||||
continue;
|
||||
bind_sa4 = (struct sockaddr_in *)res->ai_addr;
|
||||
/* init port num in case servname is dummy */
|
||||
bind_sa4->sin_port = 0;
|
||||
no_v4bind = 0;
|
||||
continue;
|
||||
#ifdef INET6
|
||||
case AF_INET6:
|
||||
if (no_v6bind == 0)
|
||||
continue;
|
||||
bind_sa6 = (struct sockaddr_in6 *)res->ai_addr;
|
||||
/* init port num in case servname is dummy */
|
||||
bind_sa6->sin6_port = 0;
|
||||
no_v6bind = 0;
|
||||
continue;
|
||||
#endif
|
||||
}
|
||||
if (no_v4bind == 0
|
||||
#ifdef INET6
|
||||
&& no_v6bind == 0
|
||||
#endif
|
||||
)
|
||||
break;
|
||||
} while ((res = res->ai_next) != NULL);
|
||||
if (no_v4bind != 0
|
||||
#ifdef INET6
|
||||
&& no_v6bind != 0
|
||||
#endif
|
||||
) {
|
||||
syslog(LOG_ERR, "-a %s: unknown address family", hostname);
|
||||
exit(EX_USAGE);
|
||||
}
|
||||
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
@ -457,18 +550,33 @@ main(argc, argv, envp)
|
||||
} else
|
||||
ctrl = sep->se_fd;
|
||||
if (log && !ISWRAP(sep)) {
|
||||
char pname[INET6_ADDRSTRLEN];
|
||||
pnm = "unknown";
|
||||
i = sizeof peer;
|
||||
i = sizeof peermax;
|
||||
if (getpeername(ctrl, (struct sockaddr *)
|
||||
&peer, &i)) {
|
||||
i = sizeof peer;
|
||||
&peermax, &i)) {
|
||||
i = sizeof peermax;
|
||||
if (recvfrom(ctrl, buf, sizeof(buf),
|
||||
MSG_PEEK,
|
||||
(struct sockaddr *)&peer, &i) >= 0)
|
||||
pnm = inet_ntoa(peer.sin_addr);
|
||||
(struct sockaddr *)&peermax,
|
||||
&i) >= 0) {
|
||||
getnameinfo((struct sockaddr *)&peermax,
|
||||
sizeof(peermax),
|
||||
pname, sizeof(pname),
|
||||
NULL, 0,
|
||||
NI_NUMERICHOST|
|
||||
NI_WITHSCOPEID);
|
||||
pnm = pname;
|
||||
}
|
||||
} else {
|
||||
getnameinfo((struct sockaddr *)&peermax,
|
||||
sizeof(peermax),
|
||||
pname, sizeof(pname),
|
||||
NULL, 0,
|
||||
NI_NUMERICHOST|
|
||||
NI_WITHSCOPEID);
|
||||
pnm = pname;
|
||||
}
|
||||
else
|
||||
pnm = inet_ntoa(peer.sin_addr);
|
||||
syslog(LOG_INFO,"%s from %s", sep->se_service, pnm);
|
||||
}
|
||||
(void) sigblock(SIGBLOCK);
|
||||
@ -783,13 +891,18 @@ void config()
|
||||
#endif
|
||||
for (sep = servtab; sep; sep = sep->se_next)
|
||||
if (strcmp(sep->se_service, new->se_service) == 0 &&
|
||||
strcmp(sep->se_proto, new->se_proto) == 0)
|
||||
strcmp(sep->se_proto, new->se_proto) == 0 &&
|
||||
sep->se_family == new->se_family)
|
||||
break;
|
||||
if (sep != 0) {
|
||||
int i;
|
||||
|
||||
#define SWAP(a, b) { typeof(a) c = a; a = b; b = c; }
|
||||
omask = sigblock(SIGBLOCK);
|
||||
if (sep->se_nomapped != new->se_nomapped) {
|
||||
sep->se_nomapped = new->se_nomapped;
|
||||
sep->se_reset = 1;
|
||||
}
|
||||
/* copy over outstanding child pids */
|
||||
if (sep->se_maxchild && new->se_maxchild) {
|
||||
new->se_numchild = sep->se_numchild;
|
||||
@ -823,6 +936,10 @@ void config()
|
||||
SWAP(sep->se_server_name, new->se_server_name);
|
||||
for (i = 0; i < MAXARGV; i++)
|
||||
SWAP(sep->se_argv[i], new->se_argv[i]);
|
||||
#ifdef IPSEC
|
||||
SWAP(sep->se_policy, new->se_policy);
|
||||
ipsecsetup(sep);
|
||||
#endif
|
||||
sigsetmask(omask);
|
||||
freeconfig(new);
|
||||
if (debug)
|
||||
@ -837,21 +954,63 @@ void config()
|
||||
sep->se_fd = -1;
|
||||
continue;
|
||||
}
|
||||
switch (sep->se_family) {
|
||||
case AF_INET:
|
||||
if (no_v4bind != 0) {
|
||||
sep->se_fd = -1;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
#ifdef INET6
|
||||
case AF_INET6:
|
||||
if (no_v6bind != 0) {
|
||||
sep->se_fd = -1;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
if (!sep->se_rpc) {
|
||||
sp = getservbyname(sep->se_service, sep->se_proto);
|
||||
if (sp == 0) {
|
||||
syslog(LOG_ERR, "%s/%s: unknown service",
|
||||
sep->se_service, sep->se_proto);
|
||||
sep->se_service, sep->se_proto);
|
||||
sep->se_checked = 0;
|
||||
continue;
|
||||
}
|
||||
if (sp->s_port != sep->se_ctrladdr.sin_port) {
|
||||
sep->se_ctrladdr.sin_family = AF_INET;
|
||||
sep->se_ctrladdr.sin_addr = bind_address;
|
||||
sep->se_ctrladdr.sin_port = sp->s_port;
|
||||
if (sep->se_fd >= 0)
|
||||
close_sep(sep);
|
||||
switch (sep->se_family) {
|
||||
case AF_INET:
|
||||
if (sep->se_ctladdrinitok == 0) {
|
||||
memcpy(&sep->se_ctrladdr4, bind_sa4,
|
||||
sizeof(sep->se_ctrladdr4));
|
||||
sep->se_ctrladdr_size =
|
||||
sizeof(sep->se_ctrladdr4);
|
||||
}
|
||||
if (sp->s_port != sep->se_ctrladdr4.sin_port) {
|
||||
sep->se_ctrladdr4.sin_port =
|
||||
sp->s_port;
|
||||
sep->se_reset = 1;
|
||||
}
|
||||
break;
|
||||
#ifdef INET6
|
||||
case AF_INET6:
|
||||
if (sep->se_ctladdrinitok == 0) {
|
||||
memcpy(&sep->se_ctrladdr6, bind_sa6,
|
||||
sizeof(sep->se_ctrladdr6));
|
||||
sep->se_ctrladdr_size =
|
||||
sizeof(sep->se_ctrladdr6);
|
||||
}
|
||||
if (sp->s_port !=
|
||||
sep->se_ctrladdr6.sin6_port) {
|
||||
sep->se_ctrladdr6.sin6_port =
|
||||
sp->s_port;
|
||||
sep->se_reset = 1;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
if (sep->se_reset != 0 && sep->se_fd >= 0)
|
||||
close_sep(sep);
|
||||
} else {
|
||||
rpc = getrpcbyname(sep->se_service);
|
||||
if (rpc == 0) {
|
||||
@ -950,7 +1109,7 @@ setup(sep)
|
||||
{
|
||||
int on = 1;
|
||||
|
||||
if ((sep->se_fd = socket(AF_INET, sep->se_socktype, 0)) < 0) {
|
||||
if ((sep->se_fd = socket(sep->se_family, sep->se_socktype, 0)) < 0) {
|
||||
if (debug)
|
||||
warn("socket failed on %s/%s",
|
||||
sep->se_service, sep->se_proto);
|
||||
@ -969,13 +1128,38 @@ setsockopt(fd, SOL_SOCKET, opt, (char *)&on, sizeof (on))
|
||||
if (turnon(sep->se_fd, SO_PRIVSTATE) < 0)
|
||||
syslog(LOG_ERR, "setsockopt (SO_PRIVSTATE): %m");
|
||||
#endif
|
||||
/* tftpd opens a new connection then needs more infos */
|
||||
if ((sep->se_family == AF_INET6) &&
|
||||
(strcmp(sep->se_proto, "udp") == 0) &&
|
||||
(sep->se_accept == 0) &&
|
||||
(setsockopt(sep->se_fd, IPPROTO_IPV6, IPV6_PKTINFO,
|
||||
(char *)&on, sizeof (on)) < 0))
|
||||
syslog(LOG_ERR, "setsockopt (IPV6_RECVPKTINFO): %m");
|
||||
#ifdef IPV6_BINDV6ONLY
|
||||
if ((sep->se_family == AF_INET6) &&
|
||||
(sep->se_nomapped != 0) &&
|
||||
(setsockopt(sep->se_fd, IPPROTO_IPV6, IPV6_BINDV6ONLY,
|
||||
(char *)&on, sizeof (on)) < 0))
|
||||
syslog(LOG_ERR, "setsockopt (IPV6_BINDV6ONLY): %m");
|
||||
#endif /* IPV6_BINDV6ONLY */
|
||||
#undef turnon
|
||||
if (sep->se_type == TTCP_TYPE)
|
||||
if (setsockopt(sep->se_fd, IPPROTO_TCP, TCP_NOPUSH,
|
||||
(char *)&on, sizeof (on)) < 0)
|
||||
syslog(LOG_ERR, "setsockopt (TCP_NOPUSH): %m");
|
||||
#ifdef IPV6_FAITH
|
||||
if (sep->se_type == FAITH_TYPE) {
|
||||
if (setsockopt(sep->se_fd, IPPROTO_IPV6, IPV6_FAITH, &on,
|
||||
sizeof(on)) < 0) {
|
||||
syslog(LOG_ERR, "setsockopt (IPV6_FAITH): %m");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#ifdef IPSEC
|
||||
ipsecsetup(sep);
|
||||
#endif
|
||||
if (bind(sep->se_fd, (struct sockaddr *)&sep->se_ctrladdr,
|
||||
sizeof (sep->se_ctrladdr)) < 0) {
|
||||
sep->se_ctrladdr_size) < 0) {
|
||||
if (debug)
|
||||
warn("bind failed on %s/%s",
|
||||
sep->se_service, sep->se_proto);
|
||||
@ -990,8 +1174,16 @@ setsockopt(fd, SOL_SOCKET, opt, (char *)&on, sizeof (on))
|
||||
return;
|
||||
}
|
||||
if (sep->se_rpc) {
|
||||
int i, len = sizeof(struct sockaddr);
|
||||
int i, len = sep->se_ctrladdr_size;
|
||||
|
||||
if (sep->se_family != AF_INET) {
|
||||
syslog(LOG_ERR,
|
||||
"%s/%s: unsupported address family for rpc",
|
||||
sep->se_service, sep->se_proto);
|
||||
(void) close(sep->se_fd);
|
||||
sep->se_fd = -1;
|
||||
return;
|
||||
}
|
||||
if (getsockname(sep->se_fd,
|
||||
(struct sockaddr*)&sep->se_ctrladdr, &len) < 0){
|
||||
syslog(LOG_ERR, "%s/%s: getsockname: %m",
|
||||
@ -1007,9 +1199,8 @@ setsockopt(fd, SOL_SOCKET, opt, (char *)&on, sizeof (on))
|
||||
pmap_set(sep->se_rpc_prog, i,
|
||||
(sep->se_socktype == SOCK_DGRAM)
|
||||
? IPPROTO_UDP : IPPROTO_TCP,
|
||||
ntohs(sep->se_ctrladdr.sin_port));
|
||||
ntohs(sep->se_ctrladdr4.sin_port));
|
||||
}
|
||||
|
||||
}
|
||||
if (sep->se_socktype == SOCK_STREAM)
|
||||
listen(sep->se_fd, 64);
|
||||
@ -1020,6 +1211,80 @@ setsockopt(fd, SOL_SOCKET, opt, (char *)&on, sizeof (on))
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef IPSEC
|
||||
void
|
||||
ipsecsetup(sep)
|
||||
struct servtab *sep;
|
||||
{
|
||||
char *buf;
|
||||
char *policy_in = NULL;
|
||||
char *policy_out = NULL;
|
||||
int level;
|
||||
int opt;
|
||||
|
||||
switch (sep->se_family) {
|
||||
case AF_INET:
|
||||
level = IPPROTO_IP;
|
||||
opt = IP_IPSEC_POLICY;
|
||||
break;
|
||||
#ifdef INET6
|
||||
case AF_INET6:
|
||||
level = IPPROTO_IPV6;
|
||||
opt = IPV6_IPSEC_POLICY;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
if (!sep->se_policy || sep->se_policy[0] == '\0') {
|
||||
policy_in = "in entrust";
|
||||
policy_out = "out entrust";
|
||||
} else {
|
||||
if (!strncmp("in", sep->se_policy, 2))
|
||||
policy_in = sep->se_policy;
|
||||
else if (!strncmp("out", sep->se_policy, 3))
|
||||
policy_out = sep->se_policy;
|
||||
else {
|
||||
syslog(LOG_ERR, "invalid security policy \"%s\"",
|
||||
sep->se_policy);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (policy_in != NULL) {
|
||||
buf = ipsec_set_policy(policy_in, strlen(policy_in));
|
||||
if (buf != NULL) {
|
||||
if (setsockopt(sep->se_fd, level, opt,
|
||||
buf, ipsec_get_policylen(buf)) < 0) {
|
||||
syslog(LOG_ERR,
|
||||
"%s/%s: ipsec initialization failed; %s",
|
||||
sep->se_service, sep->se_proto,
|
||||
policy_in);
|
||||
}
|
||||
free(buf);
|
||||
} else
|
||||
syslog(LOG_ERR, "invalid security policy \"%s\"",
|
||||
policy_in);
|
||||
}
|
||||
if (policy_out != NULL) {
|
||||
buf = ipsec_set_policy(policy_out, strlen(policy_out));
|
||||
if (buf != NULL) {
|
||||
if (setsockopt(sep->se_fd, level, opt,
|
||||
buf, ipsec_get_policylen(buf)) < 0) {
|
||||
syslog(LOG_ERR,
|
||||
"%s/%s: ipsec initialization failed; %s",
|
||||
sep->se_service, sep->se_proto,
|
||||
policy_out);
|
||||
}
|
||||
free(buf);
|
||||
} else
|
||||
syslog(LOG_ERR, "invalid security policy \"%s\"",
|
||||
policy_out);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Finish with a service and its socket.
|
||||
*/
|
||||
@ -1173,10 +1438,42 @@ getconfigent()
|
||||
char *versp;
|
||||
static char TCPMUX_TOKEN[] = "tcpmux/";
|
||||
#define MUX_LEN (sizeof(TCPMUX_TOKEN)-1)
|
||||
#ifdef IPSEC
|
||||
char *policy = NULL;
|
||||
#endif
|
||||
int v4bind = 0;
|
||||
#ifdef INET6
|
||||
int v6bind = 0;
|
||||
#endif
|
||||
|
||||
more:
|
||||
while ((cp = nextline(fconfig)) && (*cp == '#' || *cp == '\0'))
|
||||
;
|
||||
while ((cp = nextline(fconfig)) != NULL) {
|
||||
#ifdef IPSEC
|
||||
/* lines starting with #@ is not a comment, but the policy */
|
||||
if (cp[0] == '#' && cp[1] == '@') {
|
||||
char *p;
|
||||
for (p = cp + 2; p && *p && isspace(*p); p++)
|
||||
;
|
||||
if (*p == '\0') {
|
||||
if (policy)
|
||||
free(policy);
|
||||
policy = NULL;
|
||||
} else if (ipsec_get_policylen(p) >= 0) {
|
||||
if (policy)
|
||||
free(policy);
|
||||
policy = newstr(p);
|
||||
} else {
|
||||
syslog(LOG_ERR,
|
||||
"%s: invalid ipsec policy \"%s\"",
|
||||
CONFIG, p);
|
||||
exit(EX_CONFIG);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (*cp == '#' || *cp == '\0')
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
if (cp == NULL)
|
||||
return ((struct servtab *)0);
|
||||
/*
|
||||
@ -1216,21 +1513,29 @@ getconfigent()
|
||||
sep->se_socktype = -1;
|
||||
|
||||
arg = sskip(&cp);
|
||||
if (strcmp(arg, "tcp/ttcp") == 0) {
|
||||
sep->se_type = TTCP_TYPE;
|
||||
sep->se_proto = newstr("tcp");
|
||||
} else {
|
||||
if (strncmp(arg, "tcp", 3) == 0) {
|
||||
sep->se_proto = newstr(strsep(&arg, "/"));
|
||||
if (arg != NULL) {
|
||||
if (strcmp(arg, "ttcp") == 0)
|
||||
sep->se_type = TTCP_TYPE;
|
||||
else if (strcmp(arg, "faith") == 0)
|
||||
sep->se_type = FAITH_TYPE;
|
||||
}
|
||||
} else
|
||||
sep->se_proto = newstr(arg);
|
||||
}
|
||||
if (strncmp(sep->se_proto, "rpc/", 4) == 0) {
|
||||
if (sep->se_family != AF_INET) {
|
||||
syslog(LOG_ERR, "IPv6 for RPC is not supported yet");
|
||||
freeconfig(sep);
|
||||
goto more;
|
||||
}
|
||||
memmove(sep->se_proto, sep->se_proto + 4,
|
||||
strlen(sep->se_proto) + 1 - 4);
|
||||
sep->se_rpc = 1;
|
||||
sep->se_rpc_prog = sep->se_rpc_lowvers =
|
||||
sep->se_rpc_lowvers = 0;
|
||||
sep->se_ctrladdr.sin_family = AF_INET;
|
||||
sep->se_ctrladdr.sin_port = 0;
|
||||
sep->se_ctrladdr.sin_addr = bind_address;
|
||||
memcpy(&sep->se_ctrladdr4, bind_sa4,
|
||||
sizeof(sep->se_ctrladdr4));
|
||||
if ((versp = rindex(sep->se_service, '/'))) {
|
||||
*versp++ = '\0';
|
||||
switch (sscanf(versp, "%d-%d",
|
||||
@ -1255,6 +1560,64 @@ getconfigent()
|
||||
sep->se_rpc_highvers = 1;
|
||||
}
|
||||
}
|
||||
sep->se_nomapped = 0;
|
||||
while (isdigit(sep->se_proto[strlen(sep->se_proto) - 1])) {
|
||||
#ifdef INET6
|
||||
if (sep->se_proto[strlen(sep->se_proto) - 1] == '6') {
|
||||
if (no_v6bind != 0) {
|
||||
syslog(LOG_INFO, "IPv6 bind is ignored for %s",
|
||||
sep->se_service);
|
||||
freeconfig(sep);
|
||||
goto more;
|
||||
}
|
||||
sep->se_proto[strlen(sep->se_proto) - 1] = '\0';
|
||||
v6bind = 1;
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
if (sep->se_proto[strlen(sep->se_proto) - 1] == '4') {
|
||||
sep->se_proto[strlen(sep->se_proto) - 1] = '\0';
|
||||
v4bind = 1;
|
||||
continue;
|
||||
}
|
||||
/* illegal version num */
|
||||
syslog(LOG_ERR, "bad IP version for %s", sep->se_proto);
|
||||
freeconfig(sep);
|
||||
goto more;
|
||||
}
|
||||
#ifdef INET6
|
||||
if (v6bind != 0) {
|
||||
sep->se_family = AF_INET6;
|
||||
if (v4bind == 0 || no_v4bind != 0)
|
||||
sep->se_nomapped = 1;
|
||||
}
|
||||
#endif
|
||||
else { /* default to v4 bind if not v6 bind */
|
||||
if (no_v4bind != 0) {
|
||||
syslog(LOG_INFO, "IPv4 bind is ignored for %s",
|
||||
sep->se_service);
|
||||
freeconfig(sep);
|
||||
goto more;
|
||||
}
|
||||
sep->se_family = AF_INET;
|
||||
}
|
||||
/* init ctladdr */
|
||||
switch(sep->se_family) {
|
||||
case AF_INET:
|
||||
memcpy(&sep->se_ctrladdr4, bind_sa4,
|
||||
sizeof(sep->se_ctrladdr4));
|
||||
sep->se_ctrladdr_size = sizeof(sep->se_ctrladdr4);
|
||||
sep->se_ctladdrinitok = 1;
|
||||
break;
|
||||
#ifdef INET6
|
||||
case AF_INET6:
|
||||
memcpy(&sep->se_ctrladdr6, bind_sa6,
|
||||
sizeof(sep->se_ctrladdr6));
|
||||
sep->se_ctrladdr_size = sizeof(sep->se_ctrladdr6);
|
||||
sep->se_ctladdrinitok = 1;
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
arg = sskip(&cp);
|
||||
if (!strncmp(arg, "wait", 4))
|
||||
sep->se_accept = 0;
|
||||
@ -1372,6 +1735,9 @@ getconfigent()
|
||||
}
|
||||
while (argc <= MAXARGV)
|
||||
sep->se_argv[argc++] = NULL;
|
||||
#ifdef IPSEC
|
||||
sep->se_policy = policy ? newstr(policy) : NULL;
|
||||
#endif
|
||||
return (sep);
|
||||
}
|
||||
|
||||
@ -1400,6 +1766,10 @@ freeconfig(cp)
|
||||
for (i = 0; i < MAXARGV; i++)
|
||||
if (cp->se_argv[i])
|
||||
free(cp->se_argv[i]);
|
||||
#ifdef IPSEC
|
||||
if (cp->se_policy)
|
||||
free(cp->se_policy);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@ -1490,14 +1860,16 @@ inetd_setproctitle(a, s)
|
||||
{
|
||||
int size;
|
||||
char *cp;
|
||||
struct sockaddr_in sin;
|
||||
char buf[80];
|
||||
struct sockaddr_storage ss;
|
||||
char buf[80], pbuf[INET6_ADDRSTRLEN];
|
||||
|
||||
cp = Argv[0];
|
||||
size = sizeof(sin);
|
||||
if (getpeername(s, (struct sockaddr *)&sin, &size) == 0)
|
||||
(void) sprintf(buf, "-%s [%s]", a, inet_ntoa(sin.sin_addr));
|
||||
else
|
||||
size = sizeof(ss);
|
||||
if (getpeername(s, (struct sockaddr *)&ss, &size) == 0) {
|
||||
getnameinfo((struct sockaddr *)&ss, size, pbuf, sizeof(pbuf),
|
||||
NULL, 0, NI_NUMERICHOST|NI_WITHSCOPEID);
|
||||
(void) sprintf(buf, "-%s [%s]", a, pbuf);
|
||||
} else
|
||||
(void) sprintf(buf, "-%s", a);
|
||||
strncpy(cp, buf, LastArg - cp);
|
||||
cp += strlen(cp);
|
||||
@ -1511,13 +1883,15 @@ inetd_setproctitle(a, s)
|
||||
int s;
|
||||
{
|
||||
int size;
|
||||
struct sockaddr_in sin;
|
||||
char buf[80];
|
||||
struct sockaddr_storage ss;
|
||||
char buf[80], pbuf[INET6_ADDRSTRLEN];
|
||||
|
||||
size = sizeof(sin);
|
||||
if (getpeername(s, (struct sockaddr *)&sin, &size) == 0)
|
||||
(void) sprintf(buf, "%s [%s]", a, inet_ntoa(sin.sin_addr));
|
||||
else
|
||||
size = sizeof(ss);
|
||||
if (getpeername(s, (struct sockaddr *)&ss, &size) == 0) {
|
||||
getnameinfo((struct sockaddr *)&ss, size, pbuf, sizeof(pbuf),
|
||||
NULL, 0, NI_NUMERICHOST|NI_WITHSCOPEID);
|
||||
(void) sprintf(buf, "%s [%s]", a, pbuf);
|
||||
} else
|
||||
(void) sprintf(buf, "%s", a);
|
||||
setproctitle("%s", buf);
|
||||
}
|
||||
@ -1528,24 +1902,41 @@ inetd_setproctitle(a, s)
|
||||
* Internet services provided internally by inetd:
|
||||
*/
|
||||
|
||||
int check_loop(sin, sep)
|
||||
struct sockaddr_in *sin;
|
||||
int check_loop(sa, sep)
|
||||
struct sockaddr *sa;
|
||||
struct servtab *sep;
|
||||
{
|
||||
struct servtab *se2;
|
||||
char pname[INET6_ADDRSTRLEN];
|
||||
|
||||
for (se2 = servtab; se2; se2 = se2->se_next) {
|
||||
if (!se2->se_bi || se2->se_socktype != SOCK_DGRAM)
|
||||
continue;
|
||||
|
||||
if (sin->sin_port == se2->se_ctrladdr.sin_port) {
|
||||
syslog(LOG_WARNING,
|
||||
"%s/%s:%s/%s loop request REFUSED from %s",
|
||||
sep->se_service, sep->se_proto,
|
||||
se2->se_service, se2->se_proto,
|
||||
inet_ntoa(sin->sin_addr));
|
||||
return 1;
|
||||
switch (se2->se_family) {
|
||||
case AF_INET:
|
||||
if (((struct sockaddr_in *)sa)->sin_port ==
|
||||
se2->se_ctrladdr4.sin_port)
|
||||
goto isloop;
|
||||
continue;
|
||||
#ifdef INET6
|
||||
case AF_INET6:
|
||||
if (((struct sockaddr_in *)sa)->sin_port ==
|
||||
se2->se_ctrladdr4.sin_port)
|
||||
goto isloop;
|
||||
continue;
|
||||
#endif
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
isloop:
|
||||
getnameinfo(sa, sa->sa_len, pname, sizeof(pname), NULL, 0,
|
||||
NI_NUMERICHOST|NI_WITHSCOPEID);
|
||||
syslog(LOG_WARNING, "%s/%s:%s/%s loop request REFUSED from %s",
|
||||
sep->se_service, sep->se_proto,
|
||||
se2->se_service, se2->se_proto,
|
||||
pname);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -1560,17 +1951,25 @@ print_service(action, sep)
|
||||
struct servtab *sep;
|
||||
{
|
||||
fprintf(stderr,
|
||||
"%s: %s proto=%s accept=%d max=%d user=%s group=%s"
|
||||
#ifdef LOGIN_CAP
|
||||
"%s: %s proto=%s accept=%d max=%d user=%s group=%s class=%s builtin=%p server=%s\n",
|
||||
#else
|
||||
"%s: %s proto=%s accept=%d max=%d user=%s group=%s builtin=%p server=%s\n",
|
||||
"class=%s"
|
||||
#endif
|
||||
" builtin=%p server=%s"
|
||||
#ifdef IPSEC
|
||||
" policy=\"%s\""
|
||||
#endif
|
||||
"\n",
|
||||
action, sep->se_service, sep->se_proto,
|
||||
sep->se_accept, sep->se_maxchild, sep->se_user, sep->se_group,
|
||||
#ifdef LOGIN_CAP
|
||||
sep->se_class,
|
||||
#endif
|
||||
(void *) sep->se_bi, sep->se_server);
|
||||
(void *) sep->se_bi, sep->se_server
|
||||
#ifdef IPSEC
|
||||
, (sep->se_policy ? sep->se_policy : "")
|
||||
#endif
|
||||
);
|
||||
}
|
||||
|
||||
#define CPMHSIZE 256
|
||||
@ -1584,7 +1983,13 @@ typedef struct CTime {
|
||||
} CTime;
|
||||
|
||||
typedef struct CHash {
|
||||
struct in_addr ch_Addr;
|
||||
union {
|
||||
struct in_addr c4_Addr;
|
||||
struct in6_addr c6_Addr;
|
||||
} cu_Addr;
|
||||
#define ch_Addr4 cu_Addr.c4_Addr
|
||||
#define ch_Addr6 cu_Addr.c6_Addr
|
||||
int ch_Family;
|
||||
time_t ch_LTime;
|
||||
char *ch_Service;
|
||||
CTime ch_Times[CHTSIZE];
|
||||
@ -1597,8 +2002,8 @@ cpmip(sep, ctrl)
|
||||
struct servtab *sep;
|
||||
int ctrl;
|
||||
{
|
||||
struct sockaddr_in rsin;
|
||||
int rsinLen = sizeof(rsin);
|
||||
struct sockaddr_storage rss;
|
||||
int rssLen = sizeof(rss);
|
||||
int r = 0;
|
||||
|
||||
/*
|
||||
@ -1607,21 +2012,43 @@ cpmip(sep, ctrl)
|
||||
*/
|
||||
|
||||
if (sep->se_maxcpm > 0 &&
|
||||
getpeername(ctrl, (struct sockaddr *)&rsin, &rsinLen) == 0 ) {
|
||||
getpeername(ctrl, (struct sockaddr *)&rss, &rssLen) == 0 ) {
|
||||
time_t t = time(NULL);
|
||||
int hv = 0xABC3D20F;
|
||||
int i;
|
||||
int cnt = 0;
|
||||
CHash *chBest = NULL;
|
||||
unsigned int ticks = t / CHTGRAN;
|
||||
struct sockaddr_in *sin;
|
||||
#ifdef INET6
|
||||
struct sockaddr_in6 *sin6;
|
||||
#endif
|
||||
|
||||
sin = (struct sockaddr_in *)&rss;
|
||||
#ifdef INET6
|
||||
sin6 = (struct sockaddr_in6 *)&rss;
|
||||
#endif
|
||||
{
|
||||
char *p;
|
||||
int i;
|
||||
int i, addrlen;
|
||||
|
||||
for (i = 0, p = (char *)&rsin.sin_addr;
|
||||
i < sizeof(rsin.sin_addr);
|
||||
++i, ++p) {
|
||||
switch (rss.ss_family) {
|
||||
case AF_INET:
|
||||
p = (char *)&sin->sin_addr;
|
||||
addrlen = sizeof(struct in_addr);
|
||||
break;
|
||||
#ifdef INET6
|
||||
case AF_INET6:
|
||||
p = (char *)&sin6->sin6_addr;
|
||||
addrlen = sizeof(struct in6_addr);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
/* should not happen */
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (i = 0; i < addrlen; ++i, ++p) {
|
||||
hv = (hv << 5) ^ (hv >> 23) ^ *p;
|
||||
}
|
||||
hv = (hv ^ (hv >> 16));
|
||||
@ -1629,26 +2056,57 @@ cpmip(sep, ctrl)
|
||||
for (i = 0; i < 5; ++i) {
|
||||
CHash *ch = &CHashAry[(hv + i) & CPMHMASK];
|
||||
|
||||
if (rsin.sin_addr.s_addr == ch->ch_Addr.s_addr &&
|
||||
if (rss.ss_family == AF_INET &&
|
||||
ch->ch_Family == AF_INET &&
|
||||
sin->sin_addr.s_addr == ch->ch_Addr4.s_addr &&
|
||||
ch->ch_Service && strcmp(sep->se_service,
|
||||
ch->ch_Service) == 0) {
|
||||
chBest = ch;
|
||||
break;
|
||||
}
|
||||
#ifdef INET6
|
||||
if (rss.ss_family == AF_INET6 &&
|
||||
ch->ch_Family == AF_INET6 &&
|
||||
IN6_ARE_ADDR_EQUAL(&sin6->sin6_addr,
|
||||
&ch->ch_Addr6) != 0 &&
|
||||
ch->ch_Service && strcmp(sep->se_service,
|
||||
ch->ch_Service) == 0) {
|
||||
chBest = ch;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
if (chBest == NULL || ch->ch_LTime == 0 ||
|
||||
ch->ch_LTime < chBest->ch_LTime) {
|
||||
chBest = ch;
|
||||
}
|
||||
}
|
||||
if (rsin.sin_addr.s_addr != chBest->ch_Addr.s_addr ||
|
||||
if ((rss.ss_family == AF_INET &&
|
||||
(chBest->ch_Family != AF_INET ||
|
||||
sin->sin_addr.s_addr != chBest->ch_Addr4.s_addr)) ||
|
||||
chBest->ch_Service == NULL ||
|
||||
strcmp(sep->se_service, chBest->ch_Service) != 0) {
|
||||
chBest->ch_Addr = rsin.sin_addr;
|
||||
chBest->ch_Family = sin->sin_family;
|
||||
chBest->ch_Addr4 = sin->sin_addr;
|
||||
if (chBest->ch_Service)
|
||||
free(chBest->ch_Service);
|
||||
chBest->ch_Service = strdup(sep->se_service);
|
||||
bzero(chBest->ch_Times, sizeof(chBest->ch_Times));
|
||||
}
|
||||
#ifdef INET6
|
||||
if ((rss.ss_family == AF_INET6 &&
|
||||
(chBest->ch_Family != AF_INET6 ||
|
||||
IN6_ARE_ADDR_EQUAL(&sin6->sin6_addr,
|
||||
&chBest->ch_Addr6) == 0)) ||
|
||||
chBest->ch_Service == NULL ||
|
||||
strcmp(sep->se_service, chBest->ch_Service) != 0) {
|
||||
chBest->ch_Family = sin6->sin6_family;
|
||||
chBest->ch_Addr6 = sin6->sin6_addr;
|
||||
if (chBest->ch_Service)
|
||||
free(chBest->ch_Service);
|
||||
chBest->ch_Service = strdup(sep->se_service);
|
||||
bzero(chBest->ch_Times, sizeof(chBest->ch_Times));
|
||||
}
|
||||
#endif
|
||||
chBest->ch_LTime = t;
|
||||
{
|
||||
CTime *ct = &chBest->ch_Times[ticks % CHTSIZE];
|
||||
@ -1666,10 +2124,16 @@ cpmip(sep, ctrl)
|
||||
}
|
||||
}
|
||||
if (cnt * (CHTSIZE * CHTGRAN) / 60 > sep->se_maxcpm) {
|
||||
char pname[INET6_ADDRSTRLEN];
|
||||
|
||||
getnameinfo((struct sockaddr *)&rss,
|
||||
((struct sockaddr *)&rss)->sa_len,
|
||||
pname, sizeof(pname), NULL, 0,
|
||||
NI_NUMERICHOST|NI_WITHSCOPEID);
|
||||
r = -1;
|
||||
syslog(LOG_ERR,
|
||||
"%s from %s exceeded counts/min (limit %d/min)",
|
||||
sep->se_service, inet_ntoa(rsin.sin_addr),
|
||||
sep->se_service, pname,
|
||||
sep->se_maxcpm);
|
||||
}
|
||||
}
|
||||
|
@ -47,6 +47,7 @@
|
||||
#define MUX_TYPE 1
|
||||
#define MUXPLUS_TYPE 2
|
||||
#define TTCP_TYPE 3
|
||||
#define FAITH_TYPE 4
|
||||
#define ISMUX(sep) (((sep)->se_type == MUX_TYPE) || \
|
||||
((sep)->se_type == MUXPLUS_TYPE))
|
||||
#define ISMUXPLUS(sep) ((sep)->se_type == MUXPLUS_TYPE)
|
||||
@ -55,6 +56,7 @@
|
||||
struct servtab {
|
||||
char *se_service; /* name of service */
|
||||
int se_socktype; /* type of socket to use */
|
||||
int se_family; /* address family */
|
||||
char *se_proto; /* protocol used */
|
||||
int se_maxchild; /* max number of children */
|
||||
int se_maxcpm; /* max connects per IP per minute */
|
||||
@ -70,8 +72,19 @@ struct servtab {
|
||||
char *se_server_name; /* server program without path */
|
||||
#define MAXARGV 20
|
||||
char *se_argv[MAXARGV+1]; /* program arguments */
|
||||
#ifdef IPSEC
|
||||
char *se_policy; /* IPsec poilcy string */
|
||||
#endif
|
||||
int se_fd; /* open descriptor */
|
||||
struct sockaddr_in se_ctrladdr;/* bound address */
|
||||
union { /* bound address */
|
||||
struct sockaddr se_un_ctrladdr;
|
||||
struct sockaddr_in se_un_ctrladdr4;
|
||||
struct sockaddr_in6 se_un_ctrladdr6;
|
||||
} se_un;
|
||||
#define se_ctrladdr se_un.se_un_ctrladdr
|
||||
#define se_ctrladdr4 se_un.se_un_ctrladdr4
|
||||
#define se_ctrladdr6 se_un.se_un_ctrladdr6
|
||||
int se_ctrladdr_size;
|
||||
u_char se_type; /* type: normal, mux, or mux+ */
|
||||
u_char se_checked; /* looked at during merge */
|
||||
u_char se_accept; /* i.e., wait/nowait mode */
|
||||
@ -82,8 +95,17 @@ struct servtab {
|
||||
int se_count; /* number started since se_time */
|
||||
struct timeval se_time; /* start of se_count */
|
||||
struct servtab *se_next;
|
||||
struct se_flags {
|
||||
u_int se_nomapped : 1;
|
||||
u_int se_ctladdrinitok : 1;
|
||||
u_int se_reset : 1;
|
||||
} se_flags;
|
||||
};
|
||||
|
||||
#define se_nomapped se_flags.se_nomapped
|
||||
#define se_ctladdrinitok se_flags.se_ctladdrinitok
|
||||
#define se_reset se_flags.se_reset
|
||||
|
||||
void chargen_dg __P((int, struct servtab *));
|
||||
void chargen_stream __P((int, struct servtab *));
|
||||
void close_sep __P((struct servtab *));
|
||||
@ -117,6 +139,9 @@ void flag_retry __P((int));
|
||||
void retry __P((void));
|
||||
int setconfig __P((void));
|
||||
void setup __P((struct servtab *));
|
||||
#ifdef IPSEC
|
||||
void ipsecsetup __P((struct servtab *));
|
||||
#endif
|
||||
char *sskip __P((char **));
|
||||
char *skip __P((char **));
|
||||
struct servtab *tcpmux __P((int));
|
||||
|
Loading…
Reference in New Issue
Block a user