Sophie

Sophie

distrib > Mandriva > 2007.0 > x86_64 > by-pkgid > bc717b9e96f4070e178e261ab5007579 > files > 15

cups-1.2.4-1.8mdv2007.0.src.rpm

diff -durN cups-1.2.4.CVE-2007-0720/cups/http.c cups-1.2.4/cups/http.c
--- cups-1.2.4.CVE-2007-0720/cups/http.c	2007-03-14 12:07:26.000000000 +0000
+++ cups-1.2.4/cups/http.c	2007-03-14 12:09:06.000000000 +0000
@@ -25,6 +25,7 @@
  *
  * Contents:
  *
+ *   _httpBIOMethods()    - Get the OpenSSL BIO methods for HTTP connections.
  *   httpBlocking()       - Set blocking/non-blocking behavior on a connection.
  *   httpCheck()          - Check to see if there is a pending response from
  *                          the server.
@@ -60,7 +61,8 @@
  *   httpPut()            - Send a PUT request to the server.
  *   httpRead()           - Read data from a HTTP connection.
  *   httpRead2()          - Read data from a HTTP connection.
- *   _httpReadCDSA()      - Read function for CDSA decryption code.
+ *   _httpReadCDSA()      - Read function for the CDSA library.
+ *   _httpReadGNUTLS()    - Read function for the GNU TLS library.
  *   httpReconnect()      - Reconnect to a HTTP server...
  *   httpSetCookie()      - Set the cookie value(s)...
  *   httpSetExpect()      - Set the Expect: header in a request.
@@ -71,7 +73,14 @@
  *   httpWait()           - Wait for data available on a connection.
  *   httpWrite()          - Write data to a HTTP connection.
  *   httpWrite2()         - Write data to a HTTP connection.
- *   _httpWriteCDSA()     - Write function for CDSA encryption code.
+ *   _httpWriteCDSA()     - Write function for the CDSA library.
+ *   _httpWriteGNUTLS()   - Write function for the GNU TLS library.
+ *   http_bio_ctrl()      - Control the HTTP connection.
+ *   http_bio_free()      - Free OpenSSL data.
+ *   http_bio_new()       - Initialize an OpenSSL BIO structure.
+ *   http_bio_puts()      - Send a string for OpenSSL.
+ *   http_bio_read()      - Read data for OpenSSL.
+ *   http_bio_write()     - Write data for OpenSSL.
  *   http_field()         - Return the field index for a field name.
  *   http_read_ssl()      - Read from a SSL/TLS connection.
  *   http_send()          - Send a request with all fields and the trailing
@@ -118,7 +127,7 @@
 static http_field_t	http_field(const char *name);
 static int		http_send(http_t *http, http_state_t request,
 			          const char *uri);
-static int		http_wait(http_t *http, int msec);
+static int		http_wait(http_t *http, int msec, int usessl);
 static int		http_write(http_t *http, const char *buffer,
 			           int length);
 static int		http_write_chunk(http_t *http, const char *buffer,
@@ -168,6 +177,45 @@
 			};
 
 
+#if defined(HAVE_SSL) && defined(HAVE_LIBSSL)
+/*
+ * BIO methods for OpenSSL...
+ */
+
+static int		http_bio_write(BIO *h, const char *buf, int num);
+static int		http_bio_read(BIO *h, char *buf, int size);
+static int		http_bio_puts(BIO *h, const char *str);
+static long		http_bio_ctrl(BIO *h, int cmd, long arg1, void *arg2);
+static int		http_bio_new(BIO *h);
+static int		http_bio_free(BIO *data);
+
+static BIO_METHOD	http_bio_methods =
+			{
+			  BIO_TYPE_SOCKET,
+			  "http",
+			  http_bio_write,
+			  http_bio_read,
+			  http_bio_puts,
+			  NULL, /* http_bio_gets, */
+			  http_bio_ctrl,
+			  http_bio_new,
+			  http_bio_free,
+			  NULL,
+			};
+
+
+/*
+ * '_httpBIOMethods()' - Get the OpenSSL BIO methods for HTTP connections.
+ */
+
+BIO_METHOD *				/* O - BIO methods for OpenSSL */
+_httpBIOMethods(void)
+{
+  return (&http_bio_methods);
+}
+#endif /* HAVE_SSL && HAVE_LIBSSL */
+
+
 /*
  * 'httpBlocking()' - Set blocking/non-blocking behavior on a connection.
  */
