]> git.ipfire.org Git - thirdparty/cups.git/commitdiff
Make httpGets() non-blocking so that a client can't send a partial HTTP
authormike <mike@7a7537e8-13f0-0310-91df-b6672ffda945>
Tue, 11 Feb 2003 16:23:55 +0000 (16:23 +0000)
committermike <mike@7a7537e8-13f0-0310-91df-b6672ffda945>
Tue, 11 Feb 2003 16:23:55 +0000 (16:23 +0000)
chunk and cause a DoS of the scheduler.

git-svn-id: svn+ssh://src.apple.com/svn/cups/cups.org/trunk@3335 7a7537e8-13f0-0310-91df-b6672ffda945

CHANGES.txt
cups/http.c
cups/http.h
cups/ipp.c
scheduler/client.c

index 4215731effda7adce1117158c5e65603242b95d2..a6aa1347c0deff4ba0e1c8969da54994ec3c5fe4 100644 (file)
@@ -1,17 +1,21 @@
-CHANGES.txt - 02/10/2003
+CHANGES.txt - 02/11/2003
 ------------------------
 
 CHANGES IN CUPS V1.1.19
 
+       - Added a new httpWait() function to support waiting for
+         data for a specific number of milliseconds.
+       - httpGets() now times out after 1 second on
+         non-blocking HTTP connections.
        - The scheduler no longer accepts rangeOfInteger values
          that are out of order (e.g. 5-1)
        - The sides attribute was incorrectly sent as a name
          value; it is a keyword value.
        - The IPP backend now detects if the destination queue
          has gone away and reports an error.
-       - The scheduler now allocates its select() sets to
-         support larger numbers of clients on systems that
-         support it.
+       - The scheduler and HTTP API now allocate their select()
+         sets to support larger numbers of clients on systems
+         that support it.
        - The scheduler now sets the CFProcessPath environment
          variable under MacOS X.
        - The cupsLangDefault() function now uses the
index 04a0dd40d2a7172325e06f3e33f57980d538ed91..797f9d3eba0b662e92fbc58b18992dd287d4883a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * "$Id: http.c,v 1.111 2003/01/24 20:39:40 mike Exp $"
+ * "$Id: http.c,v 1.112 2003/02/11 16:23:53 mike Exp $"
  *
  *   HTTP routines for the Common UNIX Printing System (CUPS).
  *
@@ -45,6 +45,7 @@
  *   httpTrace()          - Send an TRACE request to the server.
  *   httpFlush()          - Flush data from a HTTP connection.
  *   httpRead()           - Read data from a HTTP connection.
+ *   httpWait()           - Wait for data available on a connection.
  *   httpWrite()          - Write data to a HTTP connection.
  *   httpGets()           - Get a line of text from a HTTP connection.
  *   httpPrintf()         - Print a formatted string to a HTTP connection.
@@ -78,6 +79,7 @@
 #include "string.h"
 #include <fcntl.h>
 #include <errno.h>
+#include <sys/resource.h>
 
 #include "http.h"
 #include "http-private.h"
@@ -254,31 +256,7 @@ httpInitialize(void)
 int                            /* O - 0 = no data, 1 = data available */
 httpCheck(http_t *http)                /* I - HTTP connection */
 {
-  fd_set       input;          /* Input set for select() */
-  struct timeval timeout;      /* Timeout */
-
-
- /*
-  * First see if there is data in the buffer...
-  */
-
-  if (http == NULL)
-    return (0);
-
-  if (http->used)
-    return (1);
-
- /*
-  * Then try doing a select() to poll the socket...
-  */
-
-  FD_ZERO(&input);
-  FD_SET(http->fd, &input);
-
-  timeout.tv_sec  = 0;
-  timeout.tv_usec = 0;
-
-  return (select(http->fd + 1, &input, NULL, NULL, &timeout) > 0);
+  return (httpWait(http, 0));
 }
 
 
@@ -292,6 +270,9 @@ httpClose(http_t *http)             /* I - Connection to close */
   if (!http)
     return;
 
