summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorColin Percival <cperciva@FreeBSD.org>2008-12-23 01:23:09 +0000
committerColin Percival <cperciva@FreeBSD.org>2008-12-23 01:23:09 +0000
commit76acf827a2438600538efe3e83e859ce42c0a0c1 (patch)
tree9cce1a9e9d4523824e2f17b099fa8191d98c1eb0
parentb99e4e1a7e52c1131c8d4184ca8d5fa67191eefd (diff)
downloadsrc-test2-76acf827a2438600538efe3e83e859ce42c0a0c1.tar.gz
src-test2-76acf827a2438600538efe3e83e859ce42c0a0c1.zip
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
Notes
Notes: svn path=/releng/7.1/; revision=186405
-rw-r--r--UPDATING7
-rw-r--r--libexec/ftpd/extern.h2
-rw-r--r--libexec/ftpd/ftpcmd.y28
-rw-r--r--libexec/ftpd/ftpd.c7
-rw-r--r--sys/kern/uipc_domain.c5
5 files changed, 41 insertions, 8 deletions
diff --git a/UPDATING b/UPDATING
index 8d7db8826b97..f08a60f78ac5 100644
--- a/UPDATING
+++ b/UPDATING
@@ -8,6 +8,13 @@ Items affecting the ports and packages system can be found in
/usr/ports/UPDATING. Please read that file before running
portupgrade.
+20081223: FreeBSD-SA-08:12.ftpd, FreeBSD-SA-08:13.protosw
+ 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]
+
20080903:
ntpd has been upgraded to 4.2.4p5.
diff --git a/libexec/ftpd/extern.h b/libexec/ftpd/extern.h
index 7c1cc8edd1db..d869f67371d7 100644
--- a/libexec/ftpd/extern.h
+++ b/libexec/ftpd/extern.h
@@ -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 *);
diff --git a/libexec/ftpd/ftpcmd.y b/libexec/ftpd/ftpcmd.y
index 3c6ecb72d04f..fcef73e6ec3e 100644
--- a/libexec/ftpd/ftpcmd.y
+++ b/libexec/ftpd/ftpcmd.y
@@ -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
diff --git a/libexec/ftpd/ftpd.c b/libexec/ftpd/ftpd.c
index 5095f20435d4..59dc71c89963 100644
--- a/libexec/ftpd/ftpd.c
+++ b/libexec/ftpd/ftpd.c
@@ -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) {
diff --git a/sys/kern/uipc_domain.c b/sys/kern/uipc_domain.c
index 12bee2b836f3..c07429340bb7 100644
--- a/sys/kern/uipc_domain.c
+++ b/sys/kern/uipc_domain.c
@@ -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);