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:
  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

Changes in other areas also in this revision:
Modified:
  head/libexec/ftpd/extern.h
  head/libexec/ftpd/ftpcmd.y
  head/libexec/ftpd/ftpd.c
  head/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: releng/6.3/UPDATING
==============================================================================
--- releng/6.3/UPDATING Tue Dec 23 01:22:57 2008        (r186404)
+++ releng/6.3/UPDATING Tue Dec 23 01:23:09 2008        (r186405)
@@ -8,6 +8,13 @@ Items affecting the ports and packages s
 /usr/ports/UPDATING.  Please read that file before running
 portupgrade.
 
+20081223:      p7      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]
+
 20081124:      p6      FreeBSD-SA-08:11.arc4random
        Make sure arc4random(9) is properly seeded when /etc/rc.d/initrandom
        returns.

Modified: releng/6.3/libexec/ftpd/extern.h
==============================================================================
--- releng/6.3/libexec/ftpd/extern.h    Tue Dec 23 01:22:57 2008        
(r186404)
+++ releng/6.3/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: releng/6.3/libexec/ftpd/ftpcmd.y
==============================================================================
--- releng/6.3/libexec/ftpd/ftpcmd.y    Tue Dec 23 01:22:57 2008        
(r186404)
+++ releng/6.3/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: releng/6.3/libexec/ftpd/ftpd.c
==============================================================================
--- releng/6.3/libexec/ftpd/ftpd.c      Tue Dec 23 01:22:57 2008        
(r186404)
+++ releng/6.3/libexec/ftpd/ftpd.c      Tue Dec 23 01:23:09 2008        
(r186405)
@@ -2802,15 +2802,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: releng/6.3/sys/conf/newvers.sh
==============================================================================
--- releng/6.3/sys/conf/newvers.sh      Tue Dec 23 01:22:57 2008        
(r186404)
+++ releng/6.3/sys/conf/newvers.sh      Tue Dec 23 01:23:09 2008        
(r186405)
@@ -32,7 +32,7 @@
 
 TYPE="FreeBSD"
 REVISION="6.3"
-BRANCH="RELEASE-p6"
+BRANCH="RELEASE-p7"
 if [ "X${BRANCH_OVERRIDE}" != "X" ]; then
        BRANCH=${BRANCH_OVERRIDE}
 fi

Modified: releng/6.3/sys/kern/uipc_domain.c
==============================================================================
--- releng/6.3/sys/kern/uipc_domain.c   Tue Dec 23 01:22:57 2008        
(r186404)
+++ releng/6.3/sys/kern/uipc_domain.c   Tue Dec 23 01:23:09 2008        
(r186405)
@@ -115,13 +115,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);
        DEFAULT(pu->pru_soreceive, soreceive);
        DEFAULT(pu->pru_sopoll, sopoll);

Modified: releng/6.4/UPDATING
==============================================================================
--- releng/6.4/UPDATING Tue Dec 23 01:22:57 2008        (r186404)
+++ releng/6.4/UPDATING Tue Dec 23 01:23:09 2008        (r186405)
@@ -8,6 +8,13 @@ Items affecting the ports and packages s
 /usr/ports/UPDATING.  Please read that file before running
 portupgrade.
 
+20081223:      p1      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]
+
 20081128:
        FreeBSD 6.4-RELEASE
 

Modified: releng/6.4/libexec/ftpd/extern.h
==============================================================================
--- releng/6.4/libexec/ftpd/extern.h    Tue Dec 23 01:22:57 2008        
(r186404)
+++ releng/6.4/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: releng/6.4/libexec/ftpd/ftpcmd.y
==============================================================================
--- releng/6.4/libexec/ftpd/ftpcmd.y    Tue Dec 23 01:22:57 2008        
(r186404)
+++ releng/6.4/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: releng/6.4/libexec/ftpd/ftpd.c
==============================================================================
--- releng/6.4/libexec/ftpd/ftpd.c      Tue Dec 23 01:22:57 2008        
(r186404)
+++ releng/6.4/libexec/ftpd/ftpd.c      Tue Dec 23 01:23:09 2008        
(r186405)
@@ -2802,15 +2802,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: releng/6.4/sys/conf/newvers.sh
==============================================================================
--- releng/6.4/sys/conf/newvers.sh      Tue Dec 23 01:22:57 2008        
(r186404)
+++ releng/6.4/sys/conf/newvers.sh      Tue Dec 23 01:23:09 2008        
(r186405)
@@ -32,7 +32,7 @@
 
 TYPE="FreeBSD"
 REVISION="6.4"