@@ -869,7 +917,7 @@
       * No newline; see if there is more data to be read...
       */
 
-      if (!http->blocking && !http_wait(http, 10000))
+      if (!http->blocking && !http_wait(http, 10000, 1))
       {
         DEBUG_puts("httpGets: Timed out!");
         http->error = ETIMEDOUT;
@@ -1391,7 +1439,7 @@
 
 #if defined(HAVE_SSL) && defined(HAVE_CDSASSL)
 /*
- * '_httpReadCDSA()' - Read function for CDSA decryption code.
+ * '_httpReadCDSA()' - Read function for the CDSA library.
  */
 
 OSStatus				/* O  - -1 on error, 0 on success */
@@ -1400,19 +1448,36 @@
     void             *data,		/* I  - Data buffer */
     size_t           *dataLength)	/* IO - Number of bytes */
 {
-  OSStatus	  result;		/* Return value */
-  ssize_t	  bytes;		/* Number of bytes read */
-  cdsa_conn_ref_t u;			/* Connection reference union */
+  OSStatus	result;			/* Return value */
+  ssize_t	bytes;			/* Number of bytes read */
+  http_t	*http;			/* HTTP connection */
 
 
-  u.connection = connection;
+  http = (http_t *)connection;
+
+  if (!http->blocking)
+  {
+   /*
+    * Make sure we have data before we read...
+    */
+
+    if (!http_wait(http, 10000, 0))
+    {
+      http->error = ETIMEDOUT;
+      return (-1);
+    }
+  }
 
   do
-    bytes = recv(u.sock, data, *dataLength, 0);
+  {
+    bytes = recv(http->fd, data, *dataLength, 0);
+  }
   while (bytes == -1 && errno == EINTR);
 
   if (bytes == *dataLength)
+  {
     result = 0;
+  }
   else if (bytes > 0)
   {
     *dataLength = bytes;
@@ -1430,11 +1495,45 @@
       result = errSSLClosedAbort;
   }
 
-  return result;
+  return (result);
 }
 #endif /* HAVE_SSL && HAVE_CDSASSL */
 
 
+#if defined(HAVE_SSL) && defined(HAVE_GNUTLS)
+/*
+ * '_httpReadGNUTLS()' - Read function for the GNU TLS library.
+ */
+
+ssize_t					/* O - Number of bytes read or -1 on error */
+_httpReadGNUTLS(
+    gnutls_transport_ptr ptr,		/* I - HTTP connection */
+    void                 *data,		/* I - Buffer */
+    size_t               length)	/* I - Number of bytes to read */
+{
+  http_t	*http;			/* HTTP connection */
+
+
+  http = (http_t *)ptr;
+
+  if (!http->blocking)
+  {
+   /*
+    * Make sure we have data before we read...
+    */
+
+    if (!http_wait(http, 10000, 0))
+    {
+      http->error = ETIMEDOUT;
+      return (-1);
+    }
+  }
+
+  return (recv(http->fd, data, length, 0));
+}
+#endif /* HAVE_SSL && HAVE_GNUTLS */
+
+
 /*
  * 'httpReconnect()' - Reconnect to a HTTP server.
  */
@@ -1830,7 +1929,7 @@
   * If not, check the SSL/TLS buffers and do a select() on the connection...
   */
 
-  return (http_wait(http, msec));
+  return (http_wait(http, msec, 1));
 }
 
 
