svn commit: r186405 - head/libexec/ftpd head/sys/kern releng/6.3 releng/6.3/libexec/ftpd releng/6.3/sys/conf releng/6.3/sys/kern releng/6.4 releng/6.4/libexec/ftpd releng/6.4/sys/conf releng/6.4/sy...

Colin Percival cperciva at FreeBSD.org
Tue Dec 23 01:23:10 UTC 2008


Author: cperciva
Date: Tue Dec 23 01:23:09 2008
New Revision: 186405
URL: http://svn.freebsd.org/changeset/base/186405

Log:
  Prevent cross-site forgery attacks on ftpd(8) due to splitting
  long commands into multiple requests. [08:12]
  
  Avoid calling uninitialized function pointers in protocol switch
  code. [08:13]
  
  Merry Christmas everybody...
  
  Approved by:	so (cperciva)
  Approved by:	re (kensmith)
  Security:	FreeBSD-SA-08:12.ftpd, FreeBSD-SA-08:13.protosw

Modified:
  head/libexec/ftpd/extern.h
  head/libexec/ftpd/ftpcmd.y
  head/libexec/ftpd/ftpd.c
  head/sys/kern/uipc_domain.c

Changes in other areas also in this revision:
Modified:
  releng/6.3/UPDATING
  releng/6.3/libexec/ftpd/extern.h
  releng/6.3/libexec/ftpd/ftpcmd.y
  releng/6.3/libexec/ftpd/ftpd.c
  releng/6.3/sys/conf/newvers.sh
  releng/6.3/sys/kern/uipc_domain.c
  releng/6.4/UPDATING
  releng/6.4/libexec/ftpd/extern.h
  releng/6.4/libexec/ftpd/ftpcmd.y
  releng/6.4/libexec/ftpd/ftpd.c
  releng/6.4/sys/conf/newvers.sh
  releng/6.4/sys/kern/uipc_domain.c
  releng/7.0/UPDATING
  releng/7.0/libexec/ftpd/extern.h
  releng/7.0/libexec/ftpd/ftpcmd.y
  releng/7.0/libexec/ftpd/ftpd.c
  releng/7.0/sys/conf/newvers.sh
  releng/7.0/sys/kern/uipc_domain.c
  releng/7.1/UPDATING
  releng/7.1/libexec/ftpd/extern.h
  releng/7.1/libexec/ftpd/ftpcmd.y
  releng/7.1/libexec/ftpd/ftpd.c
  releng/7.1/sys/kern/uipc_domain.c
  stable/6/libexec/ftpd/extern.h
  stable/6/libexec/ftpd/ftpcmd.y
  stable/6/libexec/ftpd/ftpd.c
  stable/6/sys/kern/uipc_domain.c
  stable/7/libexec/ftpd/extern.h
  stable/7/libexec/ftpd/ftpcmd.y
  stable/7/libexec/ftpd/ftpd.c
  stable/7/sys/kern/uipc_domain.c

Modified: head/libexec/ftpd/extern.h
==============================================================================
--- head/libexec/ftpd/extern.h	Tue Dec 23 01:22:57 2008	(r186404)
+++ head/libexec/ftpd/extern.h	Tue Dec 23 01:23:09 2008	(r186405)
@@ -46,7 +46,7 @@ void	fatalerror(char *);
 void    ftpd_logwtmp(char *, char *, struct sockaddr *addr);
 int	ftpd_pclose(FILE *);
 FILE   *ftpd_popen(char *, char *);
-char   *getline(char *, int, FILE *);
+int	getline(char *, int, FILE *);
 void	lreply(int, const char *, ...) __printflike(2, 3);
 void	makedir(char *);
 void	nack(char *);

Modified: head/libexec/ftpd/ftpcmd.y
==============================================================================
--- head/libexec/ftpd/ftpcmd.y	Tue Dec 23 01:22:57 2008	(r186404)
+++ head/libexec/ftpd/ftpcmd.y	Tue Dec 23 01:23:09 2008	(r186405)
@@ -1191,7 +1191,7 @@ lookup(struct tab *p, char *cmd)
 /*
  * getline - a hacked up version of fgets to ignore TELNET escape codes.
  */
-char *
+int
 getline(char *s, int n, FILE *iop)
 {
 	int c;
@@ -1207,7 +1207,7 @@ getline(char *s, int n, FILE *iop)
 			if (ftpdebug)
 				syslog(LOG_DEBUG, "command: %s", s);
 			tmpline[0] = '\0';
-			return(s);
+			return(0);
 		}
 		if (c == 0)
 			tmpline[0] = '\0';
