/*
- * "$Id$"
- *
* HTTP routines for CUPS.
*
- * Copyright 2007-2014 by Apple Inc.
+ * Copyright 2007-2015 by Apple Inc.
* Copyright 1997-2007 by Easy Software Products, all rights reserved.
*
* This file contains Kerberos support code, copyright 2006 by
* 'httpAcceptConnection()' - Accept a new HTTP client connection from the
* specified listening socket.
*
- * @since CUPS 1.7/OS X 10.9@
+ * @since CUPS 1.7/macOS 10.9@
*/
http_t * /* O - HTTP connection or @code NULL@ */
*
* Use @code cupsArrayNew(NULL, NULL)@ to create a credentials array.
*
- * @since CUPS 1.5/OS X 10.7@
+ * @since CUPS 1.5/macOS 10.7@
*/
int /* O - 0 on success, -1 on error */
/*
* 'httpClearCookie()' - Clear the cookie value(s).
*
- * @since CUPS 1.1.19/OS X 10.3@
+ * @since CUPS 1.1.19/macOS 10.3@
*/
void
void
httpClearFields(http_t *http) /* I - HTTP connection */
{
- DEBUG_printf(("httpClearFields(http=%p)", http));
+ DEBUG_printf(("httpClearFields(http=%p)", (void *)http));
if (http)
{
#endif /* HAVE_GSSAPI */
- DEBUG_printf(("httpClose(http=%p)", http));
+ DEBUG_printf(("httpClose(http=%p)", (void *)http));
/*
* Range check input...
/*
* 'httpConnect2()' - Connect to a HTTP server.
*
- * @since CUPS 1.7/OS X 10.9@
+ * @since CUPS 1.7/macOS 10.9@
*/
http_t * /* O - New HTTP connection */
http_t *http; /* New HTTP connection */
- DEBUG_printf(("httpConnect2(host=\"%s\", port=%d, addrlist=%p, family=%d, "
- "encryption=%d, blocking=%d, msec=%d, cancel=%p)", host, port,
- addrlist, family, encryption, blocking, msec, cancel));
+ DEBUG_printf(("httpConnect2(host=\"%s\", port=%d, addrlist=%p, family=%d, encryption=%d, blocking=%d, msec=%d, cancel=%p)", host, port, (void *)addrlist, family, encryption, blocking, msec, (void *)cancel));
/*
* Create the HTTP structure...
httpEncryption(http_t *http, /* I - HTTP connection */
http_encryption_t e) /* I - New encryption preference */
{
- DEBUG_printf(("httpEncryption(http=%p, e=%d)", http, e));
+ DEBUG_printf(("httpEncryption(http=%p, e=%d)", (void *)http, e));
#ifdef HAVE_SSL
if (!http)
http_state_t oldstate; /* Old state */
- DEBUG_printf(("httpFlush(http=%p), state=%s", http,
- httpStateString(http->state)));
+ DEBUG_printf(("httpFlush(http=%p), state=%s", (void *)http, httpStateString(http->state)));
/*
* Nothing to do if we are in the "waiting" state...
/*
* 'httpFlushWrite()' - Flush data in write buffer.
*
- * @since CUPS 1.2/OS X 10.5@
+ * @since CUPS 1.2/macOS 10.5@
*/
int /* O - Bytes written or -1 on error */
ssize_t bytes; /* Bytes written */
- DEBUG_printf(("httpFlushWrite(http=%p) data_encoding=%d", http,
- http ? http->data_encoding : 100));
+ DEBUG_printf(("httpFlushWrite(http=%p) data_encoding=%d", (void *)http, http ? http->data_encoding : 100));
if (!http || !http->wused)
{
* string to use with httpSetField() for the HTTP_FIELD_AUTHORIZATION
* value.
*
- * @since CUPS 1.3/OS X 10.5@
+ * @since CUPS 1.3/macOS 10.5@
*/
char * /* O - Authorization string */
/*
* 'httpGetBlocking()' - Get the blocking/non-block state of a connection.
*
- * @since CUPS 1.2/OS X 10.5@
+ * @since CUPS 1.2/macOS 10.5@
*/
int /* O - 1 if blocking, 0 if non-blocking */
* client. The value returned can be use in subsequent requests (for clients)
* or in the response (for servers) in order to compress the content stream.
*
- * @since CUPS 1.7/OS X 10.9@
+ * @since CUPS 1.7/macOS 10.9@
*/
const char * /* O - Content-Coding value or
/*
* 'httpGetCookie()' - Get any cookie data from the response.
*
- * @since CUPS 1.1.19/OS X 10.3@
+ * @since CUPS 1.1.19/macOS 10.3@
*/
const char * /* O - Cookie data or NULL */
-httpGetCookie(http_t *http) /* I - HTTP connecion */
+httpGetCookie(http_t *http) /* I - HTTP connection */
{
return (http ? http->cookie : NULL);
}
* Returns @code HTTP_STATUS_NONE@ if there is no Expect header, otherwise
* returns the expected HTTP status code, typically @code HTTP_STATUS_CONTINUE@.
*
- * @since CUPS 1.7/OS X 10.9@
+ * @since CUPS 1.7/macOS 10.9@
*/
http_status_t /* O - Expect: status, if any */
/*
* 'httpGetFd()' - Get the file descriptor associated with a connection.
*
- * @since CUPS 1.2/OS X 10.5@
+ * @since CUPS 1.2/macOS 10.5@
*/
int /* O - File descriptor or -1 if none */
* This function returns the complete content length, even for
* content larger than 2^31 - 1.
*
- * @since CUPS 1.2/OS X 10.5@
+ * @since CUPS 1.2/macOS 10.5@
*/
off_t /* O - Content length */
off_t remaining; /* Remaining length */
- DEBUG_printf(("2httpGetLength2(http=%p), state=%s", http,
- httpStateString(http->state)));
+ DEBUG_printf(("2httpGetLength2(http=%p), state=%s", (void *)http, httpStateString(http->state)));
if (!http)
return (-1);
int eol; /* End-of-line? */
- DEBUG_printf(("2httpGets(line=%p, length=%d, http=%p)", line, length, http));
+ DEBUG_printf(("2httpGets(line=%p, length=%d, http=%p)", (void *)line, length, (void *)http));
if (!http || !line || length <= 1)
return (NULL);
/*
* 'httpGetStatus()' - Get the status of the last HTTP request.
*
- * @since CUPS 1.2/OS X 10.5@
+ * @since CUPS 1.2/macOS 10.5@
*/
http_status_t /* O - HTTP status */
/*
* 'httpGetSubField2()' - Get a sub-field value.
*
- * @since CUPS 1.2/OS X 10.5@
+ * @since CUPS 1.2/macOS 10.5@
*/
char * /* O - Value or NULL */
*ptr, /* Pointer into string buffer */
*end; /* End of value buffer */
- DEBUG_printf(("2httpGetSubField2(http=%p, field=%d, name=\"%s\", value=%p, "
- "valuelen=%d)", http, field, name, value, valuelen));
+ DEBUG_printf(("2httpGetSubField2(http=%p, field=%d, name=\"%s\", value=%p, valuelen=%d)", (void *)http, field, name, (void *)value, valuelen));
if (!http || !name || !value || valuelen < 2 ||
field <= HTTP_FIELD_UNKNOWN || field >= HTTP_FIELD_MAX)
httpHead(http_t *http, /* I - HTTP connection */
const char *uri) /* I - URI for head */
{
- DEBUG_printf(("httpHead(http=%p, uri=\"%s\")", http, uri));
+ DEBUG_printf(("httpHead(http=%p, uri=\"%s\")", (void *)http, uri));
return (http_send(http, HTTP_STATE_HEAD, uri));
}
*
* For non-blocking connections the usual timeouts apply.
*
- * @since CUPS 1.7/OS X 10.9@
+ * @since CUPS 1.7/macOS 10.9@
*/
ssize_t /* O - Number of bytes copied */
char len[32]; /* Length string */
- DEBUG_printf(("httpPeek(http=%p, buffer=%p, length=" CUPS_LLFMT ")",
- http, buffer, CUPS_LLCAST length));
+ DEBUG_printf(("httpPeek(http=%p, buffer=%p, length=" CUPS_LLFMT ")", (void *)http, (void *)buffer, CUPS_LLCAST length));
if (http == NULL || buffer == NULL)
return (-1);
memcpy(http->sbuffer + http->stream.avail_in, http->buffer, buflen);
http->stream.avail_in += buflen;
- http->used -= buflen;
- http->data_remaining -= buflen;
+ http->used -= (int)buflen;
+ http->data_remaining -= (off_t)buflen;
if (http->used > 0)
memmove(http->buffer, http->buffer + buflen, (size_t)http->used);
va_list ap; /* Variable argument pointer */
- DEBUG_printf(("2httpPrintf(http=%p, format=\"%s\", ...)", http, format));
+ DEBUG_printf(("2httpPrintf(http=%p, format=\"%s\", ...)", (void *)http, format));
va_start(ap, format);
bytes = vsnprintf(buf, sizeof(buf), format, ap);
httpPut(http_t *http, /* I - HTTP connection */
const char *uri) /* I - URI to put */
{
- DEBUG_printf(("httpPut(http=%p, uri=\"%s\")", http, uri));
+ DEBUG_printf(("httpPut(http=%p, uri=\"%s\")", (void *)http, uri));
return (http_send(http, HTTP_STATE_PUT, uri));
}
/*
* 'httpRead2()' - Read data from a HTTP connection.
*
- * @since CUPS 1.2/OS X 10.5@
+ * @since CUPS 1.2/macOS 10.5@
*/
ssize_t /* O - Number of bytes read */
#ifdef HAVE_LIBZ
- DEBUG_printf(("httpRead2(http=%p, buffer=%p, length=" CUPS_LLFMT
- ") coding=%d data_encoding=%d data_remaining=" CUPS_LLFMT,
- http, buffer, CUPS_LLCAST length,
- http->coding,
- http->data_encoding, CUPS_LLCAST http->data_remaining));
+ DEBUG_printf(("httpRead2(http=%p, buffer=%p, length=" CUPS_LLFMT ") coding=%d data_encoding=%d data_remaining=" CUPS_LLFMT, (void *)http, (void *)buffer, CUPS_LLCAST length, http->coding, http->data_encoding, CUPS_LLCAST http->data_remaining));
#else
- DEBUG_printf(("httpRead2(http=%p, buffer=%p, length=" CUPS_LLFMT
- ") data_encoding=%d data_remaining=" CUPS_LLFMT,
- http, buffer, CUPS_LLCAST length,
- http->data_encoding, CUPS_LLCAST http->data_remaining));
+ DEBUG_printf(("httpRead2(http=%p, buffer=%p, length=" CUPS_LLFMT ") data_encoding=%d data_remaining=" CUPS_LLFMT, (void *)http, (void *)buffer, CUPS_LLCAST length, http->data_encoding, CUPS_LLCAST http->data_remaining));
#endif /* HAVE_LIBZ */
if (http == NULL || buffer == NULL)
/*
* 'httpReadRequest()' - Read a HTTP request from a connection.
*
- * @since CUPS 1.7/OS X 10.9@
+ * @since CUPS 1.7/macOS 10.9@
*/
http_state_t /* O - New state of connection */
* Range check input...
*/
- DEBUG_printf(("httpReadRequest(http=%p, uri=%p, urilen=" CUPS_LLFMT ")",
- http, uri, CUPS_LLCAST urilen));
+ DEBUG_printf(("httpReadRequest(http=%p, uri=%p, urilen=" CUPS_LLFMT ")", (void *)http, (void *)uri, CUPS_LLCAST urilen));
if (uri)
*uri = '\0';
int /* O - 0 on success, non-zero on failure */
httpReconnect(http_t *http) /* I - HTTP connection */
{
- DEBUG_printf(("httpReconnect(http=%p)", http));
+ DEBUG_printf(("httpReconnect(http=%p)", (void *)http));
return (httpReconnect2(http, 30000, NULL));
}
#endif /* DEBUG */
- DEBUG_printf(("httpReconnect2(http=%p, msec=%d, cancel=%p)", http, msec,
- cancel));
+ DEBUG_printf(("httpReconnect2(http=%p, msec=%d, cancel=%p)", (void *)http, msec, (void *)cancel));
if (!http)
{
httpAddrPort(&(current->addr))));
#endif /* DEBUG */
- if ((addr = httpAddrConnect2(http->addrlist, &(http->fd), msec,
- cancel)) == NULL)
+ if ((addr = httpAddrConnect2(http->addrlist, &(http->fd), msec, cancel)) == NULL)
{
/*
* Unable to connect...
* HTTP_FIELD_AUTHORIZATION prior to issuing a HTTP request using httpGet(),
* httpHead(), httpOptions(), httpPost, or httpPut().
*
- * @since CUPS 1.3/OS X 10.5@
+ * @since CUPS 1.3/macOS 10.5@
*/
void
* 'httpSetCredentials()' - Set the credentials associated with an encrypted
* connection.
*
- * @since CUPS 1.5/OS X 10.7@
+ * @since CUPS 1.5/macOS 10.7@
*/
int /* O - Status of call (0 = success) */
/*
* 'httpSetCookie()' - Set the cookie value(s).
*
- * @since CUPS 1.1.19/OS X 10.3@
+ * @since CUPS 1.1.19/macOS 10.3@
*/
void
* Currently only @code HTTP_FIELD_ACCEPT_ENCODING@, @code HTTP_FIELD_SERVER@,
* and @code HTTP_FIELD_USER_AGENT@ can be set.
*
- * @since CUPS 1.7/OS X 10.9@
+ * @since CUPS 1.7/macOS 10.9@
*/
void
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));
+ DEBUG_printf(("httpSetDefaultField(http=%p, field=%d(%s), value=\"%s\")", (void *)http, field, http_fields[field], value));
if (!http)
return;
* Currently only @code HTTP_STATUS_CONTINUE@ is supported for the "expect"
* argument.
*
- * @since CUPS 1.2/OS X 10.5@
+ * @since CUPS 1.2/macOS 10.5@
*/
void
http_status_t expect) /* I - HTTP status to expect
(@code HTTP_STATUS_CONTINUE@) */
{
- DEBUG_printf(("httpSetExpect(http=%p, expect=%d)", http, expect));
+ DEBUG_printf(("httpSetExpect(http=%p, expect=%d)", (void *)http, expect));
if (http)
http->expect = expect;
http_field_t field, /* I - Field index */
const char *value) /* I - Value */
{
- DEBUG_printf(("httpSetField(http=%p, field=%d(%s), value=\"%s\")", http,
- field, http_fields[field], value));
+ DEBUG_printf(("httpSetField(http=%p, field=%d(%s), value=\"%s\")", (void *)http, field, http_fields[field], value));
if (http == NULL ||
field < HTTP_FIELD_ACCEPT_LANGUAGE ||
http->server = _cupsStrAlloc(value);
break;
+ case HTTP_FIELD_WWW_AUTHENTICATE :
+ /* CUPS STR #4503 - don't override WWW-Authenticate for unknown auth schemes */
+ if (http->fields[HTTP_FIELD_WWW_AUTHENTICATE][0] &&
+ _cups_strncasecmp(value, "Basic ", 6) &&
+ _cups_strncasecmp(value, "Digest ", 7) &&
+ _cups_strncasecmp(value, "Negotiate ", 10))
+ {
+ DEBUG_printf(("1httpSetField: Ignoring unknown auth scheme in \"%s\".", value));
+ return;
+ }
+
+ /* Fall through to copy */
+
default :
strlcpy(http->fields[field], value, HTTP_MAX_VALUE);
break;
/*
* 'httpSetLength()' - Set the content-length and content-encoding.
*
- * @since CUPS 1.2/OS X 10.5@
+ * @since CUPS 1.2/macOS 10.5@
*/
void
httpSetLength(http_t *http, /* I - HTTP connection */
size_t length) /* I - Length (0 for chunked) */
{
- DEBUG_printf(("httpSetLength(http=%p, length=" CUPS_LLFMT ")", http,
- CUPS_LLCAST length));
+ DEBUG_printf(("httpSetLength(http=%p, length=" CUPS_LLFMT ")", (void *)http, CUPS_LLCAST length));
if (!http)
return;
* The optional timeout callback receives both the HTTP connection and a user
* data pointer and must return 1 to continue or 0 to error (time) out.
*
- * @since CUPS 1.5/OS X 10.7@
+ * @since CUPS 1.5/macOS 10.7@
*/
void
int major, minor; /* HTTP version numbers */
- DEBUG_printf(("_httpUpdate(http=%p, status=%p), state=%s", http, status,
- httpStateString(http->state)));
+ DEBUG_printf(("_httpUpdate(http=%p, status=%p), state=%s", (void *)http, (void *)status, httpStateString(http->state)));
/*
* Grab a single line from the connection...
*status = http->status;
return (0);
}
- else if (!strncmp(line, "HTTP/", 5))
+ else if (!strncmp(line, "HTTP/", 5) && http->mode == _HTTP_MODE_CLIENT)
{
/*
* Got the beginning of a response...
http_status_t status; /* Request status */
- DEBUG_printf(("httpUpdate(http=%p), state=%s", http,
- httpStateString(http->state)));
+ DEBUG_printf(("httpUpdate(http=%p), state=%s", (void *)http, httpStateString(http->state)));
/*
* Flush pending data, if any...
int nfds; /* Result from select()/poll() */
- DEBUG_printf(("4_httpWait(http=%p, msec=%d, usessl=%d)", http, msec, usessl));
+ DEBUG_printf(("4_httpWait(http=%p, msec=%d, usessl=%d)", (void *)http, msec, usessl));
if (http->fd < 0)
{
/*
* 'httpWait()' - Wait for data available on a connection.
*
- * @since CUPS 1.1.19/OS X 10.3@
+ * @since CUPS 1.1.19/macOS 10.3@
*/
int /* O - 1 if data is available, 0 otherwise */
* First see if there is data in the buffer...
*/
- DEBUG_printf(("2httpWait(http=%p, msec=%d)", http, msec));
+ DEBUG_printf(("2httpWait(http=%p, msec=%d)", (void *)http, msec));
if (http == NULL)
return (0);
/*
* 'httpWrite2()' - Write data to a HTTP connection.
*
- * @since CUPS 1.2/OS X 10.5@
+ * @since CUPS 1.2/macOS 10.5@
*/
ssize_t /* O - Number of bytes written */
ssize_t bytes; /* Bytes written */
- DEBUG_printf(("httpWrite2(http=%p, buffer=%p, length=" CUPS_LLFMT ")", http,
- buffer, CUPS_LLCAST length));
+ DEBUG_printf(("httpWrite2(http=%p, buffer=%p, length=" CUPS_LLFMT ")", (void *)http, (void *)buffer, CUPS_LLCAST length));
/*
* Range check input...
/*
* 'httpWriteResponse()' - Write a HTTP response to a client connection.
*
- * @since CUPS 1.7/OS X 10.9@
+ * @since CUPS 1.7/macOS 10.9@
*/
int /* O - 0 on success, -1 on error */
* Range check input...
*/
- DEBUG_printf(("httpWriteResponse(http=%p, status=%d)", http, status));
+ DEBUG_printf(("httpWriteResponse(http=%p, status=%d)", (void *)http, status));
if (!http || status < HTTP_STATUS_CONTINUE)
{
return (-1);
}
}
+
+ /*
+ * "Click-jacking" defense (STR #4492)...
+ */
+
+ if (httpPrintf(http, "X-Frame-Options: DENY\r\n"
+ "Content-Security-Policy: frame-ancestors 'none'\r\n") < 1)
+ {
+ http->status = HTTP_STATUS_ERROR;
+ return (-1);
+ }
}
if (httpWrite2(http, "\r\n", 2) < 2)
size_t bytes; /* Number of bytes to write */
- DEBUG_printf(("http_content_coding_finish(http=%p)", http));
+ DEBUG_printf(("http_content_coding_finish(http=%p)", (void *)http));
DEBUG_printf(("1http_content_coding_finishing: http->coding=%d", http->coding));
switch (http->coding)
_http_coding_t coding; /* Content coding value */
- DEBUG_printf(("http_content_coding_start(http=%p, value=\"%s\")", http,
- value));
+ DEBUG_printf(("http_content_coding_start(http=%p, value=\"%s\")", (void *)http, value));
if (http->coding != _HTTP_CODING_IDENTITY)
{
http_addrlist_t *myaddrlist = NULL; /* My address list */
- DEBUG_printf(("4http_create(host=\"%s\", port=%d, addrlist=%p, family=%d, "
- "encryption=%d, blocking=%d, mode=%d)", host, port, addrlist,
- family, encryption, blocking, mode));
+ DEBUG_printf(("4http_create(host=\"%s\", port=%d, addrlist=%p, family=%d, encryption=%d, blocking=%d, mode=%d)", host, port, (void *)addrlist, family, encryption, blocking, mode));
if (!host && mode == _HTTP_MODE_CLIENT)
return (NULL);
for (i = 0; i < bytes; i += 16)
{
for (j = 0, ptr = start; j < 16 && (i + j) < bytes; j ++, ptr += 2)
- sprintf(ptr, "%02X", buffer[i + j] & 255);
+ snprintf(ptr, 3, "%02X", buffer[i + j] & 255);
while (j < 16)
{
ssize_t bytes; /* Bytes read */
- DEBUG_printf(("http_read(http=%p, buffer=%p, length=" CUPS_LLFMT ")", http,
- buffer, CUPS_LLCAST length));
+ DEBUG_printf(("http_read(http=%p, buffer=%p, length=" CUPS_LLFMT ")", (void *)http, (void *)buffer, CUPS_LLCAST length));
if (!http->blocking)
{
ssize_t bytes; /* Bytes read */
- DEBUG_printf(("http_read_buffered(http=%p, buffer=%p, length=" CUPS_LLFMT
- ") used=%d",
- http, buffer, CUPS_LLCAST length, http->used));
+ DEBUG_printf(("http_read_buffered(http=%p, buffer=%p, length=" CUPS_LLFMT ") used=%d", (void *)http, (void *)buffer, CUPS_LLCAST length, http->used));
if (http->used > 0)
{
char *buffer, /* I - Buffer */
size_t length) /* I - Maximum bytes to read */
{
- DEBUG_printf(("http_read_chunk(http=%p, buffer=%p, length=" CUPS_LLFMT ")",
- http, buffer, CUPS_LLCAST length));
+ DEBUG_printf(("http_read_chunk(http=%p, buffer=%p, length=" CUPS_LLFMT ")", (void *)http, (void *)buffer, CUPS_LLCAST length));
if (http->data_remaining <= 0)
{
};
- DEBUG_printf(("4http_send(http=%p, request=HTTP_%s, uri=\"%s\")",
- http, codes[request], uri));
+ DEBUG_printf(("4http_send(http=%p, request=HTTP_%s, uri=\"%s\")", (void *)http, codes[request], uri));
if (http == NULL || uri == NULL)
return (-1);
off_t remaining; /* Remainder */
- DEBUG_printf(("http_set_length(http=%p) mode=%d state=%s", http, http->mode,
- httpStateString(http->state)));
+ DEBUG_printf(("http_set_length(http=%p) mode=%d state=%s", (void *)http, http->mode, httpStateString(http->state)));
if ((remaining = httpGetLength2(http)) >= 0)
{
http_t myhttp; /* Local copy of HTTP data */
- DEBUG_printf(("7http_tls_upgrade(%p)", http));
+ DEBUG_printf(("7http_tls_upgrade(%p)", (void *)http));
/*
* Flush the connection to make sure any previous "Upgrade" message
bytes; /* Bytes sent */
- DEBUG_printf(("2http_write(http=%p, buffer=%p, length=" CUPS_LLFMT ")", http,
- buffer, CUPS_LLCAST length));
+ DEBUG_printf(("2http_write(http=%p, buffer=%p, length=" CUPS_LLFMT ")", (void *)http, (void *)buffer, CUPS_LLCAST length));
http->error = 0;
tbytes = 0;
ssize_t bytes; /* Bytes written */
- DEBUG_printf(("7http_write_chunk(http=%p, buffer=%p, length=" CUPS_LLFMT ")",
- http, buffer, CUPS_LLCAST length));
+ DEBUG_printf(("7http_write_chunk(http=%p, buffer=%p, length=" CUPS_LLFMT ")", (void *)http, (void *)buffer, CUPS_LLCAST length));
/*
* Write the chunk header, data, and trailer.
return (bytes);
}
-
-
-/*
- * End of "$Id$".
- */