@@ -1977,7 +2076,7 @@
 
 #if defined(HAVE_SSL) && defined(HAVE_CDSASSL)
 /*
- * '_httpWriteCDSA()' - Write function for CDSA encryption code.
+ * '_httpWriteCDSA()' - Write function for the CDSA library.
  */
 
 OSStatus				/* O  - -1 on error, 0 on success */
@@ -1986,19 +2085,23 @@
     const void       *data,		/* I  - Data buffer */
     size_t           *dataLength)	/* IO - Number of bytes */
 {
-  OSStatus	  result;		/* Return value */
-  ssize_t	  bytes;		/* Number of bytes read */
-  cdsa_conn_ref_t u;			/* Connection reference union */
+  OSStatus	result;			/* Return value */
+  ssize_t	bytes;			/* Number of bytes read */
+  http_t	*http;			/* HTTP connection */
 
 
-  u.connection = connection;
+  http = (http_t *)connection;
 
   do
-    bytes = write(u.sock, data, *dataLength);
+  {
+    bytes = write(http->fd, data, *dataLength);
+  }
   while (bytes == -1 && errno == EINTR);
 
   if (bytes == *dataLength)
+  {
     result = 0;
+  }
   else if (bytes >= 0)
   {
     *dataLength = bytes;
@@ -2014,11 +2117,164 @@
       result = errSSLClosedAbort;
   }
 
-  return result;
+  return (result);
 }
 #endif /* HAVE_SSL && HAVE_CDSASSL */
 
 
+#if defined(HAVE_SSL) && defined(HAVE_GNUTLS)
+/*
+ * '_httpWriteGNUTLS()' - Write function for the GNU TLS library.
+ */
+
+ssize_t					/* O - Number of bytes written or -1 on error */
+_httpWriteGNUTLS(
+    gnutls_transport_ptr ptr,		/* I - HTTP connection */
+    const void           *data,		/* I - Data buffer */
+    size_t               length)	/* I - Number of bytes to write */
+{
+  return (send(((http_t *)ptr)->fd, data, length, 0));
+}
+#endif /* HAVE_SSL && HAVE_GNUTLS */
+
+
+#if defined(HAVE_SSL) && defined(HAVE_LIBSSL)
+/*
+ * 'http_bio_ctrl()' - Control the HTTP connection.
+ */
+
+static long				/* O - Result/data */
+http_bio_ctrl(BIO  *h,			/* I - BIO data */
+              int  cmd,			/* I - Control command */
+	      long arg1,		/* I - First argument */
+	      void *arg2)		/* I - Second argument */
+{
+  switch (cmd)
+  {
+    default :
+        return (0);
+
+    case BIO_CTRL_RESET :
+        h->ptr = NULL;
+	return (0);
+
+    case BIO_C_SET_FILE_PTR :
+        h->ptr  = arg2;
+	h->init = 1;
+	return (1);
+
+    case BIO_C_GET_FILE_PTR :
+        if (arg2)
+	{
+	  *((void **)arg2) = h->ptr;
+	  return (1);
+	}
+	else
+	  return (0);
+        
+    case BIO_CTRL_DUP :
+    case BIO_CTRL_FLUSH :
+        return (1);
+  }
+}
+
+
+/*
+ * 'http_bio_free()' - Free OpenSSL data.
+ */
+
+static int				/* O - 1 on success, 0 on failure */
+http_bio_free(BIO *h)			/* I - BIO data */
+{
+  if (!h)
+    return (0);
+
+  if (h->shutdown)
+  {
+    h->init  = 0;
+    h->flags = 0;
+  }
+
+  return (1);
+}
+
+
+/*
+ * 'http_bio_new()' - Initialize an OpenSSL BIO structure.
+ */
+
+static int				/* O - 1 on success, 0 on failure */
+http_bio_new(BIO *h)			/* I - BIO data */
+{
+  if (!h)
+    return (0);
+
+  h->init  = 0;
+  h->num   = 0;
+  h->ptr   = NULL;
+  h->flags = 0;
+
+  return (1);
+}
+
+
+/*
+ * 'http_bio_puts()' - Send a string for OpenSSL.
+ */
+
+static int				/* O - Bytes written */
+http_bio_puts(BIO        *h,		/* I - BIO data */
+              const char *str)		/* I - String to write */
+{
+  return (send(((http_t *)h->ptr)->fd, str, strlen(str), 0));
+}
+
+
+/*
+ * 'http_bio_read()' - Read data for OpenSSL.
+ */
+
+static int				/* O - Bytes read */
+http_bio_read(BIO  *h,			/* I - BIO data */
+              char *buf,		/* I - Buffer */
+	      int  size)		/* I - Number of bytes to read */
+{
+  http_t	*http;			/* HTTP connection */
+
+
+  http = (http_t *)h->ptr;
+
+  if (!http->blocking)
+  {
+   /*
+    * Make sure we have data before we read...
+    */
+
+    if (!http_wait(http, 10000, 0))
+    {
+      http->error = ETIMEDOUT;
+      return (-1);
+    }
+  }
+
+  return (recv(http->fd, buf, size, 0));
+}
+
+
+/*
+ * 'http_bio_write()' - Write data for OpenSSL.
+ */
+
+static int				/* O - Bytes written */
+http_bio_write(BIO        *h,		/* I - BIO data */
+               const char *buf,		/* I - Buffer to write */
+	       int        num)		/* I - Number of bytes to write */
+{
+  return (send(((http_t *)h->ptr)->fd, buf, num, 0));
+}
+#endif /* HAVE_SSL && HAVE_LIBSSL */
+
+
 /*
  * 'http_field()' - Return the field index for a field name.
  */