@@ -1244,13 +1244,24 @@ getline(char *s, int n, FILE *iop)
 			}
 		}
 		*cs++ = c;
-		if (--n <= 0 || c == '\n')
+		if (--n <= 0) {
+			/*
+			 * If command doesn't fit into buffer, discard the
+			 * rest of the command and indicate truncation.
+			 * This prevents the command to be split up into
+			 * multiple commands.
+			 */
+			while (c != '\n' && (c = getc(iop)) != EOF)
+				;
+			return (-2);
+		}
+		if (c == '\n')
 			break;
 	}
 got_eof:
 	sigprocmask(SIG_SETMASK, &osset, NULL);
 	if (c == EOF && cs == s)
-		return (NULL);
+		return (-1);
 	*cs++ = '\0';
 	if (ftpdebug) {
 		if (!guest && strncasecmp("pass ", s, 5) == 0) {
@@ -1270,7 +1281,7 @@ got_eof:
 			syslog(LOG_DEBUG, "command: %.*s", len, s);
 		}
 	}
-	return (s);
+	return (0);
 }
 
 static void
@@ -1300,9 +1311,14 @@ yylex(void)
 		case CMD:
 			(void) signal(SIGALRM, toolong);
 			(void) alarm(timeout);
-			if (getline(cbuf, sizeof(cbuf)-1, stdin) == NULL) {
+			n = getline(cbuf, sizeof(cbuf)-1, stdin);
+			if (n == -1) {
 				reply(221, "You could at least say goodbye.");
 				dologout(0);
+			} else if (n == -2) {
+				reply(500, "Command too long.");
+				(void) alarm(0);
+				continue;
 			}
 			(void) alarm(0);
 #ifdef SETPROCTITLE

Modified: head/libexec/ftpd/ftpd.c
==============================================================================
--- head/libexec/ftpd/ftpd.c	Tue Dec 23 01:22:57 2008	(r186404)
+++ head/libexec/ftpd/ftpd.c	Tue Dec 23 01:23:09 2008	(r186405)
@@ -2794,15 +2794,20 @@ static int
 myoob(void)
 {
 	char *cp;
+	int ret;
 
 	if (!transflag) {
 		syslog(LOG_ERR, "Internal: myoob() while no transfer");
 		return (0);
 	}
 	cp = tmpline;
-	if (getline(cp, 7, stdin) == NULL) {
+	ret = getline(cp, 7, stdin);
+	if (ret == -1) {
 		reply(221, "You could at least say goodbye.");
 		dologout(0);
+	} else if (ret == -2) {
+		/* Ignore truncated command. */
+		return (0);
 	}
 	upper(cp);
 	if (strcmp(cp, "ABOR\r\n") == 0) {

Modified: head/sys/kern/uipc_domain.c
==============================================================================
--- head/sys/kern/uipc_domain.c	Tue Dec 23 01:22:57 2008	(r186404)
+++ head/sys/kern/uipc_domain.c	Tue Dec 23 01:23:09 2008	(r186405)
@@ -112,13 +112,18 @@ protosw_init(struct protosw *pr)
 
 #define DEFAULT(foo, bar)	if ((foo) == NULL)  (foo) = (bar)
 	DEFAULT(pu->pru_accept, pru_accept_notsupp);
+	DEFAULT(pu->pru_bind, pru_bind_notsupp);
 	DEFAULT(pu->pru_connect, pru_connect_notsupp);
 	DEFAULT(pu->pru_connect2, pru_connect2_notsupp);
 	DEFAULT(pu->pru_control, pru_control_notsupp);
+	DEFAULT(pu->pru_disconnect, pru_disconnect_notsupp);
 	DEFAULT(pu->pru_listen, pru_listen_notsupp);
+	DEFAULT(pu->pru_peeraddr, pru_peeraddr_notsupp);
 	DEFAULT(pu->pru_rcvd, pru_rcvd_notsupp);
 	DEFAULT(pu->pru_rcvoob, pru_rcvoob_notsupp);
 	DEFAULT(pu->pru_sense, pru_sense_null);
+	DEFAULT(pu->pru_shutdown, pru_shutdown_notsupp);
+	DEFAULT(pu->pru_sockaddr, pru_sockaddr_notsupp);
 	DEFAULT(pu->pru_sosend, sosend_generic);
 	DEFAULT(pu->pru_soreceive, soreceive_generic);
 	DEFAULT(pu->pru_sopoll, sopoll_generic);


More information about the svn-src-head mailing list