diff options
author | msweet <msweet@a1ca3aef-8c08-0410-bb20-df032aa958be> | 2012-12-12 20:54:21 +0000 |
---|---|---|
committer | msweet <msweet@a1ca3aef-8c08-0410-bb20-df032aa958be> | 2012-12-12 20:54:21 +0000 |
commit | c1420c8744235de1249c34b956b7c11ccafd659d (patch) | |
tree | 27879336dd313e589eb2004964f2af416520daff /cups/http.c | |
parent | c41769ffd04ad45bb2c95691ad3999674896a2ed (diff) |
Merge changes from CUPS 1.7svn-r10755.
git-svn-id: svn+ssh://src.apple.com/svn/cups/easysw/current@4074 a1ca3aef-8c08-0410-bb20-df032aa958be
Diffstat (limited to 'cups/http.c')
-rw-r--r-- | cups/http.c | 231 |
1 files changed, 145 insertions, 86 deletions
diff --git a/cups/http.c b/cups/http.c index d5099b272..12e7338ad 100644 --- a/cups/http.c +++ b/cups/http.c @@ -176,9 +176,9 @@ static int http_write_chunk(http_t *http, const char *buffer, int length); #ifdef HAVE_SSL static int http_read_ssl(http_t *http, char *buf, int len); -# if defined(HAVE_CDSASSL) && defined(HAVE_SECCERTIFICATECOPYDATA) +# ifdef HAVE_CDSASSL static int http_set_credentials(http_t *http); -# endif /* HAVE_CDSASSL ** HAVE_SECCERTIFICATECOPYDATA */ +# endif /* HAVE_CDSASSL */ #endif /* HAVE_SSL */ static off_t http_set_length(http_t *http); static void http_set_timeout(int fd, double timeout); @@ -671,10 +671,10 @@ httpCopyCredentials( { # ifdef HAVE_LIBSSL # elif defined(HAVE_GNUTLS) -# elif defined(HAVE_CDSASSL) && defined(HAVE_SECCERTIFICATECOPYDATA) +# elif defined(HAVE_CDSASSL) OSStatus error; /* Error code */ + SecTrustRef peerTrust; /* Peer trust reference */ CFIndex count; /* Number of credentials */ - CFArrayRef peerCerts; /* Peer certificates */ SecCertificateRef secCert; /* Certificate reference */ CFDataRef data; /* Certificate data */ int i; /* Looping var */ @@ -694,14 +694,16 @@ httpCopyCredentials( # elif defined(HAVE_GNUTLS) return (-1); -# elif defined(HAVE_CDSASSL) && defined(HAVE_SECCERTIFICATECOPYDATA) - if (!(error = SSLCopyPeerCertificates(http->tls, &peerCerts)) && peerCerts) +# elif defined(HAVE_CDSASSL) + if (!(error = SSLCopyPeerTrust(http->tls, &peerTrust)) && peerTrust) { if ((*credentials = cupsArrayNew(NULL, NULL)) != NULL) { - for (i = 0, count = CFArrayGetCount(peerCerts); i < count; i++) + count = SecTrustGetCertificateCount(peerTrust); + + for (i = 0; i < count; i ++) { - secCert = (SecCertificateRef)CFArrayGetValueAtIndex(peerCerts, i); + secCert = SecTrustGetCertificateAtIndex(peerTrust, i); if ((data = SecCertificateCopyData(secCert))) { httpAddCredential(*credentials, CFDataGetBytePtr(data), @@ -711,7 +713,7 @@ httpCopyCredentials( } } - CFRelease(peerCerts); + CFRelease(peerTrust); } return (error); @@ -832,7 +834,7 @@ _httpCreateCredentials( # elif defined(HAVE_GNUTLS) return (NULL); -# elif defined(HAVE_CDSASSL) && defined(HAVE_SECCERTIFICATECOPYDATA) +# elif defined(HAVE_CDSASSL) CFMutableArrayRef peerCerts; /* Peer credentials reference */ SecCertificateRef secCert; /* Certificate reference */ CFDataRef data; /* Credential data reference */ @@ -969,6 +971,13 @@ httpFlush(http_t *http) /* I - Connection to server */ http_states[http->state + 1])); /* + * Nothing to do if we are in the "waiting" state... + */ + + if (http->state == HTTP_STATE_WAITING) + return; + + /* * Temporarily set non-blocking mode so we don't get stuck in httpRead()... */ @@ -1981,7 +1990,9 @@ httpPeek(http_t *http, /* I - Connection to server */ return (0); } - else if (length > (size_t)http->data_remaining) + else if ((http->data_encoding == HTTP_ENCODING_LENGTH || + http->coding == _HTTP_CODING_IDENTITY) && + length > (size_t)http->data_remaining) length = (size_t)http->data_remaining; if (http->used == 0) @@ -2069,6 +2080,47 @@ httpPeek(http_t *http, /* I - Connection to server */ http->used = bytes; } +#ifdef HAVE_LIBZ + if (http->coding) + { + int zerr; /* Decompressor error */ + off_t comp_avail; /* Maximum bytes for decompression */ + z_stream stream; /* Copy of decompressor stream */ + + if (http->used > http->data_remaining) + comp_avail = http->data_remaining; + else + comp_avail = http->used; + + DEBUG_printf(("2httpPeek: length=%d, avail_in=%d", (int)length, + (int)comp_avail)); + + if (inflateCopy(&stream, &(http->stream)) != Z_OK) + { + DEBUG_puts("2httpPeek: Unable to copy decompressor stream."); + http->error = ENOMEM; + return (-1); + } + + stream.next_in = (Bytef *)http->buffer; + stream.avail_in = comp_avail; + stream.next_out = (Bytef *)buffer; + stream.avail_out = length; + + zerr = inflate(&stream, Z_SYNC_FLUSH); + inflateEnd(&stream); + + if (zerr < Z_OK) + { + DEBUG_printf(("2httpPeek: zerr=%d", zerr)); + http->error = EIO; + return (-1); + } + + bytes = length - http->stream.avail_out; + } + else +#endif /* HAVE_LIBZ */ if (http->used > 0) { if (length > (size_t)http->used) @@ -2111,6 +2163,10 @@ httpPeek(http_t *http, /* I - Connection to server */ return (bytes); } +/* For OS X 10.8 and earlier */ +ssize_t _httpPeek(http_t *http, char *buffer, size_t length) +{ return (httpPeek(http, buffer, length)); } + /* * 'httpPost()' - Send a POST request to the server. @@ -3124,6 +3180,56 @@ httpSetCookie(http_t *http, /* I - Connection */ /* + * 'httpSetDefaultField()' - Set the default value of an HTTP header. + * + * Currently only HTTP_FIELD_ACCEPT_ENCODING, HTTP_FIELD_SERVER, and + * HTTP_FIELD_USER_AGENT can be set. + * + * @since CUPS 1.7@ + */ + +void +httpSetDefaultField(http_t *http, /* I - Connection to server */ + http_field_t field, /* I - Field index */ + const char *value)/* I - Value */ +{ + DEBUG_printf(("httpSetDefaultField(http=%p, field=%d(%s), value=\"%s\")", + http, field, http_fields[field], value)); + + if (!http) + return; + + switch (field) + { + case HTTP_FIELD_ACCEPT_ENCODING : + if (http->default_accept_encoding) + _cupsStrFree(http->default_accept_encoding); + + http->default_accept_encoding = value ? _cupsStrAlloc(value) : NULL; + break; + + case HTTP_FIELD_SERVER : + if (http->default_server) + _cupsStrFree(http->default_server); + + http->default_server = value ? _cupsStrAlloc(value) : NULL; + break; + + case HTTP_FIELD_USER_AGENT : + if (http->default_user_agent) + _cupsStrFree(http->default_user_agent); + + http->default_user_agent = value ? _cupsStrAlloc(value) : NULL; + break; + + default : + DEBUG_puts("1httpSetDefaultField: Ignored."); + break; + } +} + + +/* * 'httpSetExpect()' - Set the Expect: header in a request. * * Currently only @code HTTP_STATUS_CONTINUE@ is supported for the "expect" @@ -4061,15 +4167,20 @@ httpWriteResponse(http_t *http, /* I - HTTP connection */ #endif /* HAVE_SSL */ if (!http->server) - httpSetField(http, HTTP_FIELD_SERVER, CUPS_MINIMAL); + httpSetField(http, HTTP_FIELD_SERVER, + http->default_server ? http->default_server : CUPS_MINIMAL); -#ifdef HAVE_LIBZ /* * Set the Accept-Encoding field if it isn't already... */ if (!http->accept_encoding) - httpSetField(http, HTTP_FIELD_ACCEPT_ENCODING, "gzip, deflate, identity"); + httpSetField(http, HTTP_FIELD_ACCEPT_ENCODING, + http->default_accept_encoding ? http->default_accept_encoding : +#ifdef HAVE_LIBZ + "gzip, deflate, identity"); +#else + "identity"); #endif /* HAVE_LIBZ */ /* @@ -4681,16 +4792,17 @@ http_send(http_t *http, /* I - Connection to server */ */ if (!http->fields[HTTP_FIELD_USER_AGENT][0]) - httpSetField(http, HTTP_FIELD_USER_AGENT, CUPS_MINIMAL); + httpSetField(http, HTTP_FIELD_USER_AGENT, + http->default_user_agent ? http->default_user_agent : + CUPS_MINIMAL); -#ifdef HAVE_LIBZ /* * Set the Accept-Encoding field if it isn't already... */ - if (!http->accept_encoding) - httpSetField(http, HTTP_FIELD_ACCEPT_ENCODING, "gzip, deflate, identity"); -#endif /* HAVE_LIBZ */ + if (!http->accept_encoding && http->default_accept_encoding) + httpSetField(http, HTTP_FIELD_ACCEPT_ENCODING, + http->default_accept_encoding); /* * Encode the URI as needed... @@ -4813,7 +4925,7 @@ http_send(http_t *http, /* I - Connection to server */ #ifdef HAVE_SSL -# if defined(HAVE_CDSASSL) && defined(HAVE_SECCERTIFICATECOPYDATA) +# if defined(HAVE_CDSASSL) /* * 'http_set_credentials()' - Set the SSL/TLS credentials. */ @@ -4836,7 +4948,6 @@ http_set_credentials(http_t *http) /* I - Connection to server */ if ((credentials = http->tls_credentials) == NULL) credentials = cg->tls_credentials; -# if HAVE_SECPOLICYCREATESSL /* * Otherwise root around in the user's keychain to see if one can be found... */ @@ -4891,7 +5002,6 @@ http_set_credentials(http_t *http) /* I - Connection to server */ if (dn_array) CFRelease(dn_array); } -# endif /* HAVE_SECPOLICYCREATESSL */ if (credentials) { @@ -4904,7 +5014,7 @@ http_set_credentials(http_t *http) /* I - Connection to server */ return (error); } -# endif /* HAVE_CDSASSL && HAVE_SECCERTIFICATECOPYDATA */ +# endif /* HAVE_CDSASSL */ #endif /* HAVE_SSL */ @@ -5016,7 +5126,6 @@ http_setup_ssl(http_t *http) /* I - Connection to server */ { _cups_globals_t *cg = _cupsGlobals(); /* Pointer to library globals */ - int any_root; /* Allow any root */ char hostname[256], /* Hostname */ *hostptr; /* Pointer into hostname */ @@ -5031,7 +5140,6 @@ http_setup_ssl(http_t *http) /* I - Connection to server */ # elif defined(HAVE_CDSASSL) OSStatus error; /* Error code */ const char *message = NULL;/* Error message */ -# ifdef HAVE_SECCERTIFICATECOPYDATA cups_array_t *credentials; /* Credentials array */ cups_array_t *names; /* CUPS distinguished names */ CFArrayRef dn_array; /* CF distinguished names array */ @@ -5039,7 +5147,6 @@ http_setup_ssl(http_t *http) /* I - Connection to server */ CFDataRef data; /* Certificate data */ int i; /* Looping var */ http_credential_t *credential; /* Credential data */ -# endif /* HAVE_SECCERTIFICATECOPYDATA */ # elif defined(HAVE_SSPISSL) TCHAR username[256]; /* Username returned from GetUserName() */ TCHAR commonName[256];/* Common name for certificate */ @@ -5050,23 +5157,19 @@ http_setup_ssl(http_t *http) /* I - Connection to server */ DEBUG_printf(("7http_setup_ssl(http=%p)", http)); /* - * Always allow self-signed certificates for the local loopback address... + * Get the hostname to use for SSL... */ if (httpAddrLocalhost(http->hostaddr)) { - any_root = 1; strlcpy(hostname, "localhost", sizeof(hostname)); } else { /* - * Otherwise use the system-wide setting and make sure the hostname we have - * does not end in a trailing dot. + * Otherwise make sure the hostname we have does not end in a trailing dot. */ - any_root = cg->any_root; - strlcpy(hostname, http->hostname, sizeof(hostname)); if ((hostptr = hostname + strlen(hostname) - 1) >= hostname && *hostptr == '.') @@ -5074,8 +5177,6 @@ http_setup_ssl(http_t *http) /* I - Connection to server */ } # ifdef HAVE_LIBSSL - (void)any_root; - context = SSL_CTX_new(SSLv23_client_method()); SSL_CTX_set_options(context, SSL_OP_NO_SSLv2); /* Only use SSLv3 or TLS */ @@ -5120,8 +5221,6 @@ http_setup_ssl(http_t *http) /* I - Connection to server */ } # elif defined(HAVE_GNUTLS) - (void)any_root; - credentials = (gnutls_certificate_client_credentials *) malloc(sizeof(gnutls_certificate_client_credentials)); if (credentials == NULL) @@ -5170,9 +5269,11 @@ http_setup_ssl(http_t *http) /* I - Connection to server */ http->tls_credentials = credentials; # elif defined(HAVE_CDSASSL) - if ((error = SSLNewContext(false, &http->tls))) + if ((http->tls = SSLCreateContext(kCFAllocatorDefault, kSSLClientSide, + kSSLStreamType)) == NULL) { - http->error = errno; + DEBUG_puts("4http_setup_ssl: SSLCreateContext failed."); + http->error = errno = ENOMEM; http->status = HTTP_ERROR; _cupsSetHTTPError(HTTP_ERROR); @@ -5190,38 +5291,12 @@ http_setup_ssl(http_t *http) /* I - Connection to server */ if (!error) { - error = SSLSetAllowsAnyRoot(http->tls, any_root); - DEBUG_printf(("4http_setup_ssl: SSLSetAllowsAnyRoot(%d), error=%d", - any_root, (int)error)); - } - - if (!error) - { - error = SSLSetAllowsExpiredCerts(http->tls, cg->expired_certs); - DEBUG_printf(("4http_setup_ssl: SSLSetAllowsExpiredCerts(%d), error=%d", - cg->expired_certs, (int)error)); - } - - if (!error) - { - error = SSLSetAllowsExpiredRoots(http->tls, cg->expired_root); - DEBUG_printf(("4http_setup_ssl: SSLSetAllowsExpiredRoots(%d), error=%d", - cg->expired_root, (int)error)); - } - - /* - * In general, don't verify certificates since things like the common name - * often do not match... - */ - - if (!error) - { - error = SSLSetEnableCertVerify(http->tls, false); - DEBUG_printf(("4http_setup_ssl: SSLSetEnableCertVerify, error=%d", + error = SSLSetSessionOption(http->tls, kSSLSessionOptionBreakOnServerAuth, + true); + DEBUG_printf(("4http_setup_ssl: SSLSetSessionOption, error=%d", (int)error)); } -# ifdef HAVE_SECCERTIFICATECOPYDATA if (!error) { if (cg->client_cert_cb) @@ -5240,20 +5315,6 @@ http_setup_ssl(http_t *http) /* I - Connection to server */ } /* - * If there's a server certificate callback installed let it evaluate the - * certificate(s) during the handshake... - */ - - if (!error && cg->server_cert_cb != NULL) - { - error = SSLSetSessionOption(http->tls, - kSSLSessionOptionBreakOnServerAuth, true); - DEBUG_printf(("4http_setup_ssl: kSSLSessionOptionBreakOnServerAuth, " - "error=%d", (int)error)); - } -# endif /* HAVE_SECCERTIFICATECOPYDATA */ - - /* * Let the server know which hostname/domain we are trying to connect to * in case it wants to serve up a certificate with a matching common name. */ @@ -5287,7 +5348,6 @@ http_setup_ssl(http_t *http) /* I - Connection to server */ usleep(1000); /* in 1 millisecond */ break; -# ifdef HAVE_SECCERTIFICATECOPYDATA case errSSLServerAuthCompleted : error = 0; if (cg->server_cert_cb) @@ -5350,7 +5410,6 @@ http_setup_ssl(http_t *http) /* I - Connection to server */ httpFreeCredentials(names); } break; -# endif /* HAVE_SECCERTIFICATECOPYDATA */ case errSSLUnknownRootCert : message = _("Unable to establish a secure connection to host " @@ -5399,7 +5458,7 @@ http_setup_ssl(http_t *http) /* I - Connection to server */ http->status = HTTP_ERROR; errno = ECONNREFUSED; - SSLDisposeContext(http->tls); + CFRelease(http->tls); http->tls = NULL; /* @@ -5448,7 +5507,7 @@ http_setup_ssl(http_t *http) /* I - Connection to server */ return (-1); } - _sspiSetAllowsAnyRoot(http->tls_credentials, any_root); + _sspiSetAllowsAnyRoot(http->tls_credentials, TRUE); _sspiSetAllowsExpiredCerts(http->tls_credentials, TRUE); if (!_sspiConnect(http->tls_credentials, hostname)) @@ -5501,7 +5560,7 @@ http_shutdown_ssl(http_t *http) /* I - Connection to server */ while (SSLClose(http->tls) == errSSLWouldBlock) usleep(1000); - SSLDisposeContext(http->tls); + CFRelease(http->tls); if (http->tls_credentials) CFRelease(http->tls_credentials); |