+  if (http->input_set)
+    free(http->input_set);
+
 #ifdef HAVE_SSL
   if (http->tls)
     http_shutdown_ssl(http);
@@ -1031,6 +1012,61 @@ httpRead(http_t *http,                   /* I - HTTP data */
 }
 
 
+/*
+ * 'httpWait()' - Wait for data available on a connection.
+ */
+
+int                                    /* O - 1 if data is available, 0 otherwise */
+httpWait(http_t *http,                 /* I - HTTP data */
+         int    msec)                  /* I - Milliseconds to wait */
+{
+  struct rlimit                limit;          /* Runtime limit */
+  struct timeval       timeout;        /* Timeout */
+
+
+ /*
+  * First see if there is data in the buffer...
+  */
+
+  if (http == NULL)
+    return (0);
+
+  if (http->used)
+    return (1);
+
+ /*
+  * Then try doing a select() to poll the socket...
+  */
+
+  if (!http->input_set)
+  {
+   /*
+    * Allocate the select() input set based upon the max number of file
+    * descriptors available for this process...
+    */
+
+    getrlimit(RLIMIT_NOFILE, &limit);
+
+    http->input_set = calloc(1, (limit.rlim_cur + 7) / 8);
+
+    if (!http->input_set)
+      return (0);
+  }
+
+  FD_SET(http->fd, http->input_set);
+
+  if (msec >= 0)
+  {
+    timeout.tv_sec  = msec / 1000;
+    timeout.tv_usec = (msec % 1000) * 1000;
+
+    return (select(http->fd + 1, http->input_set, NULL, NULL, &timeout) > 0);
+  }
+  else
+    return (select(http->fd + 1, http->input_set, NULL, NULL, NULL) > 0);
+}
+
+
 /*
  * 'httpWrite()' - Write data to a HTTP connection.
  */
