summaryrefslogtreecommitdiffstats
path: root/lib/libc/net/rcmd.c
diff options
context:
space:
mode:
authorpeter <peter@FreeBSD.org>1996-08-12 14:14:09 +0000
committerpeter <peter@FreeBSD.org>1996-08-12 14:14:09 +0000
commit665b6e261ba076b16c6c02125a104c2297ae5a96 (patch)
treee32121b3f5805b48061ebc9b88fb1f4f2193a7b0 /lib/libc/net/rcmd.c
parent36d45bbacbf50bdee375845c4a955b90e649b036 (diff)
downloadFreeBSD-src-665b6e261ba076b16c6c02125a104c2297ae5a96.zip
FreeBSD-src-665b6e261ba076b16c6c02125a104c2297ae5a96.tar.gz
clear sockaddr_in's on stack before use
set sin_len close one ftp port bounce attack have rresvport() use bindresvport() rather than duplicate the code, rresvport() is a superset of bindresvport(). Obtained from: OpenBSD / Jason Downs / Theo de Raadt, minor tweaks by me.
Diffstat (limited to 'lib/libc/net/rcmd.c')
-rw-r--r--lib/libc/net/rcmd.c54
1 files changed, 28 insertions, 26 deletions
diff --git a/lib/libc/net/rcmd.c b/lib/libc/net/rcmd.c
index 7e396c0..77032e1 100644
--- a/lib/libc/net/rcmd.c
+++ b/lib/libc/net/rcmd.c
@@ -100,9 +100,11 @@ rcmd(ahost, rport, locuser, remuser, cmd, fd2p)
return (-1);
}
fcntl(s, F_SETOWN, pid);
+ bzero(&sin, sizeof sin);
+ sin.sin_len = sizeof(struct sockaddr_in);
sin.sin_family = hp->h_addrtype;
- bcopy(hp->h_addr_list[0], &sin.sin_addr, hp->h_length);
sin.sin_port = rport;
+ bcopy(hp->h_addr_list[0], &sin.sin_addr, hp->h_length);
if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) >= 0)
break;
(void)close(s);
@@ -159,6 +161,7 @@ rcmd(ahost, rport, locuser, remuser, cmd, fd2p)
(void)close(s2);
goto bad;
}
+again:
FD_ZERO(&reads);
FD_SET(s, &reads);
FD_SET(s2, &reads);
@@ -175,6 +178,14 @@ rcmd(ahost, rport, locuser, remuser, cmd, fd2p)
goto bad;
}
s3 = accept(s2, (struct sockaddr *)&from, &len);
+ /*
+ * XXX careful for ftp bounce attacks. If discovered, shut them
+ * down and check for the real auxiliary channel to connect.
+ */
+ if (from.sin_family == AF_INET && from.sin_port == htons(20)) {
+ close(s3);
+ goto again;
+ }
(void)close(s2);
if (s3 < 0) {
(void)fprintf(stderr,
@@ -224,40 +235,31 @@ rresvport(alport)
int *alport;
{
struct sockaddr_in sin;
- int s, on, len;
+ int s;
+ bzero(&sin, sizeof sin);
+ sin.sin_len = sizeof(struct sockaddr_in);
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = INADDR_ANY;
- sin.sin_port = 0;
-
s = socket(AF_INET, SOCK_STREAM, 0);
if (s < 0)
return (-1);
-
- on = IP_PORTRANGE_LOW;
- if (setsockopt(s, IPPROTO_IP, IP_PORTRANGE, (char*)&on, sizeof(on)) < 0)
- {
+#if 0 /* compat_exact_traditional_rresvport_semantics */
+ sin.sin_port = htons((u_short)*alport);
+ if (bind(s, (struct sockaddr *)&sin, sizeof(sin)) >= 0)
+ return (s);
+ if (errno != EADDRINUSE) {
(void)close(s);
- return(-1);
+ return (-1);
}
-
- if (bind(s, (struct sockaddr *)&sin, sizeof(sin)) >= 0) {
- /* attempt to find the port that we were assigned */
- len = sizeof(sin);
- if (getsockname(s, (struct sockaddr *)&sin, &len) >= 0)
- *alport = ntohs(sin.sin_port);
- else {
- (void)close(s);
- return (-1);
- }
-
- return (s);
+#endif
+ sin.sin_port = 0;
+ if (bindresvport(s, &sin) == -1) {
+ (void)close(s);
+ return (-1);
}
- if (errno == EADDRNOTAVAIL) /* no available ports? */
- errno = EAGAIN; /* "official" return for this case */
-
- (void)close(s);
- return (-1);
+ *alport = (int)ntohs(sin.sin_port);
+ return (s);
}
int __check_rhosts_file = 1;
OpenPOWER on IntegriCloud