@@ -2247,6 +2503,7 @@
 #  ifdef HAVE_LIBSSL
   SSL_CTX	*context;		/* Context for encryption */
   SSL		*conn;			/* Connection for encryption */
+  BIO		*bio;			/* BIO data */
 #  elif defined(HAVE_GNUTLS)
   http_tls_t	*conn;			/* TLS session object */
   gnutls_certificate_client_credentials *credentials;
@@ -2254,7 +2511,6 @@
 #  elif defined(HAVE_CDSASSL)
   OSStatus	error;			/* Error code */
   http_tls_t	*conn;			/* CDSA connection information */
-  cdsa_conn_ref_t u;			/* Connection reference union */
 #  endif /* HAVE_LIBSSL */
 
 
@@ -2265,9 +2521,12 @@
 
   SSL_CTX_set_options(context, SSL_OP_NO_SSLv2); /* Only use SSLv3 or TLS */
 
+  bio = BIO_new(_httpBIOMethods());
+  BIO_ctrl(bio, BIO_C_SET_FILE_PTR, 0, (char *)http);
+
   conn = SSL_new(context);
+  SSL_set_bio(conn, bio, bio);
 
-  SSL_set_fd(conn, http->fd);
   if (SSL_connect(conn) != 1)
   {
 #    ifdef DEBUG
@@ -2316,8 +2575,9 @@
   gnutls_init(&(conn->session), GNUTLS_CLIENT);
   gnutls_set_default_priority(conn->session);
   gnutls_credentials_set(conn->session, GNUTLS_CRD_CERTIFICATE, *credentials);
-  gnutls_transport_set_ptr(conn->session,
-                           (gnutls_transport_ptr)((long)http->fd));
+  gnutls_transport_set_ptr(conn->session, (gnutls_transport_ptr)http);
+  gnutls_transport_set_pull_function(conn->session, _httpReadGNUTLS);
+  gnutls_transport_set_push_function(conn->session, _httpWriteGNUTLS);
 
   if ((gnutls_handshake(conn->session)) != GNUTLS_E_SUCCESS)
   {
@@ -2348,9 +2608,7 @@
   * Use a union to resolve warnings about int/pointer size mismatches...
   */
 
-  u.connection = NULL;
-  u.sock       = http->fd;
-  error        = SSLSetConnection(conn->session, u.connection);
+  error = SSLSetConnection(conn->session, http);
 
   if (!error)
     error = SSLSetIOFuncs(conn->session, _httpReadCDSA, _httpWriteCDSA);
@@ -2544,7 +2802,8 @@
 
 static int				/* O - 1 if data is available, 0 otherwise */
 http_wait(http_t *http,			/* I - HTTP connection */
-          int    msec)			/* I - Milliseconds to wait */
+          int    msec,			/* I - Milliseconds to wait */
+	  int    usessl)		/* I - Use SSL context? */
 {
 #ifndef WIN32
   struct rlimit		limit;          /* Runtime limit */
@@ -2564,7 +2823,7 @@
   */
 
 #ifdef HAVE_SSL
-  if (http->tls)
+  if (http->tls && usessl)
   {
 #  ifdef HAVE_LIBSSL
     if (SSL_pending((SSL *)(http->tls)))
diff -durN cups-1.2.4.CVE-2007-0720/cups/http-private.h cups-1.2.4/cups/http-private.h
--- cups-1.2.4.CVE-2007-0720/cups/http-private.h	2006-05-10 19:57:46.000000000 +0100
+++ cups-1.2.4/cups/http-private.h	2007-03-14 12:09:06.000000000 +0000
@@ -70,7 +70,8 @@
 #  if defined HAVE_LIBSSL
 /*
  * The OpenSSL library provides its own SSL/TLS context structure for its
- * IO and protocol management...
+ * IO and protocol management.  However, we need to provide our own BIO
+ * (basic IO) implementation to do timeouts...
  */
 
 #    include <openssl/err.h>
@@ -79,6 +80,8 @@
 
 typedef SSL http_tls_t;
 
+extern BIO_METHOD *_httpBIOMethods(void);
+
 #  elif defined HAVE_GNUTLS
 /*
  * The GNU TLS library is more of a "bare metal" SSL/TLS library...
@@ -91,6 +94,11 @@
   void			*credentials;	/* GNU TLS credentials object */
 } http_tls_t;
 
+extern ssize_t	_httpReadGNUTLS(gnutls_transport_ptr ptr, void *data,
+		                size_t length);
+extern ssize_t	_httpWriteGNUTLS(gnutls_transport_ptr ptr, const void *data,
+		                 size_t length);
+
 #  elif defined(HAVE_CDSASSL)
 /*
  * Darwin's Security framework provides its own SSL/TLS context structure
@@ -105,15 +113,6 @@
   CFArrayRef		certsArray;	/* Certificates array */
 } http_tls_t;
 
-typedef union _cdsa_conn_ref_u		/**** CDSA Connection reference union
-					 **** used to resolve 64-bit casting
-					 **** warnings.
-					 ****/
-{
-  SSLConnectionRef connection;		/* SSL connection pointer */
-  int		   sock;		/* Socket */
-} cdsa_conn_ref_t;
-
 extern OSStatus	_httpReadCDSA(SSLConnectionRef connection, void *data,
 		              size_t *dataLength);
 extern OSStatus	_httpWriteCDSA(SSLConnectionRef connection, const void *data,
diff -durN cups-1.2.4.CVE-2007-0720/scheduler/client.c cups-1.2.4/scheduler/client.c
--- cups-1.2.4.CVE-2007-0720/scheduler/client.c	2007-03-14 12:07:26.000000000 +0000
+++ cups-1.2.4/scheduler/client.c	2007-03-14 12:09:06.000000000 +0000
@@ -488,7 +488,8 @@
 
     con->http.encryption = HTTP_ENCRYPT_ALWAYS;
 
-    encrypt_client(con);
+    if (!encrypt_client(con))
+      cupsdCloseClient(con);
   }
   else
     con->auto_ssl = 1;
@@ -814,7 +815,9 @@
                       "cupsdReadClient: Saw first byte %02X, auto-negotiating SSL/TLS session...",
                       buf[0] & 255);
 