@@ -1218,6 +1254,9 @@ httpGets(char   *line,                    /* I - Line to read into */
       * No newline; see if there is more data to be read...
       */
 
+      if (!http->blocking && !httpWait(http, 1000))
+        return (NULL);
+
 #ifdef HAVE_SSL
       if (http->tls)
        bytes = http_read_ssl(http, bufend, HTTP_MAX_BUFFER - http->used);
@@ -2231,5 +2270,5 @@ CDSAWriteFunc(SSLConnectionRef connection,        /* I  - SSL/TLS connection */
 
 
 /*
- * End of "$Id: http.c,v 1.111 2003/01/24 20:39:40 mike Exp $".
+ * End of "$Id: http.c,v 1.112 2003/02/11 16:23:53 mike Exp $".
  */
index 9e481f989c4942f0bbaba63d6094403281df954e..56a680eba462e5e2d101ab9e5f2c1fd6acdfd7ff 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * "$Id: http.h,v 1.43 2003/01/10 19:05:49 swdev Exp $"
+ * "$Id: http.h,v 1.44 2003/02/11 16:23:53 mike Exp $"
  *
  *   Hyper-Text Transport Protocol definitions for the Common UNIX Printing
  *   System (CUPS).
@@ -281,6 +281,7 @@ typedef struct
   int                  nonce_count;    /* Nonce count */
   void                 *tls;           /* TLS state information */
   http_encryption_t    encryption;     /* Encryption requirements */
+  fd_set               *input_set;     /* select() set for httpWait() */
 } http_t;
 
 
@@ -328,6 +329,7 @@ extern void         httpSetField(http_t *http, http_field_t field,
 extern const char      *httpStatus(http_status_t status);
 extern int             httpTrace(http_t *http, const char *uri);
 extern http_status_t   httpUpdate(http_t *http);
+extern int             httpWait(http_t *http, int msec);
 extern int             httpWrite(http_t *http, const char *buffer, int length);
 extern char            *httpEncode64(char *out, const char *in);
 extern char            *httpDecode64(char *out, const char *in);
@@ -349,5 +351,5 @@ extern char         *httpMD5String(const md5_byte_t *, char [33]);
 #endif /* !_CUPS_HTTP_H_ */
 
 /*
- * End of "$Id: http.h,v 1.43 2003/01/10 19:05:49 swdev Exp $".
+ * End of "$Id: http.h,v 1.44 2003/02/11 16:23:53 mike Exp $".
  */
index 7fe67d0d1b7ce52397532171fdef50d3b3b2e4dd..3497d69931c1d236ef10bb5ac48f09427824d971 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * "$Id: ipp.c,v 1.83 2003/01/28 21:43:29 mike Exp $"
+ * "$Id: ipp.c,v 1.84 2003/02/11 16:23:53 mike Exp $"
  *
  *   Internet Printing Protocol object functions for the Common UNIX
  *   Printing System (CUPS).
@@ -2004,8 +2004,6 @@ ipp_read(http_t        *http,     /* I - Client connection */
   int          tbytes,         /* Total bytes read */
                bytes;          /* Bytes read this pass */
   char         len[32];        /* Length string */
-  fd_set       input;          /* Input set for select() */
-  struct timeval timeout;      /* Timeout */
 
 
  /*
@@ -2053,26 +2051,10 @@ ipp_read(http_t        *http,   /* I - Client connection */
     else
     {
      /*
-      * Try doing a select() to poll the socket for data, waiting a
-      * maximum of 1 second...
+      * Wait a maximum of 1 second for data...
       */
 
-      FD_ZERO(&input);
-      FD_SET(http->fd, &input);
-
-      timeout.tv_sec  = 1;
-      timeout.tv_usec = 0;
-
-      if (select(http->fd + 1, &input, NULL, NULL, &timeout) < 1)
-      {
-       /*
-        * Signal no data...
-       */
-
-        bytes = -1;
-       break;
-      }
-      else if (!FD_ISSET(http->fd, &input))
+      if (!httpWait(http, 1000))
       {
        /*
         * Signal no data...
@@ -2098,5 +2080,5 @@ ipp_read(http_t        *http,     /* I - Client connection */
 
 
 /*
- * End of "$Id: ipp.c,v 1.83 2003/01/28 21:43:29 mike Exp $".
+ * End of "$Id: ipp.c,v 1.84 2003/02/11 16:23:53 mike Exp $".
  */
index 97b3974efa833f512ea0c5fc1118991bdfcf35d7..26ee88f978605b21134240a5fedf891617874c65 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * "$Id: client.c,v 1.143 2003/02/05 21:10:15 mike Exp $"
+ * "$Id: client.c,v 1.144 2003/02/11 16:23:55 mike Exp $"
  *
  *   Client routines for the Common UNIX Printing System (CUPS) scheduler.
  *
@@ -282,11 +282,15 @@ AcceptClient(listener_t *lis)     /* I - Listener socket */
   setsockopt(con->http.fd, IPPROTO_TCP, TCP_NODELAY, &val, sizeof(val)); 
 
  /*
-  * Add the socket to the select() input mask.
+  * Close this file on all execs...
   */
 
   fcntl(con->http.fd, F_SETFD, fcntl(con->http.fd, F_GETFD) | FD_CLOEXEC);
 
+ /*
+  * Add the socket to the select() input mask.
+  */
+
   LogMessage(L_DEBUG2, "AcceptClient: Adding fd %d to InputSet...",
              con->http.fd);
   FD_SET(con->http.fd, InputSet);
@@ -353,6 +357,9 @@ CloseClient(client_t *con)  /* I - Client to close */
 
   LogMessage(L_DEBUG, "CloseClient() %d", con->http.fd);
 
+  if (con->http.input_set)
+    free(con->http.input_set);
+
 #ifdef HAVE_SSL
  /*
   * Shutdown encryption as needed...
@@ -2932,5 +2939,5 @@ CDSAWriteFunc(SSLConnectionRef connection,        /* I  - SSL/TLS connection */
 
 
 /*
- * End of "$Id: client.c,v 1.143 2003/02/05 21:10:15 mike Exp $".
+ * End of "$Id: client.c,v 1.144 2003/02/11 16:23:55 mike Exp $".
  */