From: mike Date: Tue, 11 Feb 2003 16:23:55 +0000 (+0000) Subject: Make httpGets() non-blocking so that a client can't send a partial HTTP X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=aa73fd191a84e87bae2c22cc7f31a45cc7dbc629;p=thirdparty%2Fcups.git Make httpGets() non-blocking so that a client can't send a partial HTTP 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 --- diff --git a/CHANGES.txt b/CHANGES.txt index 4215731eff..a6aa1347c0 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -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 diff --git a/cups/http.c b/cups/http.c index 04a0dd40d2..797f9d3eba 100644 --- a/cups/http.c +++ b/cups/http.c @@ -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 #include +#include #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 $". */ diff --git a/cups/http.h b/cups/http.h index 9e481f989c..56a680eba4 100644 --- a/cups/http.h +++ b/cups/http.h @@ -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 $". */ diff --git a/cups/ipp.c b/cups/ipp.c index 7fe67d0d1b..3497d69931 100644 --- a/cups/ipp.c +++ b/cups/ipp.c @@ -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 $". */ diff --git a/scheduler/client.c b/scheduler/client.c index 97b3974efa..26ee88f978 100644 --- a/scheduler/client.c +++ b/scheduler/client.c @@ -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 $". */