-BRANCH="RELEASE"
+BRANCH="RELEASE-p1"
 if [ "X${BRANCH_OVERRIDE}" != "X" ]; then
        BRANCH=${BRANCH_OVERRIDE}
 fi

Modified: releng/6.4/sys/kern/uipc_domain.c
==============================================================================
--- releng/6.4/sys/kern/uipc_domain.c   Tue Dec 23 01:22:57 2008        
(r186404)
+++ releng/6.4/sys/kern/uipc_domain.c   Tue Dec 23 01:23:09 2008        
(r186405)
@@ -115,13 +115,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);
        DEFAULT(pu->pru_soreceive, soreceive);
        DEFAULT(pu->pru_sopoll, sopoll);

Modified: releng/7.0/UPDATING
==============================================================================
--- releng/7.0/UPDATING Tue Dec 23 01:22:57 2008        (r186404)
+++ releng/7.0/UPDATING Tue Dec 23 01:23:09 2008        (r186405)
@@ -8,6 +8,13 @@ Items affecting the ports and packages s
 /usr/ports/UPDATING.  Please read that file before running
 portupgrade.
 
+20081223:      p7      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]
+
 20081124:      p6      FreeBSD-SA-08:11.arc4random
        Make sure arc4random(9) is properly seeded when /etc/rc.d/initrandom
        returns.

Modified: releng/7.0/libexec/ftpd/extern.h
==============================================================================
--- releng/7.0/libexec/ftpd/extern.h    Tue Dec 23 01:22:57 2008        
(r186404)
+++ releng/7.0/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: releng/7.0/libexec/ftpd/ftpcmd.y
==============================================================================
--- releng/7.0/libexec/ftpd/ftpcmd.y    Tue Dec 23 01:22:57 2008        
(r186404)
+++ releng/7.0/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: releng/7.0/libexec/ftpd/ftpd.c
==============================================================================
--- releng/7.0/libexec/ftpd/ftpd.c      Tue Dec 23 01:22:57 2008        
(r186404)
+++ releng/7.0/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: releng/7.0/sys/conf/newvers.sh
==============================================================================
--- releng/7.0/sys/conf/newvers.sh      Tue Dec 23 01:22:57 2008        
(r186404)
+++ releng/7.0/sys/conf/newvers.sh      Tue Dec 23 01:23:09 2008        
(r186405)
@@ -32,7 +32,7 @@
 
 TYPE="FreeBSD"
 REVISION="7.0"
-BRANCH="RELEASE-p6"
+BRANCH="RELEASE-p7"
 if [ "X${BRANCH_OVERRIDE}" != "X" ]; then
        BRANCH=${BRANCH_OVERRIDE}
 fi

Modified: releng/7.0/sys/kern/uipc_domain.c
==============================================================================
--- releng/7.0/sys/kern/uipc_domain.c   Tue Dec 23 01:22:57 2008        
(r186404)
+++ releng/7.0/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);

Modified: releng/7.1/UPDATING
==============================================================================
--- releng/7.1/UPDATING Tue Dec 23 01:22:57 2008        (r186404)
+++ releng/7.1/UPDATING Tue Dec 23 01:23:09 2008        (r186405)
@@ -8,6 +8,13 @@ Items affecting the ports and packages s
 /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.
 

Modified: releng/7.1/libexec/ftpd/extern.h
==============================================================================
--- releng/7.1/libexec/ftpd/extern.h    Tue Dec 23 01:22:57 2008        
(r186404)
+++ releng/7.1/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: releng/7.1/libexec/ftpd/ftpcmd.y
==============================================================================
--- releng/7.1/libexec/ftpd/ftpcmd.y    Tue Dec 23 01:22:57 2008        
(r186404)
+++ releng/7.1/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: releng/7.1/libexec/ftpd/ftpd.c
==============================================================================
--- releng/7.1/libexec/ftpd/ftpd.c      Tue Dec 23 01:22:57 2008        
(r186404)
+++ releng/7.1/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: releng/7.1/sys/kern/uipc_domain.c
==============================================================================
--- releng/7.1/sys/kern/uipc_domain.c   Tue Dec 23 01:22:57 2008        
(r186404)
+++ releng/7.1/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);
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to