-      encrypt_client(con);
+      if (!encrypt_client(con))
+        return (cupsdCloseClient(con));
+
       return (1);
     }
   }
@@ -1113,7 +1116,8 @@
 	if (cupsdFlushHeader(con) < 0)
 	  return (cupsdCloseClient(con));
 
-        encrypt_client(con);
+        if (!encrypt_client(con))
+	  return (cupsdCloseClient(con));
 #else
 	if (!cupsdSendError(con, HTTP_NOT_IMPLEMENTED))
 	  return (cupsdCloseClient(con));
@@ -1160,7 +1164,8 @@
 	if (cupsdFlushHeader(con) < 0)
 	  return (cupsdCloseClient(con));
 
-        encrypt_client(con);
+        if (!encrypt_client(con))
+	  return (cupsdCloseClient(con));
 #else
 	if (!cupsdSendError(con, HTTP_NOT_IMPLEMENTED))
 	  return (cupsdCloseClient(con));
@@ -2701,6 +2706,7 @@
 #  ifdef HAVE_LIBSSL
   SSL_CTX	*context;		/* Context for encryption */
   SSL		*conn;			/* Connection for encryption */
+  BIO		*bio;			/* BIO data */
   unsigned long	error;			/* Error code */
 
 
@@ -2728,9 +2734,12 @@
   SSL_CTX_use_PrivateKey_file(context, ServerKey, SSL_FILETYPE_PEM);
   SSL_CTX_use_certificate_file(context, ServerCertificate, SSL_FILETYPE_PEM);
 
