Skip to content

Commit

Permalink
Prevent cross-site forgery attacks on ftpd(8) due to splitting
Browse files Browse the repository at this point in the history
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
  • Loading branch information
cperciva committed Dec 23, 2008
1 parent d31572b commit f0b40b1
Show file tree
Hide file tree
Showing 4 changed files with 34 additions and 8 deletions.
2 changes: 1 addition & 1 deletion libexec/ftpd/extern.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 *);
Expand Down
28 changes: 22 additions & 6 deletions libexec/ftpd/ftpcmd.y
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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';
Expand Down Expand Up @@ -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) {
Expand All @@ -1270,7 +1281,7 @@ got_eof:
syslog(LOG_DEBUG, "command: %.*s", len, s);
}
}
return (s);
return (0);
}

static void
Expand Down Expand Up @@ -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
Expand Down
7 changes: 6 additions & 1 deletion libexec/ftpd/ftpd.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
5 changes: 5 additions & 0 deletions sys/kern/uipc_domain.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down

0 comments on commit f0b40b1

Please sign in to comment.