Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 15 Oct 2000 13:16:56 +0300 (EEST)
From:      netch@segfault.kiev.ua (Valentin Nechayev)
To:        FreeBSD-gnats-submit@freebsd.org
Subject:   misc/21998: ident only for outgoing connections
Message-ID:  <200010151016.e9FAGun01111@nn.kiev.ua>

next in thread | raw e-mail | index | archive | help

>Number:         21998
>Category:       misc
>Synopsis:       ident only for outgoing connections
>Confidential:   no
>Severity:       serious
>Priority:       low
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Sun Oct 15 03:20:01 PDT 2000
>Closed-Date:
>Last-Modified:
>Originator:     netch@netch.kiev.ua (Valentin Nechayev)
>Release:        FreeBSD 5.0(13)-CURRENT-20001014 i386
>Organization:
private
>Environment:

>Description:

The bugfeature of identd is known (since 1996): anyone can connect to production
service on host running identd and query owner of remote side socket. This
can be used by bad guy to find objects to attack; i.e. nmap scanner uses it.

>How-To-Repeat:
>Fix:

diff -rNu src.orig/sys/kern/uipc_socket2.c src/sys/kern/uipc_socket2.c
--- src.orig/sys/kern/uipc_socket2.c	Fri Sep  8 22:21:49 2000
+++ src/sys/kern/uipc_socket2.c	Sun Oct 15 12:50:55 2000
@@ -235,7 +235,7 @@
 	so->so_type = head->so_type;
 	so->so_options = head->so_options &~ SO_ACCEPTCONN;
 	so->so_linger = head->so_linger;
-	so->so_state = head->so_state | SS_NOFDREF;
+	so->so_state = head->so_state | SS_NOFDREF | SS_ISACCEPTED;
 	so->so_proto = head->so_proto;
 	so->so_timeo = head->so_timeo;
 	so->so_cred = p ? p->p_ucred : head->so_cred;
diff -rNu src.orig/sys/netinet/tcp_subr.c src/sys/netinet/tcp_subr.c
--- src.orig/sys/netinet/tcp_subr.c	Sat Sep 30 21:44:07 2000
+++ src/sys/netinet/tcp_subr.c	Sun Oct 15 12:49:48 2000
@@ -872,7 +872,9 @@
 	    tcp_pcblist, "S,xtcpcb", "List of active TCP connections");
 
 static int
-tcp_getcred(SYSCTL_HANDLER_ARGS)
+tcp_getcred_common(req, all)
+	struct sysctl_req *req;
+	int all;
 {
 	struct sockaddr_in addrs[2];
 	struct inpcb *inp;
@@ -891,18 +893,41 @@
 		error = ENOENT;
 		goto out;
 	}
+	if (!all && (inp->inp_socket->so_state & SS_ISACCEPTED)) {
+		error = EPERM;
+		goto out;
+	}
 	error = SYSCTL_OUT(req, inp->inp_socket->so_cred, sizeof(struct ucred));
 out:
 	splx(s);
 	return (error);
 }
 
+static int
+tcp_getcred_outgoing(SYSCTL_HANDLER_ARGS)
+{
+	return tcp_getcred_common(req, 0);
+}
+
+SYSCTL_PROC(_net_inet_tcp, OID_AUTO, getcred_outgoing,
+    CTLTYPE_OPAQUE|CTLFLAG_RW,
+    0, 0, tcp_getcred_outgoing, "S,ucred",
+    "Get the ucred of a TCP connection (outgoing connections only)");
+
+static int
+tcp_getcred_any(SYSCTL_HANDLER_ARGS)
+{
+	return tcp_getcred_common(req, 1);
+}
+
 SYSCTL_PROC(_net_inet_tcp, OID_AUTO, getcred, CTLTYPE_OPAQUE|CTLFLAG_RW,
-    0, 0, tcp_getcred, "S,ucred", "Get the ucred of a TCP connection");
+    0, 0, tcp_getcred_any, "S,ucred", "Get the ucred of a TCP connection");
 
 #ifdef INET6
 static int
-tcp6_getcred(SYSCTL_HANDLER_ARGS)
+tcp6_getcred_common(req, all)
+	struct sysctl_req *req;
+	int all;
 {
 	struct sockaddr_in6 addrs[2];
 	struct inpcb *inp;
@@ -937,6 +962,10 @@
 		error = ENOENT;
 		goto out;
 	}
+	if (!all && (inp->inp_socket->so_state & SS_ISACCEPTED)) {
+		error = EPERM;
+		goto out;
+	}
 	error = SYSCTL_OUT(req, inp->inp_socket->so_cred, 
 			   sizeof(struct ucred));
 out:
@@ -944,9 +973,27 @@
 	return (error);
 }
 
+static int
+tcp6_getcred_outgoing(SYSCTL_HANDLER_ARGS)
+{
+	return tcp6_getcred_common(req, 0);
+}
+
+SYSCTL_PROC(_net_inet6_tcp6, OID_AUTO, getcred_outgoing,
+	    CTLTYPE_OPAQUE|CTLFLAG_RW,
+	    0, 0,
+	    tcp6_getcred_outgoing, "S,ucred",
+	    "Get the ucred of a TCP6 connection (outgoing only)");
+
+static int
+tcp6_getcred_any(SYSCTL_HANDLER_ARGS)
+{
+	return tcp6_getcred_common(req, 1);
+}
+
 SYSCTL_PROC(_net_inet6_tcp6, OID_AUTO, getcred, CTLTYPE_OPAQUE|CTLFLAG_RW,
 	    0, 0,
-	    tcp6_getcred, "S,ucred", "Get the ucred of a TCP6 connection");
+	    tcp6_getcred_any, "S,ucred", "Get the ucred of a TCP6 connection");
 #endif
 
 
diff -rNu src.orig/sys/sys/socketvar.h src/sys/sys/socketvar.h
--- src.orig/sys/sys/socketvar.h	Fri Sep  8 22:22:38 2000
+++ src/sys/sys/socketvar.h	Sun Oct 15 12:49:17 2000
@@ -131,6 +131,7 @@
 #define	SS_CANTSENDMORE		0x0010	/* can't send more data to peer */
 #define	SS_CANTRCVMORE		0x0020	/* can't receive more data from peer */
 #define	SS_RCVATMARK		0x0040	/* at mark on input */
+#define	SS_ISACCEPTED		0x0080	/* obtained from accept() */
 
 #define	SS_NBIO			0x0100	/* non-blocking ops */
 #define	SS_ASYNC		0x0200	/* async i/o notify */
diff -rNu src.orig/usr.sbin/inetd/builtins.c src/usr.sbin/inetd/builtins.c
--- src.orig/usr.sbin/inetd/builtins.c	Sun Oct 15 00:44:36 2000
+++ src/usr.sbin/inetd/builtins.c	Sun Oct 15 12:59:11 2000
@@ -352,6 +352,7 @@
 	ssize_t ssize;
 	size_t size, bufsiz;
 	int c, fflag = 0, nflag = 0, rflag = 0, argc = 0, usedfallback = 0;
+	int getcred_all = 0;
 	int gflag = 0, getcredfail = 0, onreadlen;
 	u_short lport, fport;
 
@@ -374,8 +375,11 @@
 		size_t i;
 		u_int32_t random;
 
-		while ((c = getopt(argc, sep->se_argv, "d:fgno:rt:")) != -1)
+		while ((c = getopt(argc, sep->se_argv, "ad:fgno:rt:")) != -1)
 			switch (c) {
+			case 'a':
+				getcred_all = 1;
+				break;
 			case 'd':
 				fallback = optarg;
 				break;
@@ -526,7 +530,9 @@
 		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, &size, sin,
+		if (sysctlbyname(getcred_all ? "net.inet.tcp.getcred" :
+					"net.inet.tcp.getcred_outgoing",
+				&uc, &size, sin,
 				 sizeof(sin)) == -1)
 			getcredfail = 1;
 		break;
@@ -536,7 +542,9 @@
 		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, &size, sin6,
+		if (sysctlbyname(getcred_all ? "net.inet6.tcp6.getcred" :
+					"net.inet6.tcp6.getcred_outgoing",
+				&uc, &size, sin6,
 				 sizeof(sin6)) == -1)
 			getcredfail = 1;
 		break;
diff -rNu src.orig/usr.sbin/inetd/inetd.8 src/usr.sbin/inetd/inetd.8
--- src.orig/usr.sbin/inetd/inetd.8	Sun Aug 13 00:46:18 2000
+++ src/usr.sbin/inetd/inetd.8	Sun Oct 15 13:09:15 2000
@@ -438,6 +438,9 @@
 .Dq ERROR\ : HIDDEN-USER .
 The available arguments to this service that alter its behavior are:
 .Bl -tag -width indent
+.It Fl a
+Provide owner information for any connection, not only outgoing. By default,
+ident does not provide information for incoming connections.
 .It Fl d Ar fallback
 Provide a
 .Ar fallback

>Release-Note:
>Audit-Trail:
>Unformatted:


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-bugs" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200010151016.e9FAGun01111>