+  bio = BIO_new(_httpBIOMethods());
+  BIO_ctrl(bio, BIO_C_SET_FILE_PTR, 0, (char *)HTTP(con));
+
   conn = SSL_new(context);
+  SSL_set_bio(conn, bio, bio);
 
-  SSL_set_fd(conn, con->http.fd);
   if (SSL_accept(conn) != 1)
   {
     cupsdLogMessage(CUPSD_LOG_ERROR,
@@ -2803,8 +2812,9 @@
   gnutls_init(&(conn->session), GNUTLS_SERVER);
   gnutls_set_default_priority(conn->session);
   gnutls_credentials_set(conn->session, GNUTLS_CRD_CERTIFICATE, *credentials);
-  gnutls_transport_set_ptr(conn->session,
-                           (gnutls_transport_ptr)((long)con->http.fd));
+  gnutls_transport_set_ptr(conn->session, (gnutls_transport_ptr)HTTP(con));
+  gnutls_transport_set_pull_function(conn->session, _httpReadGNUTLS);
+  gnutls_transport_set_push_function(conn->session, _httpWriteGNUTLS);
 
   error = gnutls_handshake(conn->session);
 
@@ -2834,7 +2844,6 @@
 #  elif defined(HAVE_CDSASSL)
   OSStatus	error;			/* Error code */
   http_tls_t	*conn;			/* CDSA connection information */
-  cdsa_conn_ref_t u;			/* Connection reference union */
 
 
   if ((conn = (http_tls_t *)malloc(sizeof(http_tls_t))) == NULL)
@@ -2857,7 +2866,7 @@
   if (!conn->certsArray)
   {
     cupsdLogMessage(CUPSD_LOG_ERROR,
-        	    "EncryptClient: Could not find signing key in keychain "
+        	    "encrypt_client: Could not find signing key in keychain "
 		    "\"%s\"", ServerCertificate);
     error = errSSLBadCert; /* errSSLBadConfiguration is a better choice, but not available on 10.2.x */
   }
@@ -2872,15 +2881,7 @@
     error = SSLSetProtocolVersionEnabled(conn->session, kSSLProtocol2, false);
 
   if (!error)
-  {
-   /*
-    * Use a union to resolve warnings about int/pointer size mismatches...
-    */
-
-    u.connection = NULL;
-    u.sock       = con->http.fd;
-    error        = SSLSetConnection(conn->session, u.connection);
-  }
+    error = SSLSetConnection(conn->session, HTTP(con));
 
   if (!error)
     error = SSLSetAllowsExpiredCerts(conn->session, true);