From d067a90a1c9473d216429143d8c6588a4d6e235d Mon Sep 17 00:00:00 2001 From: wollman Date: Wed, 21 Dec 1994 19:08:45 +0000 Subject: Disable UDP service looping attack. --- usr.sbin/inetd/inetd.8 | 16 ++++++---- usr.sbin/inetd/inetd.c | 80 +++++++++++++++++++++++++++++++++++++++----------- 2 files changed, 73 insertions(+), 23 deletions(-) diff --git a/usr.sbin/inetd/inetd.8 b/usr.sbin/inetd/inetd.8 index cfb8b86..6edd3bb 100644 --- a/usr.sbin/inetd/inetd.8 +++ b/usr.sbin/inetd/inetd.8 @@ -30,7 +30,7 @@ .\" SUCH DAMAGE. .\" .\" from: @(#)inetd.8 8.3 (Berkeley) 4/13/94 -.\" $Id$ +.\" $Id: inetd.8,v 1.3 1994/09/11 11:16:30 csgr Exp $ .\" .Dd April 13, 1994 .Dt INETD 8 @@ -295,12 +295,16 @@ routines within itself. These services are .Dq daytime (human readable time), and .Dq time -(machine readable time, -in the form of the number of seconds since midnight, January -1, 1900). All of these services are tcp based. For -details of these services, consult the appropriate +(machine readable time, in the form of the number of seconds since +midnight, January 1, 1900). All of these services are available in +both TCP and UDP versions; the UDP versions will refuse service if the +request specifies a reply port corresponding to any internal service. +(This is done as a defense against looping attacks; the remote IP address +is logged.) +For details of these services, consult the +appropriate .Tn RFC -from the Network Information Center. +document. .Pp When given the .Fl l diff --git a/usr.sbin/inetd/inetd.c b/usr.sbin/inetd/inetd.c index e3e79c6..70a41f4 100644 --- a/usr.sbin/inetd/inetd.c +++ b/usr.sbin/inetd/inetd.c @@ -39,7 +39,8 @@ static char copyright[] = #ifndef lint /* from: @(#)inetd.c 8.4 (Berkeley) 4/13/94"; */ -static char RCSid[] = "$Id"; +static char inetd_c_rcsid[] = + "$Id$"; #endif /* not lint */ /* @@ -1084,6 +1085,28 @@ echo_stream(s, sep) /* Echo service -- echo data back */ exit(0); } +int check_loop(sin, sep) + struct sockaddr_in *sin; + struct servtab *sep; +{ + struct servtab *se2; + + 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; + } + } + return 0; +} + /* ARGSUSED */ void echo_dg(s, sep) /* Echo service -- echo data back */ @@ -1092,12 +1115,18 @@ echo_dg(s, sep) /* Echo service -- echo data back */ { char buffer[BUFSIZE]; int i, size; - struct sockaddr sa; + struct sockaddr_in sin; - size = sizeof(sa); - if ((i = recvfrom(s, buffer, sizeof(buffer), 0, &sa, &size)) < 0) + size = sizeof(sin); + if ((i = recvfrom(s, buffer, sizeof(buffer), 0, + (struct sockaddr *)&sin, &size)) < 0) return; - (void) sendto(s, buffer, i, 0, &sa, sizeof(sa)); + + if (check_loop(&sin, sep)) + return; + + (void) sendto(s, buffer, i, 0, (struct sockaddr *)&sin, + sizeof(sin)); } /* ARGSUSED */ @@ -1186,7 +1215,7 @@ chargen_dg(s, sep) /* Character generator */ int s; struct servtab *sep; { - struct sockaddr sa; + struct sockaddr_in sin; static char *rs; int len, size; char text[LINESIZ+2]; @@ -1196,8 +1225,12 @@ chargen_dg(s, sep) /* Character generator */ rs = ring; } - size = sizeof(sa); - if (recvfrom(s, text, sizeof(text), 0, &sa, &size) < 0) + size = sizeof(sin); + if (recvfrom(s, text, sizeof(text), 0, + (struct sockaddr *)&sin, &size) < 0) + return; + + if (check_loop(&sin, sep)) return; if ((len = endring - rs) >= LINESIZ) @@ -1210,7 +1243,8 @@ chargen_dg(s, sep) /* Character generator */ rs = ring; text[LINESIZ] = '\r'; text[LINESIZ + 1] = '\n'; - (void) sendto(s, text, sizeof(text), 0, &sa, sizeof(sa)); + (void) sendto(s, text, sizeof(text), 0, + (struct sockaddr *)&sin, sizeof(sin)); } /* @@ -1255,14 +1289,20 @@ machtime_dg(s, sep) struct servtab *sep; { long result; - struct sockaddr sa; + struct sockaddr_in sin; int size; - size = sizeof(sa); - if (recvfrom(s, (char *)&result, sizeof(result), 0, &sa, &size) < 0) + size = sizeof(sin); + if (recvfrom(s, (char *)&result, sizeof(result), 0, + (struct sockaddr *)&sin, &size) < 0) + return; + + if (check_loop(&sin, sep)) return; + result = machtime(); - (void) sendto(s, (char *) &result, sizeof(result), 0, &sa, sizeof(sa)); + (void) sendto(s, (char *) &result, sizeof(result), 0, + (struct sockaddr *)&sin, sizeof(sin)); } /* ARGSUSED */ @@ -1288,16 +1328,22 @@ daytime_dg(s, sep) /* Return human-readable time of day */ { char buffer[256]; time_t clock; - struct sockaddr sa; + struct sockaddr_in sin; int size; clock = time((time_t *) 0); - size = sizeof(sa); - if (recvfrom(s, buffer, sizeof(buffer), 0, &sa, &size) < 0) + size = sizeof(sin); + if (recvfrom(s, buffer, sizeof(buffer), 0, + (struct sockaddr *)&sin, &size) < 0) return; + + if (check_loop(&sin, sep)) + return; + (void) sprintf(buffer, "%.24s\r\n", ctime(&clock)); - (void) sendto(s, buffer, strlen(buffer), 0, &sa, sizeof(sa)); + (void) sendto(s, buffer, strlen(buffer), 0, + (struct sockaddr *)&sin, sizeof(sin)); } /* -- cgit v1.1