Subject: bin/34658: [dM] identd truncates queries to first segment
To: None <gnats-admin@netbsd.org, netbsd-bugs@netbsd.org>
From: der Mouse <mouse@Rodents.Montreal.QC.CA>
List: netbsd-bugs
Date: 09/29/2006 07:10:00
>Number: 34658
>Category: bin
>Synopsis: [dM] identd truncates queries to first segment
>Confidential: no
>Severity: serious
>Priority: low
>Responsible: bin-bug-people
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Fri Sep 29 07:10:00 +0000 2006
>Originator: der Mouse
>Release: NetBSD 4.99.1, i386 snapshot of 09-06 or shortly before
>Organization:
Dis-
>Environment:
NetBSD-current/i386, but any using Peter Postma's identd, at
least as of identd.c,v 1.29.
>Description:
identd does not read the entire query before responding, unless
it all happens to come in fast enough to get returned by a
single recv() (which basically means, all in a single packet).
This leads to corrupted queries if the sender is slow.
>How-To-Repeat:
Send a query other than all at once. For example, here's a
query that works, because it's all sent at once:
% echo 22,51851^M | nc 10.0.1.22 113
22,51851:USERID:UNIX:root
whereas here's one that doesn't:
% (echo -n 22, ; sleep 1 ; echo 51851^M) | nc 10.0.1.22 113
0,0:ERROR:INVALID-PORT
(the response comes back before the sleep finishes,
demonstrating even more clearly that identd isn't waiting).
>Fix:
This is relative to identd.c,v 1.29.
--- identd.c.orig 2006-09-29 03:03:09.000000000 -0400
+++ identd.c 2006-09-29 03:03:15.000000000 -0400
@@ -325,6 +325,7 @@
socklen_t len;
uid_t uid;
ssize_t n;
+ ssize_t qlen;
lport = fport = 0;
@@ -352,14 +353,25 @@
}
/* Receive data from the client. */
- if ((n = recv(fd, buf, sizeof(buf) - 1, 0)) < 0) {
- fatal("recv");
- } else if (n == 0) {
- maybe_syslog(LOG_NOTICE, "recv: EOF");
- iderror(fd, 0, 0, "UNKNOWN-ERROR");
- return 1;
+ qlen = 0;
+ while (1) {
+ if ((n = recv(fd, &buf[qlen], sizeof(buf)-qlen, 0)) < 0) {
+ fatal("recv");
+ } else if (n == 0) {
+ maybe_syslog(LOG_NOTICE, "recv: EOF");
+ iderror(fd, 0, 0, "UNKNOWN-ERROR");
+ return 1;
+ }
+ /* 1413 is not clear on what to do if data follows the first
+ CRLF before we respond. We do not consider the query
+ complete until we get a CRLF _at the end of the buffer_. */
+ qlen += n;
+ if ( (qlen >= 2) &&
+ (buf[qlen-2] == '\r') &&
+ (buf[qlen-1] == '\n') )
+ break;
}
- buf[n] = '\0';
+ buf[qlen-2] = '\0';
/* Get local and remote ports from the received data. */
p = buf;
/~\ The ASCII der Mouse
\ / Ribbon Campaign
X Against HTML mouse@rodents.montreal.qc.ca
/ \ Email! 7D C8 61 52 5D E7 2D 39 4E F1 31 3E E8 B3 27 4B