-CHANGES - 2.2.6 - 2017-11-01
+CHANGES - 2.2.7 - 2018-03-06
============================
+Changes in CUPS v2.2.7
+----------------------
+
+- Fixed a compile issue when PAM is not available (Issue #5253)
+- Documentation fixes (Issue #5252)
+- Star Micronics printers need the "unidir" USB quirk rule (Issue #5251)
+- The scheduler now supports using temporary print queues for older IPP/1.1
+ print queues like those shared by CUPS 1.3 and earlier (Issue #5241)
+- The `cupsRasterWritePixels` function did not correctly swap bytes for some
+ formats (Issue #5225)
+- Added a USB quirk rule for Canon MP280 series printers (Issue #5221)
+- The `ppdInstallableConflict` tested too many constraints (Issue #5213)
+- More fixes for printing to old CUPS servers (Issue #5211)
+- The `cupsCopyDest` function now correctly copies the `is_default` value
+ (Issue #5208)
+- The scheduler did not work with older versions of uClibc (Issue #5188)
+- The scheduler now substitutes default values for invalid job attributes when
+ running in "relaxed conformance" mode (Issue #5186)
+- Fixed PAM module detection and added support for the common PAM definitions
+ (Issue #5185)
+- Fixed a journald support bug in the scheduler (Issue #5181)
+- The cups-driverd program incorrectly stopped scanning PPDs as soon as a loop
+ was seen (Issue #5170)
+- Fixed group validation on OpenBSD (Issue #5166)
+- Fixed the `ippserver` sample code when threading is disabled or unavailable
+ (Issue #5154)
+- The `cupsEnumDests` function did not include options from the lpoptions files
+ (Issue #5144)
+- The `SSLOptions` directive now supports `MinTLS` and `MaxTLS` options to
+ control the minimum and maximum TLS versions that will be allowed,
+ respectively (Issue #5119)
+- The scheduler did not write out dirty configuration and state files if there
+ were open client connections (Issue #5118)
+- The `lpadmin` command now provides a better error message when an unsupported
+ System V interface script is used (Issue #5111)
+- The `lp` and `lpr` commands now provide better error messages when the default
+ printer cannot be found (Issue #5096)
+- No longer support backslash, question mark, or quotes in printer names
+ (Issue #4966)
+- The CUPS library now supports the latest HTTP Digest authentication
+ specification including support for SHA-256 (Issue #4862)
+- The `lpstat` command now reports when new jobs are being held (Issue #4761)
+- The `lpoptions` command incorrectly saved default options (Issue #4717)
+- The `ppdLocalizeIPPReason` function incorrectly returned a localized version
+ of "none" (rdar://36566269)
+- TLS connections now properly timeout (rdar://34938533)
+- The IPP backend did not properly detect failed PDF prints (rdar://34055474)
+
+
Changes in CUPS v2.2.6
----------------------
-INSTALL - CUPS v2.2.6 - 2017-11-01
+INSTALL - CUPS v2.2.7 - 2018-03-06
==================================
This file describes how to compile and install CUPS from source code. For more
-README - CUPS v2.2.6 - 2017-11-01
+README - CUPS v2.2.7 - 2018-03-06
=================================
Looking for compile instructions? Read the file `INSTALL.md` instead...
LEGAL STUFF
-----------
-CUPS is copyright © 2007-2017 by Apple Inc. CUPS and the CUPS logo are
+CUPS is copyright © 2007-2018 by Apple Inc. CUPS and the CUPS logo are
trademarks of Apple Inc.
The MD5 Digest code is Copyright 1999 Aladdin Enterprises.
#define _CUPS_JSR_ACCOUNT_LIMIT_REACHED 0x08
#define _CUPS_JSR_JOB_PASSWORD_WAIT 0x10
#define _CUPS_JSR_JOB_RELEASE_WAIT 0x20
+#define _CUPS_JSR_DOCUMENT_FORMAT_ERROR 0x40
+#define _CUPS_JSR_DOCUMENT_UNPRINTABLE 0x80
/*
http_encryption_t encryption; /* Use encryption? */
ipp_jstate_t job_state; /* Current job state */
ipp_pstate_t printer_state; /* Current printer state */
+ int retryable; /* Is this a job that should be retried? */
} _cups_monitor_t;
monitor.encryption = cupsEncryption();
monitor.job_state = IPP_JOB_PENDING;
monitor.printer_state = IPP_PRINTER_IDLE;
+ monitor.retryable = argc == 6 && document_format && strcmp(document_format, "image/pwg-raster") && strcmp(document_format, "image/urf");
if (create_job)
{
for (i = 0; i < attr->num_values; i ++)
{
- if (!strcmp(attr->values[i].string.text,
- "account-authorization-failed"))
+ if (!strcmp(attr->values[i].string.text, "account-authorization-failed"))
new_reasons |= _CUPS_JSR_ACCOUNT_AUTHORIZATION_FAILED;
else if (!strcmp(attr->values[i].string.text, "account-closed"))
new_reasons |= _CUPS_JSR_ACCOUNT_CLOSED;
else if (!strcmp(attr->values[i].string.text, "account-info-needed"))
new_reasons |= _CUPS_JSR_ACCOUNT_INFO_NEEDED;
- else if (!strcmp(attr->values[i].string.text,
- "account-limit-reached"))
+ else if (!strcmp(attr->values[i].string.text, "account-limit-reached"))
new_reasons |= _CUPS_JSR_ACCOUNT_LIMIT_REACHED;
else if (!strcmp(attr->values[i].string.text, "job-password-wait"))
new_reasons |= _CUPS_JSR_JOB_PASSWORD_WAIT;
else if (!strcmp(attr->values[i].string.text, "job-release-wait"))
new_reasons |= _CUPS_JSR_JOB_RELEASE_WAIT;
- if (!job_canceled &&
- (!strncmp(attr->values[i].string.text, "job-canceled-", 13) || !strcmp(attr->values[i].string.text, "aborted-by-system")))
+ else if (!strcmp(attr->values[i].string.text, "document-format-error"))
+ new_reasons |= _CUPS_JSR_DOCUMENT_FORMAT_ERROR;
+ else if (!strcmp(attr->values[i].string.text, "document-unprintable"))
+ new_reasons |= _CUPS_JSR_DOCUMENT_UNPRINTABLE;
+
+ if (!job_canceled && (!strncmp(attr->values[i].string.text, "job-canceled-", 13) || !strcmp(attr->values[i].string.text, "aborted-by-system")))
job_canceled = 1;
}
fputs("JOBSTATE: job-password-wait\n", stderr);
else if (new_reasons & _CUPS_JSR_JOB_RELEASE_WAIT)
fputs("JOBSTATE: job-release-wait\n", stderr);
+ else if (new_reasons & (_CUPS_JSR_DOCUMENT_FORMAT_ERROR | _CUPS_JSR_DOCUMENT_UNPRINTABLE))
+ {
+ if (monitor->retryable)
+ {
+ /*
+ * Can't print this, so retry as raster...
+ */
+
+ job_canceled = 1;
+ fputs("JOBSTATE: cups-retry-as-raster\n", stderr);
+ }
+ else if (new_reasons & _CUPS_JSR_DOCUMENT_FORMAT_ERROR)
+ {
+ fputs("JOBSTATE: document-format-error\n", stderr);
+ }
+ else
+ {
+ fputs("JOBSTATE: document-unprintable\n", stderr);
+ }
+ }
else
fputs("JOBSTATE: job-printing\n", stderr);
char *printer, /* Destination printer or class */
*instance, /* Instance */
*opt; /* Option pointer */
- const char *title, /* Job title */
- *val; /* Environment variable name */
+ const char *title; /* Job title */
int num_copies; /* Number of copies per file */
int num_files; /* Number of files to print */
const char *files[1000]; /* Files to print */
if (printer == NULL)
{
- val = NULL;
-
- if ((printer = getenv("LPDEST")) == NULL)
- {
- if ((printer = getenv("PRINTER")) != NULL)
- {
- if (!strcmp(printer, "lp"))
- printer = NULL;
- else
- val = "PRINTER";
- }
- }
- else
- val = "LPDEST";
-
- if (printer && !cupsGetNamedDest(NULL, printer, NULL))
- _cupsLangPrintf(stderr,
- _("%s: Error - %s environment variable names "
- "non-existent destination \"%s\"."), argv[0], val,
- printer);
- else if (cupsLastError() == IPP_NOT_FOUND)
- _cupsLangPrintf(stderr,
- _("%s: Error - no default destination available."),
- argv[0]);
+ if (!cupsGetNamedDest(NULL, NULL, NULL) && cupsLastError() == IPP_STATUS_ERROR_NOT_FOUND)
+ _cupsLangPrintf(stderr, _("%s: Error - %s"), argv[0], cupsLastErrorString());
else
- _cupsLangPrintf(stderr, _("%s: Error - scheduler not responding."),
- argv[0]);
+ _cupsLangPrintf(stderr, _("%s: Error - scheduler not responding."), argv[0]);
return (1);
}
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for CUPS 2.2.6.
+# Generated by GNU Autoconf 2.69 for CUPS 2.2.7.
#
# Report bugs to <https://github.com/apple/cups/issues>.
#
# Identity of this package.
PACKAGE_NAME='CUPS'
PACKAGE_TARNAME='cups'
-PACKAGE_VERSION='2.2.6'
-PACKAGE_STRING='CUPS 2.2.6'
+PACKAGE_VERSION='2.2.7'
+PACKAGE_STRING='CUPS 2.2.7'
PACKAGE_BUGREPORT='https://github.com/apple/cups/issues'
PACKAGE_URL='https://www.cups.org/'
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
-\`configure' configures CUPS 2.2.6 to adapt to many kinds of systems.
+\`configure' configures CUPS 2.2.7 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
if test -n "$ac_init_help"; then
case $ac_init_help in
- short | recursive ) echo "Configuration of CUPS 2.2.6:";;
+ short | recursive ) echo "Configuration of CUPS 2.2.7:";;
esac
cat <<\_ACEOF
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
-CUPS configure 2.2.6
+CUPS configure 2.2.7
generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc.
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
-It was created by CUPS $as_me 2.2.6, which was
+It was created by CUPS $as_me 2.2.7, which was
generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@
ac_config_headers="$ac_config_headers config.h"
-CUPS_VERSION="2.2.6"
+CUPS_VERSION="2.2.7"
CUPS_REVISION=""
CUPS_BUILD="cups-$CUPS_VERSION"
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
-This file was extended by CUPS $as_me 2.2.6, which was
+This file was extended by CUPS $as_me 2.2.7, which was
generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\
-CUPS config.status 2.2.6
+CUPS config.status 2.2.7
configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\"
dnl
dnl Configuration script for CUPS.
dnl
-dnl Copyright 2007-2017 by Apple Inc.
+dnl Copyright 2007-2018 by Apple Inc.
dnl Copyright 1997-2007 by Easy Software Products, all rights reserved.
dnl
dnl These coded instructions, statements, and computer programs are the
AC_PREREQ(2.60)
dnl Package name and version...
-AC_INIT([CUPS], [2.2.6], [https://github.com/apple/cups/issues], [cups], [https://www.cups.org/])
+AC_INIT([CUPS], [2.2.7], [https://github.com/apple/cups/issues], [cups], [https://www.cups.org/])
sinclude(config-scripts/cups-opsys.m4)
sinclude(config-scripts/cups-common.m4)
* Local functions...
*/
+static const char *cups_auth_find(const char *www_authenticate, const char *scheme);
+static const char *cups_auth_param(const char *scheme, const char *name, char *value, size_t valsize);
+static const char *cups_auth_scheme(const char *www_authenticate, char *scheme, size_t schemesize);
+
#ifdef HAVE_GSSAPI
# ifdef HAVE_GSS_ACQUIRE_CRED_EX_F
# ifdef HAVE_GSS_GSSAPI_SPI_H
const char *resource) /* I - Resource path */
{
const char *password, /* Password string */
- *www_auth; /* WWW-Authenticate header */
- char prompt[1024], /* Prompt for user */
+ *www_auth, /* WWW-Authenticate header */
+ *schemedata; /* Scheme-specific data */
+ char scheme[256], /* Scheme name */
+ prompt[1024], /* Prompt for user */
realm[HTTP_MAX_VALUE], /* realm="xyz" string */
nonce[HTTP_MAX_VALUE]; /* nonce="xyz" string */
int localauth; /* Local authentication result */
}
/*
- * Nope, see if we should retry the current username:password...
+ * Nope, loop through the authentication schemes to find the first we support.
*/
- www_auth = http->fields[HTTP_FIELD_WWW_AUTHENTICATE];
+ www_auth = httpGetField(http, HTTP_FIELD_WWW_AUTHENTICATE);
- if ((http->digest_tries > 1 || !http->userpass[0]) &&
- (!_cups_strncasecmp(www_auth, "Basic", 5) ||
- !_cups_strncasecmp(www_auth, "Digest", 6)))
+ for (schemedata = cups_auth_scheme(www_auth, scheme, sizeof(scheme)); schemedata; schemedata = cups_auth_scheme(schemedata + strlen(scheme), scheme, sizeof(scheme)))
{
/*
- * Nope - get a new password from the user...
+ * Check the scheme name...
*/
- char default_username[HTTP_MAX_VALUE];
- /* Default username */
+#ifdef HAVE_GSSAPI
+ if (!_cups_strcasecmp(scheme, "Negotiate"))
+ {
+ /*
+ * Kerberos authentication...
+ */
- cg = _cupsGlobals();
+ if (_cupsSetNegotiateAuthString(http, method, resource))
+ {
+ http->status = HTTP_STATUS_CUPS_AUTHORIZATION_CANCELED;
+ return (-1);
+ }
- if (!cg->lang_default)
- cg->lang_default = cupsLangDefault();
+ break;
+ }
+ else
+#endif /* HAVE_GSSAPI */
+ if (_cups_strcasecmp(scheme, "Basic") && _cups_strcasecmp(scheme, "Digest"))
+ continue; /* Not supported (yet) */
- if (httpGetSubField(http, HTTP_FIELD_WWW_AUTHENTICATE, "username",
- default_username))
- cupsSetUser(default_username);
+ /*
+ * See if we should retry the current username:password...
+ */
- snprintf(prompt, sizeof(prompt),
- _cupsLangString(cg->lang_default, _("Password for %s on %s? ")),
- cupsUser(),
- http->hostname[0] == '/' ? "localhost" : http->hostname);
+ if ((http->digest_tries > 1 || !http->userpass[0]) && (!_cups_strcasecmp(scheme, "Basic") || (!_cups_strcasecmp(scheme, "Digest"))))
+ {
+ /*
+ * Nope - get a new password from the user...
+ */
- http->digest_tries = _cups_strncasecmp(www_auth, "Digest", 6) != 0;
- http->userpass[0] = '\0';
+ char default_username[HTTP_MAX_VALUE];
+ /* Default username */
- if ((password = cupsGetPassword2(prompt, http, method, resource)) == NULL)
- {
- http->status = HTTP_STATUS_CUPS_AUTHORIZATION_CANCELED;
- return (-1);
- }
+ cg = _cupsGlobals();
- snprintf(http->userpass, sizeof(http->userpass), "%s:%s", cupsUser(),
- password);
- }
- else if (http->status == HTTP_STATUS_UNAUTHORIZED)
- http->digest_tries ++;
+ if (!cg->lang_default)
+ cg->lang_default = cupsLangDefault();
- if (http->status == HTTP_STATUS_UNAUTHORIZED && http->digest_tries >= 3)
- {
- DEBUG_printf(("1cupsDoAuthentication: Too many authentication tries (%d)",
- http->digest_tries));
+ if (cups_auth_param(scheme, "username", default_username, sizeof(default_username)))
+ cupsSetUser(default_username);
- http->status = HTTP_STATUS_CUPS_AUTHORIZATION_CANCELED;
- return (-1);
- }
+ snprintf(prompt, sizeof(prompt), _cupsLangString(cg->lang_default, _("Password for %s on %s? ")), cupsUser(), http->hostname[0] == '/' ? "localhost" : http->hostname);
- /*
- * Got a password; encode it for the server...
- */
+ http->digest_tries = _cups_strncasecmp(scheme, "Digest", 6) != 0;
+ http->userpass[0] = '\0';
-#ifdef HAVE_GSSAPI
- if (!_cups_strncasecmp(www_auth, "Negotiate", 9))
- {
- /*
- * Kerberos authentication...
- */
+ if ((password = cupsGetPassword2(prompt, http, method, resource)) == NULL)
+ {
+ http->status = HTTP_STATUS_CUPS_AUTHORIZATION_CANCELED;
+ return (-1);
+ }
+
+ snprintf(http->userpass, sizeof(http->userpass), "%s:%s", cupsUser(), password);
+ }
+ else if (http->status == HTTP_STATUS_UNAUTHORIZED)
+ http->digest_tries ++;
- if (_cupsSetNegotiateAuthString(http, method, resource))
+ if (http->status == HTTP_STATUS_UNAUTHORIZED && http->digest_tries >= 3)
{
+ DEBUG_printf(("1cupsDoAuthentication: Too many authentication tries (%d)", http->digest_tries));
+
http->status = HTTP_STATUS_CUPS_AUTHORIZATION_CANCELED;
return (-1);
}
- }
- else
-#endif /* HAVE_GSSAPI */
- if (!_cups_strncasecmp(www_auth, "Basic", 5))
- {
+
/*
- * Basic authentication...
+ * Got a password; encode it for the server...
*/
- char encode[256]; /* Base64 buffer */
+ if (!_cups_strcasecmp(scheme, "Basic"))
+ {
+ /*
+ * Basic authentication...
+ */
+
+ char encode[256]; /* Base64 buffer */
+ httpEncode64_2(encode, sizeof(encode), http->userpass, (int)strlen(http->userpass));
+ httpSetAuthString(http, "Basic", encode);
+ }
+ else if (!_cups_strcasecmp(scheme, "Digest"))
+ {
+ /*
+ * Digest authentication...
+ */
- httpEncode64_2(encode, sizeof(encode), http->userpass,
- (int)strlen(http->userpass));
- httpSetAuthString(http, "Basic", encode);
- }
- else if (!_cups_strncasecmp(www_auth, "Digest", 6))
- {
- /*
- * Digest authentication...
- */
+ int i; /* Looping var */
+ char algorithm[65], /* Hashing algorithm */
+ opaque[HTTP_MAX_VALUE],
+ /* Opaque data from server */
+ cnonce[65], /* cnonce value */
+ kd[65], /* Final MD5/SHA-256 digest */
+ ha1[65], /* Hash of username:realm:password */
+ ha2[65], /* Hash of method:request-uri */
+ hdata[65], /* Hash of auth data */
+ temp[1024], /* Temporary string */
+ digest[1024]; /* Digest auth data */
+ unsigned char hash[32]; /* Hash buffer */
+ const char *hashalg; /* Hashing algorithm */
+ size_t hashsize; /* Size of hash */
+
+ if (strcmp(nonce, http->nonce))
+ {
+ strlcpy(http->nonce, nonce, sizeof(http->nonce));
+ http->nonce_count = 1;
+ }
+ else
+ http->nonce_count ++;
- char encode[33], /* MD5 buffer */
- digest[1024]; /* Digest auth data */
+ cups_auth_param(schemedata, "opaque", opaque, sizeof(opaque));
+ cups_auth_param(schemedata, "nonce", nonce, sizeof(nonce));
+ cups_auth_param(schemedata, "realm", realm, sizeof(realm));
+
+ for (i = 0; i < 64; i ++)
+ cnonce[i] = "0123456789ABCDEF"[CUPS_RAND() & 15];
+ cnonce[64] = '\0';
+
+ if (cups_auth_param(schemedata, "algorithm", algorithm, sizeof(algorithm)))
+ {
+ /*
+ * Follow RFC 2617/7616...
+ */
- httpGetSubField(http, HTTP_FIELD_WWW_AUTHENTICATE, "realm", realm);
- httpGetSubField(http, HTTP_FIELD_WWW_AUTHENTICATE, "nonce", nonce);
+ if (!_cups_strcasecmp(algorithm, "MD5"))
+ {
+ /*
+ * RFC 2617 Digest with MD5
+ */
- httpMD5(cupsUser(), realm, strchr(http->userpass, ':') + 1, encode);
- httpMD5Final(nonce, method, resource, encode);
- snprintf(digest, sizeof(digest),
- "username=\"%s\", realm=\"%s\", nonce=\"%s\", uri=\"%s\", "
- "response=\"%s\"", cupsUser(), realm, nonce, resource, encode);
- httpSetAuthString(http, "Digest", digest);
+ hashalg = "md5";
+ }
+ else if (!_cups_strcasecmp(algorithm, "SHA-256"))
+ {
+ /*
+ * RFC 7616 Digest with SHA-256
+ */
+
+ hashalg = "sha2-256";
+ }
+ else
+ {
+ /*
+ * Some other algorithm we don't support, skip this one...
+ */
+
+ continue;
+ }
+
+ /*
+ * Calculate digest value...
+ */
+
+ /* H(A1) = H(username:realm:password) */
+ snprintf(temp, sizeof(temp), "%s:%s:%s", cupsUser(), realm, strchr(http->userpass, ':') + 1);
+ hashsize = (size_t)cupsHashData(hashalg, (unsigned char *)temp, strlen(temp), hash, sizeof(hash));
+ cupsHashString(hash, hashsize, ha1, sizeof(ha1));
+
+ /* H(A2) = H(method:uri) */
+ snprintf(temp, sizeof(temp), "%s:%s", method, resource);
+ hashsize = (size_t)cupsHashData(hashalg, (unsigned char *)temp, strlen(temp), hash, sizeof(hash));
+ cupsHashString(hash, hashsize, ha2, sizeof(ha2));
+
+ /* H(data) = H(nonce:nc:cnonce:qop:H(A2)) */
+ snprintf(temp, sizeof(temp), "%s:%08x:%s:auth:%s", nonce, http->nonce_count, cnonce, ha2);
+ hashsize = (size_t)cupsHashData(hashalg, (unsigned char *)temp, strlen(temp), hash, sizeof(hash));
+ cupsHashString(hash, hashsize, hdata, sizeof(hdata));
+
+ /* KD = H(H(A1):H(data)) */
+ snprintf(temp, sizeof(temp), "%s:%s", ha1, hdata);
+ hashsize = (size_t)cupsHashData(hashalg, (unsigned char *)temp, strlen(temp), hash, sizeof(hash));
+ cupsHashString(hash, hashsize, kd, sizeof(kd));
+
+ /* Pass the RFC 2617/7616 WWW-Authenticate header */
+ if (opaque[0])
+ snprintf(digest, sizeof(digest), "username=\"%s\", realm=\"%s\", nonce=\"%s\", algorithm=%s, qop=auth, opaque=\"%s\", cnonce=\"%s\", nc=%08x, uri=\"%s\", response=\"%s\"", cupsUser(), realm, nonce, algorithm, opaque, cnonce, http->nonce_count, resource, kd);
+ else
+ snprintf(digest, sizeof(digest), "username=\"%s\", realm=\"%s\", nonce=\"%s\", algorithm=%s, qop=auth, cnonce=\"%s\", nc=%08x, uri=\"%s\", response=\"%s\"", cupsUser(), realm, nonce, algorithm, cnonce, http->nonce_count, resource, kd);
+ }
+ else
+ {
+ /*
+ * Use old RFC 2069 Digest method...
+ */
+
+ /* H(A1) = H(username:realm:password) */
+ snprintf(temp, sizeof(temp), "%s:%s:%s", cupsUser(), realm, strchr(http->userpass, ':') + 1);
+ hashsize = (size_t)cupsHashData("md5", (unsigned char *)temp, strlen(temp), hash, sizeof(hash));
+ cupsHashString(hash, hashsize, ha1, sizeof(ha1));
+
+ /* H(A2) = H(method:uri) */
+ snprintf(temp, sizeof(temp), "%s:%s", method, resource);
+ hashsize = (size_t)cupsHashData("md5", (unsigned char *)temp, strlen(temp), hash, sizeof(hash));
+ cupsHashString(hash, hashsize, ha2, sizeof(ha2));
+
+ /* KD = H(H(A1):nonce:H(A2)) */
+ snprintf(temp, sizeof(temp), "%s:%s:%s", ha1, nonce, ha2);
+ hashsize = (size_t)cupsHashData("md5", (unsigned char *)temp, strlen(temp), hash, sizeof(hash));
+ cupsHashString(hash, hashsize, kd, sizeof(kd));
+
+ /* Pass the RFC 2069 WWW-Authenticate header */
+ snprintf(digest, sizeof(digest), "username=\"%s\", realm=\"%s\", nonce=\"%s\", uri=\"%s\", response=\"%s\"", cupsUser(), realm, nonce, resource, kd);
+ }
+
+ httpSetAuthString(http, "Digest", digest);
+ }
+ }
+
+ if (http->authstring)
+ {
+ DEBUG_printf(("1cupsDoAuthentication: authstring=\"%s\"", http->authstring));
+
+ return (0);
}
else
{
- DEBUG_printf(("1cupsDoAuthentication: Unknown auth type: \"%s\"",
- www_auth));
+ DEBUG_printf(("1cupsDoAuthentication: Unknown auth type: \"%s\"", www_auth));
http->status = HTTP_STATUS_CUPS_AUTHORIZATION_CANCELED;
+
return (-1);
}
-
- DEBUG_printf(("1cupsDoAuthentication: authstring=\"%s\"", http->authstring));
-
- return (0);
}
GSS_C_NO_BUFFER, &http->gssmech,
&output_token, NULL, NULL);
-#ifdef HAVE_GSS_ACQUIRE_CRED_EX_F
+# ifdef HAVE_GSS_ACQUIRE_CRED_EX_F
if (major_status == GSS_S_NO_CRED)
{
/*
}
}
}
-#endif /* HAVE_GSS_ACQUIRED_CRED_EX_F */
+# endif /* HAVE_GSS_ACQUIRED_CRED_EX_F */
if (GSS_ERROR(major_status))
{
return (-1);
}
-#ifdef DEBUG
+# ifdef DEBUG
else if (major_status == GSS_S_CONTINUE_NEEDED)
cups_gss_printf(major_status, minor_status,
"_cupsSetNegotiateAuthString: Continuation needed!");
-#endif /* DEBUG */
+# endif /* DEBUG */
if (output_token.length > 0 && output_token.length <= 65536)
{
return (0);
}
+#endif /* HAVE_GSSAPI */
+
+
+/*
+ * 'cups_auth_find()' - Find the named WWW-Authenticate scheme.
+ *
+ * The "www_authenticate" parameter points to the current position in the header.
+ *
+ * Returns @code NULL@ if the auth scheme is not present.
+ */
+
+static const char * /* O - Start of matching scheme or @code NULL@ if not found */
+cups_auth_find(const char *www_authenticate, /* I - Pointer into WWW-Authenticate header */
+ const char *scheme) /* I - Authentication scheme */
+{
+ size_t schemelen = strlen(scheme); /* Length of scheme */
+
+
+ DEBUG_printf(("8cups_auth_find(www_authenticate=\"%s\", scheme=\"%s\"(%d))", www_authenticate, scheme, (int)schemelen));
+
+ while (*www_authenticate)
+ {
+ /*
+ * Skip leading whitespace and commas...
+ */
+
+ DEBUG_printf(("9cups_auth_find: Before whitespace: \"%s\"", www_authenticate));
+ while (isspace(*www_authenticate & 255) || *www_authenticate == ',')
+ www_authenticate ++;
+ DEBUG_printf(("9cups_auth_find: After whitespace: \"%s\"", www_authenticate));
+
+ /*
+ * See if this is "Scheme" followed by whitespace or the end of the string.
+ */
+
+ if (!strncmp(www_authenticate, scheme, schemelen) && (isspace(www_authenticate[schemelen] & 255) || !www_authenticate[schemelen]))
+ {
+ /*
+ * Yes, this is the start of the scheme-specific information...
+ */
+
+ DEBUG_printf(("9cups_auth_find: Returning \"%s\".", www_authenticate));
+
+ return (www_authenticate);
+ }
+
+ /*
+ * Skip the scheme name or param="value" string...
+ */
+
+ while (!isspace(*www_authenticate & 255) && *www_authenticate)
+ {
+ if (*www_authenticate == '\"')
+ {
+ /*
+ * Skip quoted value...
+ */
+
+ www_authenticate ++;
+ while (*www_authenticate && *www_authenticate != '\"')
+ www_authenticate ++;
+
+ DEBUG_printf(("9cups_auth_find: After quoted: \"%s\"", www_authenticate));
+ }
+
+ www_authenticate ++;
+ }
+
+ DEBUG_printf(("9cups_auth_find: After skip: \"%s\"", www_authenticate));
+ }
+
+ DEBUG_puts("9cups_auth_find: Returning NULL.");
+
+ return (NULL);
+}
+
+
+/*
+ * 'cups_auth_param()' - Copy the value for the named authentication parameter,
+ * if present.
+ */
+
+static const char * /* O - Parameter value or @code NULL@ if not present */
+cups_auth_param(const char *scheme, /* I - Pointer to auth data */
+ const char *name, /* I - Name of parameter */
+ char *value, /* I - Value buffer */
+ size_t valsize) /* I - Size of value buffer */
+{
+ char *valptr = value, /* Pointer into value buffer */
+ *valend = value + valsize - 1; /* Pointer to end of buffer */
+ size_t namelen = strlen(name); /* Name length */
+ int param; /* Is this a parameter? */
+
+
+ DEBUG_printf(("8cups_auth_param(scheme=\"%s\", name=\"%s\", value=%p, valsize=%d)", scheme, name, (void *)value, (int)valsize));
+
+ while (!isspace(*scheme & 255) && *scheme)
+ scheme ++;
+
+ while (*scheme)
+ {
+ while (isspace(*scheme & 255) || *scheme == ',')
+ scheme ++;
+
+ if (!strncmp(scheme, name, namelen) && scheme[namelen] == '=')
+ {
+ /*
+ * Found the parameter, copy the value...
+ */
+
+ scheme += namelen + 1;
+ if (*scheme == '\"')
+ {
+ scheme ++;
+
+ while (*scheme && *scheme != '\"')
+ {
+ if (valptr < valend)
+ *valptr++ = *scheme;
+
+ scheme ++;
+ }
+ }
+ else
+ {
+ while (*scheme && strchr("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~+/=", *scheme))
+ {
+ if (valptr < valend)
+ *valptr++ = *scheme;
+
+ scheme ++;
+ }
+ }
+
+ *valptr = '\0';
+
+ DEBUG_printf(("9cups_auth_param: Returning \"%s\".", value));
+
+ return (value);
+ }
+
+ /*
+ * Skip the param=value string...
+ */
+
+ param = 0;
+
+ while (!isspace(*scheme & 255) && *scheme)
+ {
+ if (*scheme == '=')
+ param = 1;
+ else if (*scheme == '\"')
+ {
+ /*
+ * Skip quoted value...
+ */
+
+ scheme ++;
+ while (*scheme && *scheme != '\"')
+ scheme ++;
+ }
+
+ scheme ++;
+ }
+
+ /*
+ * If this wasn't a parameter, we are at the end of this scheme's
+ * parameters...
+ */
+
+ if (!param)
+ break;
+ }
+
+ *value = '\0';
+
+ DEBUG_puts("9cups_auth_param: Returning NULL.");
+
+ return (NULL);
+}
+/*
+ * 'cups_auth_scheme()' - Get the (next) WWW-Authenticate scheme.
+ *
+ * The "www_authenticate" parameter points to the current position in the header.
+ *
+ * Returns @code NULL@ if there are no (more) auth schemes present.
+ */
+
+static const char * /* O - Start of scheme or @code NULL@ if not found */
+cups_auth_scheme(const char *www_authenticate, /* I - Pointer into WWW-Authenticate header */
+ char *scheme, /* I - Scheme name buffer */
+ size_t schemesize) /* I - Size of buffer */
+{
+ const char *start; /* Start of scheme data */
+ char *sptr = scheme, /* Pointer into scheme buffer */
+ *send = scheme + schemesize - 1;/* End of scheme buffer */
+ int param; /* Is this a parameter? */
+
+
+ DEBUG_printf(("8cups_auth_scheme(www_authenticate=\"%s\", scheme=%p, schemesize=%d)", www_authenticate, (void *)scheme, (int)schemesize));
+
+ while (*www_authenticate)
+ {
+ /*
+ * Skip leading whitespace and commas...
+ */
+
+ while (isspace(*www_authenticate & 255) || *www_authenticate == ',')
+ www_authenticate ++;
+
+ /*
+ * Parse the scheme name or param="value" string...
+ */
+
+ for (sptr = scheme, start = www_authenticate, param = 0; *www_authenticate && !isspace(*www_authenticate & 255); www_authenticate ++)
+ {
+ if (*www_authenticate == '=')
+ param = 1;
+ else if (!param && sptr < send)
+ *sptr++ = *www_authenticate;
+ else if (*www_authenticate == '\"')
+ {
+ /*
+ * Skip quoted value...
+ */
+
+ www_authenticate ++;
+ while (*www_authenticate && *www_authenticate != '\"')
+ www_authenticate ++;
+ }
+ }
+
+ if (sptr > scheme && !param)
+ {
+ *sptr = '\0';
+
+ DEBUG_printf(("9cups_auth_scheme: Returning \"%s\".", start));
+
+ return (start);
+ }
+ }
+
+ *scheme = '\0';
+
+ DEBUG_puts("9cups_auth_scheme: Returning NULL.");
+
+ return (NULL);
+}
+
+
+#ifdef HAVE_GSSAPI
# ifdef HAVE_GSS_ACQUIRE_CRED_EX_F
/*
* 'cups_gss_acquire()' - Kerberos credentials callback.
FILE *fp; /* Certificate file */
char trc[16], /* Try Root Certificate parameter */
filename[1024]; /* Certificate filename */
+ const char *www_auth, /* WWW-Authenticate header */
+ *schemedata; /* Data for the named auth scheme */
_cups_globals_t *cg = _cupsGlobals(); /* Global data */
# if defined(HAVE_AUTHORIZATION_H)
OSStatus status; /* Status */
* See if we are accessing localhost...
*/
- if (!httpAddrLocalhost(http->hostaddr) &&
- _cups_strcasecmp(http->hostname, "localhost") != 0)
+ if (!httpAddrLocalhost(http->hostaddr) && _cups_strcasecmp(http->hostname, "localhost") != 0)
{
DEBUG_puts("8cups_local_auth: Not a local connection!");
return (1);
}
+ www_auth = httpGetField(http, HTTP_FIELD_WWW_AUTHENTICATE);
+
# if defined(HAVE_AUTHORIZATION_H)
/*
* Delete any previous authorization reference...
http->auth_ref = NULL;
}
- if (!getenv("GATEWAY_INTERFACE") &&
- httpGetSubField2(http, HTTP_FIELD_WWW_AUTHENTICATE, "authkey",
- auth_key, sizeof(auth_key)))
+ if (!getenv("GATEWAY_INTERFACE") && (schemedata = cups_auth_find(www_auth, "AuthRef")) != NULL && cups_auth_param(schemedata, "key", auth_key, sizeof(auth_key)))
{
- status = AuthorizationCreate(NULL, kAuthorizationEmptyEnvironment,
- kAuthorizationFlagDefaults, &http->auth_ref);
+ status = AuthorizationCreate(NULL, kAuthorizationEmptyEnvironment, kAuthorizationFlagDefaults, &http->auth_ref);
if (status != errAuthorizationSuccess)
{
DEBUG_printf(("8cups_local_auth: AuthorizationCreate() returned %d (%s)",
}
# endif /* HAVE_AUTHORIZATION_H */
+# ifdef HAVE_GSSAPI
+ if (cups_auth_find(www_auth, "Negotiate"))
+ return (1);
+# endif /* HAVE_GSSAPI */
+# ifdef HAVE_AUTHORIZATION_H
+ if (cups_auth_find(www_auth, "AuthRef"))
+ return (1);
+# endif /* HAVE_AUTHORIZATION_H */
+
# if defined(SO_PEERCRED) && defined(AF_LOCAL)
/*
* See if we can authenticate using the peer credentials provided over a
* information...
*/
- if (
-# ifdef HAVE_GSSAPI
- _cups_strncasecmp(http->fields[HTTP_FIELD_WWW_AUTHENTICATE], "Negotiate", 9) &&
-# endif /* HAVE_GSSAPI */
-# ifdef HAVE_AUTHORIZATION_H
- !httpGetSubField2(http, HTTP_FIELD_WWW_AUTHENTICATE, "authkey",
- auth_key, sizeof(auth_key)) &&
-# endif /* HAVE_AUTHORIZATION_H */
- http->hostaddr->addr.sa_family == AF_LOCAL &&
- !getenv("GATEWAY_INTERFACE")) /* Not via CGI programs... */
+ if (http->hostaddr->addr.sa_family == AF_LOCAL &&
+ !getenv("GATEWAY_INTERFACE") && /* Not via CGI programs... */
+ cups_auth_find(www_auth, "PeerCred"))
{
/*
* Verify that the current cupsUser() matches the current UID...
}
# endif /* SO_PEERCRED && AF_LOCAL */
+ if ((schemedata = cups_auth_find(www_auth, "Local")) == NULL)
+ return (1);
+
/*
* Try opening a certificate file for this PID. If that fails,
* try the root certificate...
* No certificate for this PID; see if we can get the root certificate...
*/
- DEBUG_printf(("9cups_local_auth: Unable to open file %s: %s",
- filename, strerror(errno)));
+ DEBUG_printf(("9cups_local_auth: Unable to open file %s: %s", filename, strerror(errno)));
-# ifdef HAVE_GSSAPI
- if (!_cups_strncasecmp(http->fields[HTTP_FIELD_WWW_AUTHENTICATE], "Negotiate", 9))
- {
- /*
- * Kerberos required, don't try the root certificate...
- */
-
- return (1);
- }
-# endif /* HAVE_GSSAPI */
-
-# ifdef HAVE_AUTHORIZATION_H
- if (httpGetSubField2(http, HTTP_FIELD_WWW_AUTHENTICATE, "authkey",
- auth_key, sizeof(auth_key)))
- {
- /*
- * Don't use the root certificate as a replacement for an authkey...
- */
-
- return (1);
- }
-# endif /* HAVE_AUTHORIZATION_H */
- if (!httpGetSubField2(http, HTTP_FIELD_WWW_AUTHENTICATE, "trc", trc,
- sizeof(trc)))
+ if (!cups_auth_param(schemedata, "trc", trc, sizeof(trc)))
{
/*
* Scheduler doesn't want us to use the root certificate...
/*
* API definitions for CUPS.
*
- * Copyright 2007-2017 by Apple Inc.
+ * Copyright 2007-2018 by Apple Inc.
* Copyright 1997-2007 by Easy Software Products.
*
* These coded instructions, statements, and computer programs are the
* Constants...
*/
-# define CUPS_VERSION 2.0206
+# define CUPS_VERSION 2.0207
# define CUPS_VERSION_MAJOR 2
# define CUPS_VERSION_MINOR 2
-# define CUPS_VERSION_PATCH 6
+# define CUPS_VERSION_PATCH 7
# define CUPS_BC_FD 3
/* Back-channel file descriptor for
/*
* Hashing function for CUPS.
*
- * Copyright 2015-2016 by Apple Inc.
+ * Copyright 2015-2017 by Apple Inc.
*
* These coded instructions, statements, and computer programs are the
* property of Apple Inc. and are protected by Federal copyright
# include <CommonCrypto/CommonDigest.h>
#elif defined(HAVE_GNUTLS)
# include <gnutls/crypto.h>
+#else
+# include "md5-private.h"
#endif /* __APPLE__ */
}
#ifdef __APPLE__
- if (!strcmp(algorithm, "sha"))
+ if (!strcmp(algorithm, "md5"))
+ {
+ /*
+ * MD5 (deprecated but widely used...)
+ */
+
+ CC_MD5_CTX ctx; /* MD5 context */
+
+ if (hashsize < CC_MD5_DIGEST_LENGTH)
+ goto too_small;
+
+ CC_MD5_Init(&ctx);
+ CC_MD5_Update(&ctx, data, (CC_LONG)datalen);
+ CC_MD5_Final(hash, &ctx);
+
+ return (CC_MD5_DIGEST_LENGTH);
+ }
+ else if (!strcmp(algorithm, "sha"))
{
/*
* SHA-1...
unsigned char temp[64]; /* Temporary hash buffer */
size_t tempsize = 0; /* Truncate to this size? */
- if (!strcmp(algorithm, "sha"))
+ if (!strcmp(algorithm, "md5"))
+ alg = GNUTLS_DIG_MD5;
+ else if (!strcmp(algorithm, "sha"))
alg = GNUTLS_DIG_SHA1;
else if (!strcmp(algorithm, "sha2-224"))
alg = GNUTLS_DIG_SHA224;
#else
/*
- * No hash support without CommonCrypto or GNU TLS...
+ * No hash support beyond MD5 without CommonCrypto or GNU TLS...
*/
- if (hashsize < 64)
+ if (!strcmp(algorithm, "md5"))
+ {
+ _cups_md5_state_t state; /* MD5 state info */
+
+ _cupsMD5Init(&state);
+ _cupsMD5Append(&state, data, datalen);
+ _cupsMD5Finish(&state, hash);
+
+ return (16);
+ }
+ else if (hashsize < 64)
goto too_small;
#endif /* __APPLE__ */
_cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Hash buffer too small."), 1);
return (-1);
}
+
+
+/*
+ * 'cupsHashString()' - Format a hash value as a hexadecimal string.
+ *
+ * The passed buffer must be at least 2 * hashsize + 1 characters in length.
+ */
+
+const char * /* O - Formatted string */
+cupsHashString(
+ const unsigned char *hash, /* I - Hash */
+ size_t hashsize, /* I - Size of hash */
+ char *buffer, /* I - String buffer */
+ size_t bufsize) /* I - Size of string buffer */
+{
+ char *bufptr = buffer; /* Pointer into buffer */
+ static const char *hex = "0123456789abcdef";
+ /* Hex characters (lowercase!) */
+
+
+ /*
+ * Range check input...
+ */
+
+ if (!hash || hashsize < 1 || !buffer || bufsize < (2 * hashsize + 1))
+ {
+ if (buffer)
+ *buffer = '\0';
+ return (NULL);
+ }
+
+ /*
+ * Loop until we've converted the whole hash...
+ */
+
+ while (hashsize > 0)
+ {
+ *bufptr++ = hex[*hash >> 4];
+ *bufptr++ = hex[*hash & 15];
+
+ hash ++;
+ hashsize --;
+ }
+
+ *bufptr = '\0';
+
+ return (buffer);
+}
/*
* Private HTTP definitions for CUPS.
*
- * Copyright 2007-2017 by Apple Inc.
+ * Copyright 2007-2018 by Apple Inc.
* Copyright 1997-2007 by Easy Software Products, all rights reserved.
*
* These coded instructions, statements, and computer programs are the
# endif /* __APPLE__ && !_SOCKLEN_T */
# include <cups/http.h>
-# include "md5-private.h"
# include "ipp-private.h"
# ifdef HAVE_GNUTLS
# define _HTTP_TLS_NONE 0 /* No TLS options */
# define _HTTP_TLS_ALLOW_RC4 1 /* Allow RC4 cipher suites */
-# define _HTTP_TLS_ALLOW_SSL3 2 /* Allow SSL 3.0 */
-# define _HTTP_TLS_ALLOW_DH 4 /* Allow DH/DHE key negotiation */
-# define _HTTP_TLS_DENY_TLS10 16 /* Deny TLS 1.0 */
-# define _HTTP_TLS_DENY_CBC 32 /* Deny CBC cipher suites */
-# define _HTTP_TLS_ONLY_TLS10 64 /* Only use TLS 1.0 */
+# define _HTTP_TLS_ALLOW_DH 2 /* Allow DH/DHE key negotiation */
+# define _HTTP_TLS_DENY_CBC 4 /* Deny CBC cipher suites */
# define _HTTP_TLS_SET_DEFAULT 128 /* Setting the default TLS options */
+# define _HTTP_TLS_SSL3 0 /* Min/max version is SSL/3.0 */
+# define _HTTP_TLS_1_0 1 /* Min/max version is TLS/1.0 */
+# define _HTTP_TLS_1_1 2 /* Min/max version is TLS/1.1 */
+# define _HTTP_TLS_1_2 3 /* Min/max version is TLS/1.2 */
+# define _HTTP_TLS_1_3 4 /* Min/max version is TLS/1.3 */
+# define _HTTP_TLS_MAX 5 /* Highest known TLS version */
+
/*
* Types and functions for SSL support...
char buffer[HTTP_MAX_BUFFER];
/* Buffer for incoming data */
int _auth_type; /* Authentication in use (deprecated) */
- _cups_md5_state_t md5_state; /* MD5 state */
+ unsigned char _md5_state[88]; /* MD5 state (deprecated) */
char nonce[HTTP_MAX_VALUE];
/* Nonce value */
- int nonce_count; /* Nonce count */
+ unsigned nonce_count; /* Nonce count */
http_tls_t tls; /* TLS state information */
http_encryption_t encryption; /* Encryption requirements */
extern size_t _httpTLSPending(http_t *http);
extern int _httpTLSRead(http_t *http, char *buf, int len);
extern int _httpTLSSetCredentials(http_t *http);
-extern void _httpTLSSetOptions(int options);
+extern void _httpTLSSetOptions(int options, int min_version, int max_version);
extern int _httpTLSStart(http_t *http);
extern void _httpTLSStop(http_t *http);
extern int _httpTLSWrite(http_t *http, const char *buf, int len);
size_t bufsize) /* I - Size of buffer */
{
char data[1024]; /* Source string for MD5 */
- _cups_md5_state_t md5state; /* MD5 state */
unsigned char md5sum[16]; /* MD5 digest/sum */
port, name ? name : server, number,
(unsigned)CUPS_RAND() & 0xffff, (unsigned)CUPS_RAND() & 0xffff);
- _cupsMD5Init(&md5state);
- _cupsMD5Append(&md5state, (unsigned char *)data, (int)strlen(data));
- _cupsMD5Finish(&md5state, md5sum);
+ cupsHashData("md5", (unsigned char *)data, strlen(data), md5sum, sizeof(md5sum));
/*
* Generate the UUID from the MD5...
case HTTP_STATUS_MOVED_PERMANENTLY :
s = _("Moved Permanently");
break;
+ case HTTP_STATUS_FOUND :
+ s = _("Found");
+ break;
case HTTP_STATUS_SEE_OTHER :
s = _("See Other");
break;
/*
* HTTP routines for CUPS.
*
- * Copyright 2007-2017 by Apple Inc.
+ * Copyright 2007-2018 by Apple Inc.
* Copyright 1997-2007 by Easy Software Products, all rights reserved.
*
* This file contains Kerberos support code, copyright 2006 by
* Local functions...
*/
+static void http_add_field(http_t *http, http_field_t field, const char *value, int append);
#ifdef HAVE_LIBZ
static void http_content_coding_finish(http_t *http);
static void http_content_coding_start(http_t *http,
value == NULL)
return;
- switch (field)
- {
- case HTTP_FIELD_ACCEPT_ENCODING :
- if (http->accept_encoding)
- _cupsStrFree(http->accept_encoding);
-
- http->accept_encoding = _cupsStrAlloc(value);
- break;
-
- case HTTP_FIELD_ALLOW :
- if (http->allow)
- _cupsStrFree(http->allow);
-
- http->allow = _cupsStrAlloc(value);
- break;
-
- case HTTP_FIELD_SERVER :
- if (http->server)
- _cupsStrFree(http->server);
-
- 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;
- }
-
- if (field == HTTP_FIELD_AUTHORIZATION)
- {
- /*
- * Special case for Authorization: as its contents can be
- * longer than HTTP_MAX_VALUE
- */
-
- if (http->field_authorization)
- free(http->field_authorization);
-
- http->field_authorization = strdup(value);
- }
- else if (field == HTTP_FIELD_HOST)
- {
- /*
- * Special-case for Host: as we don't want a trailing "." on the hostname and
- * need to bracket IPv6 numeric addresses.
- */
-
- char *ptr = strchr(value, ':');
-
- if (value[0] != '[' && ptr && strchr(ptr + 1, ':'))
- {
- /*
- * Bracket IPv6 numeric addresses...
- *
- * This is slightly inefficient (basically copying twice), but is an edge
- * case and not worth optimizing...
- */
-
- snprintf(http->fields[HTTP_FIELD_HOST],
- sizeof(http->fields[HTTP_FIELD_HOST]), "[%s]", value);
- }
- else
- {
- /*
- * Check for a trailing dot on the hostname...
- */
-
- ptr = http->fields[HTTP_FIELD_HOST];
-
- if (*ptr)
- {
- ptr += strlen(ptr) - 1;
-
- if (*ptr == '.')
- *ptr = '\0';
- }
- }
- }
-#ifdef HAVE_LIBZ
- else if (field == HTTP_FIELD_CONTENT_ENCODING &&
- http->data_encoding != HTTP_ENCODING_FIELDS)
- {
- DEBUG_puts("1httpSetField: Calling http_content_coding_start.");
- http_content_coding_start(http, value);
- }
-#endif /* HAVE_LIBZ */
+ http_add_field(http, field, value, 0);
}
httpSetCookie(http, value);
}
else if ((field = httpFieldValue(line)) != HTTP_FIELD_UNKNOWN)
- httpSetField(http, field, value);
+ http_add_field(http, field, value, 1);
#ifdef DEBUG
else
DEBUG_printf(("1_httpUpdate: unknown field %s seen!", line));
}
+/*
+ * 'http_add_field()' - Add a value for a HTTP field, appending if needed.
+ */
+
+static void
+http_add_field(http_t *http, /* I - HTTP connection */
+ http_field_t field, /* I - HTTP field */
+ const char *value, /* I - Value string */
+ int append) /* I - Append value? */
+{
+ char newvalue[1024]; /* New value string */
+ const char *oldvalue; /* Old field value */
+
+
+
+ /*
+ * Optionally append the new value to the existing one...
+ */
+
+ if (append && field != HTTP_FIELD_ACCEPT_ENCODING && field != HTTP_FIELD_ACCEPT_LANGUAGE && field != HTTP_FIELD_ACCEPT_RANGES && field != HTTP_FIELD_ALLOW && field != HTTP_FIELD_LINK && field != HTTP_FIELD_TRANSFER_ENCODING && field != HTTP_FIELD_UPGRADE && field != HTTP_FIELD_WWW_AUTHENTICATE)
+ append = 0;
+
+ if (field == HTTP_FIELD_HOST)
+ {
+ /*
+ * Special-case for Host: as we don't want a trailing "." on the hostname and
+ * need to bracket IPv6 numeric addresses.
+ */
+
+ char *ptr = strchr(value, ':');
+
+ if (value[0] != '[' && ptr && strchr(ptr + 1, ':'))
+ {
+ /*
+ * Bracket IPv6 numeric addresses...
+ */
+
+ snprintf(newvalue, sizeof(newvalue), "[%s]", value);
+ value = newvalue;
+ }
+ else if (*value && value[strlen(value) - 1] == '.')
+ {
+ /*
+ * Strip the trailing dot on the hostname...
+ */
+
+ strlcpy(newvalue, value, sizeof(newvalue));
+ newvalue[strlen(newvalue) - 1] = '\0';
+ value = newvalue;
+ }
+ }
+ else if (append && *value && *(oldvalue = httpGetField(http, field)))
+ {
+ snprintf(newvalue, sizeof(newvalue), "%s, %s", oldvalue, value);
+ value = newvalue;
+ }
+
+ /*
+ * Save the new value...
+ */
+
+ switch (field)
+ {
+ case HTTP_FIELD_ACCEPT_ENCODING :
+ if (http->accept_encoding)
+ _cupsStrFree(http->accept_encoding);
+
+ http->accept_encoding = _cupsStrAlloc(value);
+ break;
+
+ case HTTP_FIELD_ALLOW :
+ if (http->allow)
+ _cupsStrFree(http->allow);
+
+ http->allow = _cupsStrAlloc(value);
+ break;
+
+ case HTTP_FIELD_SERVER :
+ if (http->server)
+ _cupsStrFree(http->server);
+
+ http->server = _cupsStrAlloc(value);
+ break;
+
+ default :
+ strlcpy(http->fields[field], value, HTTP_MAX_VALUE);
+ break;
+ }
+
+ if (field == HTTP_FIELD_AUTHORIZATION)
+ {
+ /*
+ * Special case for Authorization: as its contents can be
+ * longer than HTTP_MAX_VALUE
+ */
+
+ if (http->field_authorization)
+ free(http->field_authorization);
+
+ http->field_authorization = strdup(value);
+ }
+#ifdef HAVE_LIBZ
+ else if (field == HTTP_FIELD_CONTENT_ENCODING &&
+ http->data_encoding != HTTP_ENCODING_FIELDS)
+ {
+ DEBUG_puts("1http_add_field: Calling http_content_coding_start.");
+ http_content_coding_start(http, value);
+ }
+#endif /* HAVE_LIBZ */
+}
+
+
#ifdef HAVE_LIBZ
/*
* 'http_content_coding_finish()' - Finish doing any content encoding.
DEBUG_printf(("http_read(http=%p, buffer=%p, length=" CUPS_LLFMT ")", (void *)http, (void *)buffer, CUPS_LLCAST length));
- if (!http->blocking)
+ if (!http->blocking || http->timeout_value > 0.0)
{
while (!httpWait(http, http->wait_value))
{
{
DEBUG_printf(("3http_write: About to write %d bytes.", (int)length));
- if (http->timeout_cb)
+ if (http->timeout_value > 0.0)
{
#ifdef HAVE_POLL
struct pollfd pfd; /* Polled file descriptor */
http->error = errno;
return (-1);
}
- else if (nfds == 0 && !(*http->timeout_cb)(http, http->timeout_data))
+ else if (nfds == 0 && (!http->timeout_cb || !(*http->timeout_cb)(http, http->timeout_data)))
{
#ifdef WIN32
http->error = WSAEWOULDBLOCK;
HTTP_STATUS_MULTIPLE_CHOICES = 300, /* Multiple files match request */
HTTP_STATUS_MOVED_PERMANENTLY, /* Document has moved permanently */
- HTTP_STATUS_MOVED_TEMPORARILY, /* Document has moved temporarily */
- HTTP_STATUS_SEE_OTHER, /* See this other link... */
+ HTTP_STATUS_FOUND, /* Document was found at a different URI */
+ HTTP_STATUS_SEE_OTHER, /* See this other link */
HTTP_STATUS_NOT_MODIFIED, /* File not modified */
HTTP_STATUS_USE_PROXY, /* Must use a proxy to access this URI */
+ HTTP_STATUS_TEMPORARY_REDIRECT = 307, /* Temporary redirection */
HTTP_STATUS_BAD_REQUEST = 400, /* Bad request */
HTTP_STATUS_UNAUTHORIZED, /* Unauthorized to access host */
HTTP_STATUS_CUPS_PKI_ERROR, /* Error negotiating a secure connection @since CUPS 1.5/macOS 10.7@ */
HTTP_STATUS_CUPS_WEBIF_DISABLED /* Web interface is disabled @private@ */
+# define HTTP_STATUS_MOVED_TEMPORARILY HTTP_STATUS_FOUND /* Renamed in RFC 7231 */
+
# ifndef _CUPS_NO_DEPRECATED
/* Old names for this enumeration */
# define HTTP_ERROR HTTP_STATUS_ERROR
/*
* Internet Printing Protocol support functions for CUPS.
*
- * Copyright 2007-2017 by Apple Inc.
- * Copyright 1997-2007 by Easy Software Products, all rights reserved.
+ * Copyright © 2007-2018 by Apple Inc.
+ * Copyright © 1997-2007 by Easy Software Products, all rights reserved.
*
* These coded instructions, statements, and computer programs are the
* property of Apple Inc. and are protected by Federal copyright
"feed-orientation-supported",
"finishings",
"finishings-col",
+ "finishings-col-database",
"finishings-col-default",
+ "finishings-col-ready",
"finishings-col-supported",
"finishings-default",
+ "finishings-ready",
"finishings-supported",
"font-name-requested",
"font-name-requested-default",
"media-bottom-margin-supported",
"media-col",
"media-col-default",
+ "media-col-ready",
"media-col-supported",
"media-color-supported",
"media-default",
"media-left-margin-supported",
"media-order-count-supported",
"media-pre-printed-supported",
+ "media-ready",
"media-recycled-supported",
"media-right-margin-supported",
"media-size-supported",
"feed-orientation-supported",
"finishings",
"finishings-col",
+ "finishings-col-database",
"finishings-col-default",
+ "finishings-col-ready",
"finishings-col-supported",
"finishings-default",
+ "finishings-ready",
"finishings-supported",
"font-name-requested",
"font-name-requested-default",
"media-bottom-margin-supported",
"media-col",
"media-col-default",
+ "media-col-ready",
"media-col-supported",
"media-color-supported",
"media-default",
"media-left-margin-supported",
"media-order-count-supported",
"media-pre-printed-supported",
+ "media-ready",
"media-recycled-supported",
"media-right-margin-supported",
"media-size-supported",
"job-page-limit", /* CUPS extension */
"job-password-encryption-supported",
"job-password-supported",
+ "job-presets-supported", /* IPP Presets */
"job-quota-period", /* CUPS extension */
"job-resolvers-supported",
"job-settable-attributes-supported",
"job-spooling-supported",
+ "job-triggers-supported", /* IPP Presets */
"jpeg-k-octets-supported", /* CUPS extension */
"jpeg-x-dimension-supported", /* CUPS extension */
"jpeg-y-dimension-supported", /* CUPS extension */
"marker-message", /* CUPS extension */
"marker-names", /* CUPS extension */
"marker-types", /* CUPS extension */
- "media-col-ready",
- "media-ready",
"member-names", /* CUPS extension */
"member-uris", /* CUPS extension */
"multiple-destination-uris-supported",/* IPP FaxOut */
"printer-charge-info",
"printer-charge-info-uri",
"printer-commands", /* CUPS extension */
+ "printer-config-change-date-time",
+ "printer-config-change-time",
"printer-current-time",
"printer-detailed-status-messages",
"printer-device-id",
{
char *temp; /* Temporary string */
_ipp_value_t *value; /* Current value */
+ ipp_tag_t value_tag; /* Value tag */
/*
* Range check input...
*/
+ if (attr && *attr)
+ value_tag = (*attr)->value_tag & IPP_TAG_CUPS_MASK;
+ else
+ value_tag = IPP_TAG_ZERO;
+
if (!ipp || !attr || !*attr ||
- ((*attr)->value_tag != IPP_TAG_TEXTLANG &&
- (*attr)->value_tag != IPP_TAG_NAMELANG &&
- ((*attr)->value_tag < IPP_TAG_TEXT ||
- (*attr)->value_tag > IPP_TAG_MIMETYPE)) ||
- element < 0 || element > (*attr)->num_values || !strvalue)
+ (value_tag < IPP_TAG_TEXT && value_tag != IPP_TAG_TEXTLANG &&
+ value_tag != IPP_TAG_NAMELANG) || value_tag > IPP_TAG_MIMETYPE ||
+ !strvalue)
return (0);
/*
/*
* Private MD5 implementation for CUPS.
*
- * Copyright 2007-2014 by Apple Inc.
+ * Copyright 2007-2017 by Apple Inc.
* Copyright 2005 by Easy Software Products
* Copyright (C) 1999 Aladdin Enterprises. All rights reserved.
*
#include "md5-private.h"
#include "string-private.h"
-#define T1 0xd76aa478
-#define T2 0xe8c7b756
-#define T3 0x242070db
-#define T4 0xc1bdceee
-#define T5 0xf57c0faf
-#define T6 0x4787c62a
-#define T7 0xa8304613
-#define T8 0xfd469501
-#define T9 0x698098d8
-#define T10 0x8b44f7af
-#define T11 0xffff5bb1
-#define T12 0x895cd7be
-#define T13 0x6b901122
-#define T14 0xfd987193
-#define T15 0xa679438e
-#define T16 0x49b40821
-#define T17 0xf61e2562
-#define T18 0xc040b340
-#define T19 0x265e5a51
-#define T20 0xe9b6c7aa
-#define T21 0xd62f105d
-#define T22 0x02441453
-#define T23 0xd8a1e681
-#define T24 0xe7d3fbc8
-#define T25 0x21e1cde6
-#define T26 0xc33707d6
-#define T27 0xf4d50d87
-#define T28 0x455a14ed
-#define T29 0xa9e3e905
-#define T30 0xfcefa3f8
-#define T31 0x676f02d9
-#define T32 0x8d2a4c8a
-#define T33 0xfffa3942
-#define T34 0x8771f681
-#define T35 0x6d9d6122
-#define T36 0xfde5380c
-#define T37 0xa4beea44
-#define T38 0x4bdecfa9
-#define T39 0xf6bb4b60
-#define T40 0xbebfbc70
-#define T41 0x289b7ec6
-#define T42 0xeaa127fa
-#define T43 0xd4ef3085
-#define T44 0x04881d05
-#define T45 0xd9d4d039
-#define T46 0xe6db99e5
-#define T47 0x1fa27cf8
-#define T48 0xc4ac5665
-#define T49 0xf4292244
-#define T50 0x432aff97
-#define T51 0xab9423a7
-#define T52 0xfc93a039
-#define T53 0x655b59c3
-#define T54 0x8f0ccc92
-#define T55 0xffeff47d
-#define T56 0x85845dd1
-#define T57 0x6fa87e4f
-#define T58 0xfe2ce6e0
-#define T59 0xa3014314
-#define T60 0x4e0811a1
-#define T61 0xf7537e82
-#define T62 0xbd3af235
-#define T63 0x2ad7d2bb
-#define T64 0xeb86d391
+#if !defined(__APPLE__) && !defined(HAVE_GNUTLS)
+# define T1 0xd76aa478
+# define T2 0xe8c7b756
+# define T3 0x242070db
+# define T4 0xc1bdceee
+# define T5 0xf57c0faf
+# define T6 0x4787c62a
+# define T7 0xa8304613
+# define T8 0xfd469501
+# define T9 0x698098d8
+# define T10 0x8b44f7af
+# define T11 0xffff5bb1
+# define T12 0x895cd7be
+# define T13 0x6b901122
+# define T14 0xfd987193
+# define T15 0xa679438e
+# define T16 0x49b40821
+# define T17 0xf61e2562
+# define T18 0xc040b340
+# define T19 0x265e5a51
+# define T20 0xe9b6c7aa
+# define T21 0xd62f105d
+# define T22 0x02441453
+# define T23 0xd8a1e681
+# define T24 0xe7d3fbc8
+# define T25 0x21e1cde6
+# define T26 0xc33707d6
+# define T27 0xf4d50d87
+# define T28 0x455a14ed
+# define T29 0xa9e3e905
+# define T30 0xfcefa3f8
+# define T31 0x676f02d9
+# define T32 0x8d2a4c8a
+# define T33 0xfffa3942
+# define T34 0x8771f681
+# define T35 0x6d9d6122
+# define T36 0xfde5380c
+# define T37 0xa4beea44
+# define T38 0x4bdecfa9
+# define T39 0xf6bb4b60
+# define T40 0xbebfbc70
+# define T41 0x289b7ec6
+# define T42 0xeaa127fa
+# define T43 0xd4ef3085
+# define T44 0x04881d05
+# define T45 0xd9d4d039
+# define T46 0xe6db99e5
+# define T47 0x1fa27cf8
+# define T48 0xc4ac5665
+# define T49 0xf4292244
+# define T50 0x432aff97
+# define T51 0xab9423a7
+# define T52 0xfc93a039
+# define T53 0x655b59c3
+# define T54 0x8f0ccc92
+# define T55 0xffeff47d
+# define T56 0x85845dd1
+# define T57 0x6fa87e4f
+# define T58 0xfe2ce6e0
+# define T59 0xa3014314
+# define T60 0x4e0811a1
+# define T61 0xf7537e82
+# define T62 0xbd3af235
+# define T63 0x2ad7d2bb
+# define T64 0xeb86d391
static void
_cups_md5_process(_cups_md5_state_t *pms, const unsigned char *data /*[64]*/)
c = pms->abcd[2], d = pms->abcd[3];
unsigned int t;
-#ifndef ARCH_IS_BIG_ENDIAN
-# define ARCH_IS_BIG_ENDIAN 1 /* slower, default implementation */
-#endif
-#if ARCH_IS_BIG_ENDIAN
+# ifndef ARCH_IS_BIG_ENDIAN
+# define ARCH_IS_BIG_ENDIAN 1 /* slower, default implementation */
+# endif
+# if ARCH_IS_BIG_ENDIAN
/*
* On big-endian machines, we must arrange the bytes in the right
X[i] = (unsigned)xp[0] + ((unsigned)xp[1] << 8) +
((unsigned)xp[2] << 16) + ((unsigned)xp[3] << 24);
-#else /* !ARCH_IS_BIG_ENDIAN */
+# else /* !ARCH_IS_BIG_ENDIAN */
/*
* On little-endian machines, we can process properly aligned data
memcpy(xbuf, data, 64);
X = xbuf;
}
-#endif
+# endif
-#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
+# define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
/* Round 1. */
/* Let [abcd k s i] denote the operation
a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */
-#define F(x, y, z) (((x) & (y)) | (~(x) & (z)))
-#define SET(a, b, c, d, k, s, Ti)\
+# define F(x, y, z) (((x) & (y)) | (~(x) & (z)))
+# define SET(a, b, c, d, k, s, Ti)\
t = a + F(b,c,d) + X[k] + Ti;\
a = ROTATE_LEFT(t, s) + b
/* Do the following 16 operations. */
SET(d, a, b, c, 13, 12, T14);
SET(c, d, a, b, 14, 17, T15);
SET(b, c, d, a, 15, 22, T16);
-#undef SET
+# undef SET
/* Round 2. */
/* Let [abcd k s i] denote the operation
a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */
-#define G(x, y, z) (((x) & (z)) | ((y) & ~(z)))
-#define SET(a, b, c, d, k, s, Ti)\
+# define G(x, y, z) (((x) & (z)) | ((y) & ~(z)))
+# define SET(a, b, c, d, k, s, Ti)\
t = a + G(b,c,d) + X[k] + Ti;\
a = ROTATE_LEFT(t, s) + b
/* Do the following 16 operations. */
SET(d, a, b, c, 2, 9, T30);
SET(c, d, a, b, 7, 14, T31);
SET(b, c, d, a, 12, 20, T32);
-#undef SET
+# undef SET
/* Round 3. */
/* Let [abcd k s t] denote the operation
a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */
-#define H(x, y, z) ((x) ^ (y) ^ (z))
-#define SET(a, b, c, d, k, s, Ti)\
+# define H(x, y, z) ((x) ^ (y) ^ (z))
+# define SET(a, b, c, d, k, s, Ti)\
t = a + H(b,c,d) + X[k] + Ti;\
a = ROTATE_LEFT(t, s) + b
/* Do the following 16 operations. */
SET(d, a, b, c, 12, 11, T46);
SET(c, d, a, b, 15, 16, T47);
SET(b, c, d, a, 2, 23, T48);
-#undef SET
+# undef SET
/* Round 4. */
/* Let [abcd k s t] denote the operation
a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */
-#define I(x, y, z) ((y) ^ ((x) | ~(z)))
-#define SET(a, b, c, d, k, s, Ti)\
+# define I(x, y, z) ((y) ^ ((x) | ~(z)))
+# define SET(a, b, c, d, k, s, Ti)\
t = a + I(b,c,d) + X[k] + Ti;\
a = ROTATE_LEFT(t, s) + b
/* Do the following 16 operations. */
SET(d, a, b, c, 11, 10, T62);
SET(c, d, a, b, 2, 15, T63);
SET(b, c, d, a, 9, 21, T64);
-#undef SET
+# undef SET
/* Then perform the following additions. (That is increment each
of the four registers by the value it had before this block
for (i = 0; i < 16; ++i)
digest[i] = (unsigned char)(pms->abcd[i >> 2] >> ((i & 3) << 3));
}
+#endif /* !__APPLE__ && !HAVE_GNUTLS */
/*
- * MD5 password support for CUPS.
+ * MD5 password support for CUPS (deprecated).
*
- * Copyright 2007-2010 by Apple Inc.
+ * Copyright 2007-2017 by Apple Inc.
* Copyright 1997-2005 by Easy Software Products.
*
* These coded instructions, statements, and computer programs are the
* Include necessary headers...
*/
+#include <cups/cups.h>
#include "http-private.h"
#include "string-private.h"
/*
* 'httpMD5()' - Compute the MD5 sum of the username:group:password.
+ *
+ * @deprecated@
*/
char * /* O - MD5 sum */
const char *passwd, /* I - Password string */
char md5[33]) /* O - MD5 string */
{
- _cups_md5_state_t state; /* MD5 state info */
unsigned char sum[16]; /* Sum data */
char line[256]; /* Line to sum */
*/
snprintf(line, sizeof(line), "%s:%s:%s", username, realm, passwd);
- _cupsMD5Init(&state);
- _cupsMD5Append(&state, (unsigned char *)line, (int)strlen(line));
- _cupsMD5Finish(&state, sum);
+ cupsHashData("md5", (unsigned char *)line, strlen(line), sum, sizeof(sum));
/*
* Return the sum...
*/
- return (httpMD5String(sum, md5));
+ return ((char *)cupsHashString(sum, sizeof(sum), md5, 33));
}
* 'httpMD5Final()' - Combine the MD5 sum of the username, group, and password
* with the server-supplied nonce value, method, and
* request-uri.
+ *
+ * @deprecated@
*/
char * /* O - New sum */
const char *resource, /* I - Resource path */
char md5[33]) /* IO - MD5 sum */
{
- _cups_md5_state_t state; /* MD5 state info */
unsigned char sum[16]; /* Sum data */
char line[1024]; /* Line of data */
char a2[33]; /* Hash of method and resource */
*/
snprintf(line, sizeof(line), "%s:%s", method, resource);
- _cupsMD5Init(&state);
- _cupsMD5Append(&state, (unsigned char *)line, (int)strlen(line));
- _cupsMD5Finish(&state, sum);
- httpMD5String(sum, a2);
+ cupsHashData("md5", (unsigned char *)line, strlen(line), sum, sizeof(sum));
+ cupsHashString(sum, sizeof(sum), a2, sizeof(a2));
/*
* Then combine A1 (MD5 of username, realm, and password) with the nonce
*/
snprintf(line, sizeof(line), "%s:%s:%s", md5, nonce, a2);
+ cupsHashData("md5", (unsigned char *)line, strlen(line), sum, sizeof(sum));
- _cupsMD5Init(&state);
- _cupsMD5Append(&state, (unsigned char *)line, (int)strlen(line));
- _cupsMD5Finish(&state, sum);
-
- return (httpMD5String(sum, md5));
+ return ((char *)cupsHashString(sum, sizeof(sum), md5, 33));
}
/*
* 'httpMD5String()' - Convert an MD5 sum to a character string.
+ *
+ * @deprecated@
*/
char * /* O - MD5 sum in hex */
char md5[33])
/* O - MD5 sum in hex */
{
- int i; /* Looping var */
- char *md5ptr; /* Pointer into MD5 string */
- static const char hex[] = "0123456789abcdef";
- /* Hex digits */
-
-
- /*
- * Convert the MD5 sum to hexadecimal...
- */
-
- for (i = 16, md5ptr = md5; i > 0; i --, sum ++)
- {
- *md5ptr++ = hex[*sum >> 4];
- *md5ptr++ = hex[*sum & 15];
- }
-
- *md5ptr = '\0';
-
- return (md5);
+ return ((char *)cupsHashString(sum, 16, md5, 33));
}
/*
* Option conflict management routines for CUPS.
*
- * Copyright 2007-2015 by Apple Inc.
+ * Copyright 2007-2018 by Apple Inc.
* Copyright 1997-2007 by Easy Software Products, all rights reserved.
*
* These coded instructions, statements, and computer programs are the
enum
{
- _PPD_NORMAL_CONSTRAINTS,
_PPD_OPTION_CONSTRAINTS,
_PPD_INSTALLABLE_CONSTRAINTS,
_PPD_ALL_CONSTRAINTS
if (!consts->installable && which == _PPD_INSTALLABLE_CONSTRAINTS)
continue; /* Skip non-installable option constraint */
- if (which == _PPD_OPTION_CONSTRAINTS && option)
+ if ((which == _PPD_OPTION_CONSTRAINTS || which == _PPD_INSTALLABLE_CONSTRAINTS) && option)
{
/*
* Skip constraints that do not involve the current option...
/*
* PPD localization routines for CUPS.
*
- * Copyright 2007-2017 by Apple Inc.
+ * Copyright 2007-2018 by Apple Inc.
* Copyright 1997-2007 by Easy Software Products, all rights reserved.
*
* These coded instructions, statements, and computer programs are the
if (!locattr)
{
- if (lang && (!scheme || !strcmp(scheme, "text")))
+ if (lang && (!scheme || !strcmp(scheme, "text")) && strcmp(reason, "none"))
{
/*
* Try to localize a standard printer-state-reason keyword...
/*
* TLS support code for CUPS on macOS.
*
- * Copyright 2007-2017 by Apple Inc.
- * Copyright 1997-2007 by Easy Software Products, all rights reserved.
+ * Copyright © 2007-2018 by Apple Inc.
+ * Copyright © 1997-2007 by Easy Software Products, all rights reserved.
*
* These coded instructions, statements, and computer programs are the
* property of Apple Inc. and are protected by Federal copyright
/* Server cert keychain path */
static _cups_mutex_t tls_mutex = _CUPS_MUTEX_INITIALIZER;
/* Mutex for keychain/certs */
-static int tls_options = -1;/* Options for TLS connections */
+static int tls_options = -1,/* Options for TLS connections */
+ tls_min_version = _HTTP_TLS_1_0,
+ tls_max_version = _HTTP_TLS_MAX;
/*
CFStringRef cf_name; /* CF common name string */
char name[256]; /* Common name associated with cert */
time_t expiration; /* Expiration date of cert */
- _cups_md5_state_t md5_state; /* MD5 state */
unsigned char md5_digest[16]; /* MD5 result */
if ((cf_name = SecCertificateCopySubjectSummary(secCert)) != NULL)
expiration = (time_t)(SecCertificateNotValidAfter(secCert) + kCFAbsoluteTimeIntervalSince1970);
- _cupsMD5Init(&md5_state);
- _cupsMD5Append(&md5_state, first->data, (int)first->datalen);
- _cupsMD5Finish(&md5_state, md5_digest);
+ cupsHashData("md5", first->data, first->datalen, md5_digest, sizeof(md5_digest));
snprintf(buffer, bufsize, "%s / %s / %02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X", name, httpGetDateString(expiration), md5_digest[0], md5_digest[1], md5_digest[2], md5_digest[3], md5_digest[4], md5_digest[5], md5_digest[6], md5_digest[7], md5_digest[8], md5_digest[9], md5_digest[10], md5_digest[11], md5_digest[12], md5_digest[13], md5_digest[14], md5_digest[15]);
*/
void
-_httpTLSSetOptions(int options) /* I - Options */
+_httpTLSSetOptions(int options, /* I - Options */
+ int min_version, /* I - Minimum TLS version */
+ int max_version) /* I - Maximum TLS version */
{
if (!(options & _HTTP_TLS_SET_DEFAULT) || tls_options < 0)
- tls_options = options;
+ {
+ tls_options = options;
+ tls_min_version = min_version;
+ tls_max_version = max_version;
+ }
}
{
DEBUG_puts("4_httpTLSStart: Setting defaults.");
_cupsSetDefaults();
- DEBUG_printf(("4_httpTLSStart: tls_options=%x", tls_options));
+ DEBUG_printf(("4_httpTLSStart: tls_options=%x, tls_min_version=%d, tls_max_version=%d", tls_options, tls_min_version, tls_max_version));
}
#ifdef HAVE_SECKEYCHAINOPEN
if (!error)
{
- SSLProtocol minProtocol;
-
- if (tls_options & _HTTP_TLS_DENY_TLS10)
- minProtocol = kTLSProtocol11;
- else if (tls_options & _HTTP_TLS_ALLOW_SSL3)
- minProtocol = kSSLProtocol3;
- else
- minProtocol = kTLSProtocol1;
+ static const SSLProtocol protocols[] = /* Min/max protocol versions */
+ {
+ kSSLProtocol3,
+ kTLSProtocol1,
+ kTLSProtocol11,
+ kTLSProtocol12,
+ kTLSProtocol12, /* TODO: update to 1.3 when 1.3 is supported */
+ kTLSProtocol12 /* TODO: update to 1.3 when 1.3 is supported */
+ };
- error = SSLSetProtocolVersionMin(http->tls, minProtocol);
- DEBUG_printf(("4_httpTLSStart: SSLSetProtocolVersionMin(%d), error=%d", minProtocol, (int)error));
+ error = SSLSetProtocolVersionMin(http->tls, protocols[tls_min_version]);
+ DEBUG_printf(("4_httpTLSStart: SSLSetProtocolVersionMin(%d), error=%d", protocols[tls_min_version], (int)error));
- if (!error && (tls_options & _HTTP_TLS_ONLY_TLS10))
+ if (!error)
{
- error = SSLSetProtocolVersionMax(http->tls, kTLSProtocol1);
- DEBUG_printf(("4_httpTLSStart: SSLSetProtocolVersionMax(kTLSProtocol1), error=%d", (int)error));
+ error = SSLSetProtocolVersionMax(http->tls, protocols[tls_max_version]);
+ DEBUG_printf(("4_httpTLSStart: SSLSetProtocolVersionMax(%d), error=%d", protocols[tls_max_version], (int)error));
}
}
if (!error)
{
- int done = 0; /* Are we done yet? */
+ int done = 0; /* Are we done yet? */
+ double old_timeout; /* Old timeout value */
+ http_timeout_cb_t old_cb; /* Old timeout callback */
+ void *old_data; /* Old timeout data */
+
+ /*
+ * Enforce a minimum timeout of 10 seconds for the TLS handshake...
+ */
+
+ old_timeout = http->timeout_value;
+ old_cb = http->timeout_cb;
+ old_data = http->timeout_data;
+
+ if (!old_cb || old_timeout < 10.0)
+ {
+ DEBUG_puts("4_httpTLSStart: Setting timeout to 10 seconds.");
+ httpSetTimeout(http, 10.0, NULL, NULL);
+ }
+
+ /*
+ * Do the TLS handshake...
+ */
while (!error && !done)
{
break;
}
}
+
+ /*
+ * Restore the previous timeout settings...
+ */
+
+ httpSetTimeout(http, old_timeout, old_cb, old_data);
}
if (error)
http = (http_t *)connection;
- if (!http->blocking)
+ if (!http->blocking || http->timeout_value > 0.0)
{
/*
* Make sure we have data before we read...
typedef struct _cups_client_conf_s /**** client.conf config data ****/
{
#ifdef HAVE_SSL
- int ssl_options; /* SSLOptions values */
+ int ssl_options, /* SSLOptions values */
+ ssl_min_version,/* Minimum SSL/TLS version */
+ ssl_max_version;/* Maximum SSL/TLS version */
#endif /* HAVE_SSL */
int trust_first, /* Trust on first use? */
any_root, /* Allow any (e.g., self-signed) root */
cg->validate_certs = cc.validate_certs;
#ifdef HAVE_SSL
- _httpTLSSetOptions(cc.ssl_options | _HTTP_TLS_SET_DEFAULT);
+ _httpTLSSetOptions(cc.ssl_options | _HTTP_TLS_SET_DEFAULT, cc.ssl_min_version, cc.ssl_max_version);
#endif /* HAVE_SSL */
}
memset(cc, 0, sizeof(_cups_client_conf_t));
- cc->encryption = (http_encryption_t)-1;
- cc->trust_first = -1;
- cc->any_root = -1;
- cc->expired_certs = -1;
- cc->validate_certs = -1;
+#ifdef HAVE_SSL
+ cc->ssl_min_version = _HTTP_TLS_1_0;
+ cc->ssl_max_version = _HTTP_TLS_MAX;
+#endif /* HAVE_SSL */
+ cc->encryption = (http_encryption_t)-1;
+ cc->trust_first = -1;
+ cc->any_root = -1;
+ cc->expired_certs = -1;
+ cc->validate_certs = -1;
/*
* Load settings from the org.cups.PrintingPrefs plist (which trump
* SSLOptions [AllowRC4] [AllowSSL3] [AllowDH] [DenyTLS1.0] [None]
*/
- int options = _HTTP_TLS_NONE; /* SSL/TLS options */
+ int options = _HTTP_TLS_NONE, /* SSL/TLS options */
+ min_version = _HTTP_TLS_1_0, /* Minimum SSL/TLS version */
+ max_version = _HTTP_TLS_MAX; /* Maximum SSL/TLS version */
char temp[256], /* Copy of value */
*start, /* Start of option */
*end; /* End of option */
if (!_cups_strcasecmp(start, "AllowRC4"))
options |= _HTTP_TLS_ALLOW_RC4;
else if (!_cups_strcasecmp(start, "AllowSSL3"))
- options |= _HTTP_TLS_ALLOW_SSL3;
+ min_version = _HTTP_TLS_SSL3;
else if (!_cups_strcasecmp(start, "AllowDH"))
options |= _HTTP_TLS_ALLOW_DH;
else if (!_cups_strcasecmp(start, "DenyCBC"))
options |= _HTTP_TLS_DENY_CBC;
else if (!_cups_strcasecmp(start, "DenyTLS1.0"))
- options |= _HTTP_TLS_DENY_TLS10;
+ min_version = _HTTP_TLS_1_1;
+ else if (!_cups_strcasecmp(start, "MaxTLS1.0"))
+ max_version = _HTTP_TLS_1_0;
+ else if (!_cups_strcasecmp(start, "MaxTLS1.1"))
+ max_version = _HTTP_TLS_1_1;
+ else if (!_cups_strcasecmp(start, "MaxTLS1.2"))
+ max_version = _HTTP_TLS_1_2;
+ else if (!_cups_strcasecmp(start, "MaxTLS1.3"))
+ max_version = _HTTP_TLS_1_3;
+ else if (!_cups_strcasecmp(start, "MinTLS1.0"))
+ min_version = _HTTP_TLS_1_0;
+ else if (!_cups_strcasecmp(start, "MinTLS1.1"))
+ min_version = _HTTP_TLS_1_1;
+ else if (!_cups_strcasecmp(start, "MinTLS1.2"))
+ min_version = _HTTP_TLS_1_2;
+ else if (!_cups_strcasecmp(start, "MinTLS1.3"))
+ min_version = _HTTP_TLS_1_3;
else if (!_cups_strcasecmp(start, "None"))
options = _HTTP_TLS_NONE;
}
- cc->ssl_options = options;
+ cc->ssl_options = options;
+ cc->ssl_max_version = max_version;
+ cc->ssl_min_version = min_version;
- DEBUG_printf(("4cups_set_ssl_options(cc=%p, value=\"%s\") options=%x", (void *)cc, value, options));
+ DEBUG_printf(("4cups_set_ssl_options(cc=%p, value=\"%s\") options=%x, min_version=%d, max_version=%d", (void *)cc, value, options, min_version, max_version));
}
#endif /* HAVE_SSL */
/*
* Raster file routines for CUPS.
*
- * Copyright 2007-2016 by Apple Inc.
+ * Copyright 2007-2018 by Apple Inc.
* Copyright 1997-2006 by Easy Software Products.
*
* This file is part of the CUPS Imaging library.
*bufend; /* End of current (read) buffer */
size_t bufsize; /* Buffer size */
#ifdef DEBUG
- size_t iocount; /* Number of bytes read/written */
+ size_t iostart, /* Start of read/write buffer */
+ iocount; /* Number of bytes read/written */
#endif /* DEBUG */
unsigned apple_page_count;/* Apple raster page count */
};
+typedef void (*_cups_copyfunc_t)(void *dst, const void *src, size_t bytes);
+
+
+/*
+ * Local globals...
+ */
+
+#ifdef DEBUG
+ static const char * const cups_color_spaces[] =
+ { /* Color spaces */
+ "CUPS_CSPACE_W",
+ "CUPS_CSPACE_RGB",
+ "CUPS_CSPACE_RGBA",
+ "CUPS_CSPACE_K",
+ "CUPS_CSPACE_CMY",
+ "CUPS_CSPACE_YMC",
+ "CUPS_CSPACE_CMYK",
+ "CUPS_CSPACE_YMCK",
+ "CUPS_CSPACE_KCMY",
+ "CUPS_CSPACE_KCMYcm",
+ "CUPS_CSPACE_GMCK",
+ "CUPS_CSPACE_GMCS",
+ "CUPS_CSPACE_WHITE",
+ "CUPS_CSPACE_GOLD",
+ "CUPS_CSPACE_SILVER",
+ "CUPS_CSPACE_CIEXYZ",
+ "CUPS_CSPACE_CIELab",
+ "CUPS_CSPACE_RGBW",
+ "CUPS_CSPACE_SW",
+ "CUPS_CSPACE_SRGB",
+ "CUPS_CSPACE_ADOBERGB",
+ "21",
+ "22",
+ "23",
+ "24",
+ "25",
+ "26",
+ "27",
+ "28",
+ "29",
+ "30",
+ "31",
+ "CUPS_CSPACE_ICC1",
+ "CUPS_CSPACE_ICC2",
+ "CUPS_CSPACE_ICC3",
+ "CUPS_CSPACE_ICC4",
+ "CUPS_CSPACE_ICC5",
+ "CUPS_CSPACE_ICC6",
+ "CUPS_CSPACE_ICC7",
+ "CUPS_CSPACE_ICC8",
+ "CUPS_CSPACE_ICC9",
+ "CUPS_CSPACE_ICCA",
+ "CUPS_CSPACE_ICCB",
+ "CUPS_CSPACE_ICCC",
+ "CUPS_CSPACE_ICCD",
+ "CUPS_CSPACE_ICCE",
+ "CUPS_CSPACE_ICCF",
+ "47",
+ "CUPS_CSPACE_DEVICE1",
+ "CUPS_CSPACE_DEVICE2",
+ "CUPS_CSPACE_DEVICE3",
+ "CUPS_CSPACE_DEVICE4",
+ "CUPS_CSPACE_DEVICE5",
+ "CUPS_CSPACE_DEVICE6",
+ "CUPS_CSPACE_DEVICE7",
+ "CUPS_CSPACE_DEVICE8",
+ "CUPS_CSPACE_DEVICE9",
+ "CUPS_CSPACE_DEVICEA",
+ "CUPS_CSPACE_DEVICEB",
+ "CUPS_CSPACE_DEVICEC",
+ "CUPS_CSPACE_DEVICED",
+ "CUPS_CSPACE_DEVICEE",
+ "CUPS_CSPACE_DEVICEF"
+ };
+ static const char * const cups_modes[] =
+ { /* Open modes */
+ "CUPS_RASTER_READ",
+ "CUPS_RASTER_WRITE",
+ "CUPS_RASTER_WRITE_COMPRESSED",
+ "CUPS_RASTER_WRITE_PWG",
+ "CUPS_RASTER_WRITE_APPLE"
+ };
+#endif /* DEBUG */
+
/*
* Local functions...
static ssize_t cups_raster_io(cups_raster_t *r, unsigned char *buf, size_t bytes);
static unsigned cups_raster_read_header(cups_raster_t *r);
-static ssize_t cups_raster_read(cups_raster_t *r, unsigned char *buf,
- size_t bytes);
+static ssize_t cups_raster_read(cups_raster_t *r, unsigned char *buf, size_t bytes);
static int cups_raster_update(cups_raster_t *r);
-static ssize_t cups_raster_write(cups_raster_t *r,
- const unsigned char *pixels);
+static ssize_t cups_raster_write(cups_raster_t *r, const unsigned char *pixels);
static ssize_t cups_read_fd(void *ctx, unsigned char *buf, size_t bytes);
static void cups_swap(unsigned char *buf, size_t bytes);
+static void cups_swap_copy(unsigned char *dst, const unsigned char *src, size_t bytes);
static ssize_t cups_write_fd(void *ctx, unsigned char *buf, size_t bytes);
@code CUPS_RASTER_WRITE_COMPRESSED@,
or @code CUPS_RASTER_WRITE_PWG@ */
{
+ DEBUG_printf(("cupsRasterOpen(fd=%d, mode=%s)", fd, cups_modes[mode]));
+
if (mode == CUPS_RASTER_READ)
return (cupsRasterOpenIO(cups_read_fd, (void *)((intptr_t)fd), mode));
else
cups_raster_t *r; /* New stream */
+ DEBUG_printf(("cupsRasterOpenIO(iocb=%p, ctx=%p, mode=%s)", (void *)iocb, ctx, cups_modes[mode]));
+
_cupsRasterClearError();
if ((r = calloc(sizeof(cups_raster_t), 1)) == NULL)
{
_cupsRasterAddError("Unable to allocate memory for raster stream: %s\n",
strerror(errno));
+ DEBUG_puts("1cupsRasterOpenIO: Returning NULL.");
return (NULL);
}
_cupsRasterAddError("Unable to read header from raster stream: %s\n",
strerror(errno));
free(r);
+ DEBUG_puts("1cupsRasterOpenIO: Unable to read header, returning NULL.");
return (NULL);
}
{
_cupsRasterAddError("Unknown raster format %08x!\n", r->sync);
free(r);
+ DEBUG_puts("1cupsRasterOpenIO: Unknown format, returning NULL.");
return (NULL);
}
r->sync == CUPS_RASTER_REVSYNCapple)
r->compressed = 1;
+ DEBUG_printf(("1cupsRasterOpenIO: sync=%08x", r->sync));
+
if (r->sync == CUPS_RASTER_REVSYNC ||
r->sync == CUPS_RASTER_REVSYNCv1 ||
r->sync == CUPS_RASTER_REVSYNCv2 ||
_cupsRasterAddError("Unable to read header from raster stream: %s\n",
strerror(errno));
free(r);
+ DEBUG_puts("1cupsRasterOpenIO: Unable to read header, returning NULL.");
return (NULL);
}
-
}
- DEBUG_printf(("1cupsRasterOpenIO: r->swapped=%d, r->sync=%08x\n", r->swapped, r->sync));
+#ifdef DEBUG
+ r->iostart = r->iocount;
+#endif /* DEBUG */
}
else
{
_cupsRasterAddError("Unable to write raster stream header: %s\n",
strerror(errno));
free(r);
+ DEBUG_puts("1cupsRasterOpenIO: Unable to write header, returning NULL.");
return (NULL);
}
}
+ DEBUG_printf(("1cupsRasterOpenIO: compressed=%d, swapped=%d, returning %p", r->compressed, r->swapped, (void *)r));
+
return (r);
}
cups_raster_t *r, /* I - Raster stream */
cups_page_header_t *h) /* I - Pointer to header data */
{
+ DEBUG_printf(("cupsRasterReadHeader(r=%p, h=%p)", (void *)r, (void *)h));
+
/*
* Get the raster header...
*/
if (!cups_raster_read_header(r))
{
memset(h, 0, sizeof(cups_page_header_t));
+ DEBUG_puts("1cupsRasterReadHeader: Unable to read page header, returning 0.");
return (0);
}
memcpy(h, &(r->header), sizeof(cups_page_header_t));
+ DEBUG_printf(("1cupsRasterReadHeader: cupsColorSpace=%s", cups_color_spaces[h->cupsColorSpace]));
+ DEBUG_printf(("1cupsRasterReadHeader: cupsBitsPerColor=%u", h->cupsBitsPerColor));
+ DEBUG_printf(("1cupsRasterReadHeader: cupsBitsPerPixel=%u", h->cupsBitsPerPixel));
+ DEBUG_printf(("1cupsRasterReadHeader: cupsBytesPerLine=%u", h->cupsBytesPerLine));
+ DEBUG_printf(("1cupsRasterReadHeader: cupsWidth=%u", h->cupsWidth));
+ DEBUG_printf(("1cupsRasterReadHeader: cupsHeight=%u", h->cupsHeight));
+
+ DEBUG_puts("1cupsRasterReadHeader: Returning 1.");
return (1);
}
if (!cups_raster_read_header(r))
{
memset(h, 0, sizeof(cups_page_header2_t));
+ DEBUG_puts("1cupsRasterReadHeader2: Unable to read header, returning 0.");
return (0);
}
memcpy(h, &(r->header), sizeof(cups_page_header2_t));
+ DEBUG_printf(("1cupsRasterReadHeader2: cupsColorSpace=%s", cups_color_spaces[h->cupsColorSpace]));
+ DEBUG_printf(("1cupsRasterReadHeader2: cupsBitsPerColor=%u", h->cupsBitsPerColor));
+ DEBUG_printf(("1cupsRasterReadHeader2: cupsBitsPerPixel=%u", h->cupsBitsPerPixel));
+ DEBUG_printf(("1cupsRasterReadHeader2: cupsBytesPerLine=%u", h->cupsBytesPerLine));
+ DEBUG_printf(("1cupsRasterReadHeader2: cupsWidth=%u", h->cupsWidth));
+ DEBUG_printf(("1cupsRasterReadHeader2: cupsHeight=%u", h->cupsHeight));
+
+ DEBUG_puts("1cupsRasterReadHeader2: Returning 1.");
return (1);
}
r->header.cupsBitsPerPixel == 12 ||
r->header.cupsBitsPerPixel == 16) &&
r->swapped)
- cups_swap(ptr, (size_t)bytes);
+ {
+ DEBUG_puts("1cupsRasterReadPixels: Swapping bytes.");
+ cups_swap(ptr, (size_t)cupsBytesPerLine);
+ }
/*
* Update pointers...
cups_raster_t *r, /* I - Raster stream */
cups_page_header_t *h) /* I - Raster page header */
{
+ DEBUG_printf(("cupsRasterWriteHeader(r=%p, h=%p)", (void *)r, (void *)h));
+
if (r == NULL || r->mode == CUPS_RASTER_READ)
+ {
+ DEBUG_puts("1cupsRasterWriteHeader: Returning 0.");
return (0);
+ }
+
+ DEBUG_printf(("1cupsRasterWriteHeader: cupsColorSpace=%s", cups_color_spaces[h->cupsColorSpace]));
+ DEBUG_printf(("1cupsRasterWriteHeader: cupsBitsPerColor=%u", h->cupsBitsPerColor));
+ DEBUG_printf(("1cupsRasterWriteHeader: cupsBitsPerPixel=%u", h->cupsBitsPerPixel));
+ DEBUG_printf(("1cupsRasterWriteHeader: cupsBytesPerLine=%u", h->cupsBytesPerLine));
+ DEBUG_printf(("1cupsRasterWriteHeader: cupsWidth=%u", h->cupsWidth));
+ DEBUG_printf(("1cupsRasterWriteHeader: cupsHeight=%u", h->cupsHeight));
/*
* Make a copy of the header, and compute the number of raster
memcpy(&(r->header), h, sizeof(cups_page_header_t));
if (!cups_raster_update(r))
+ {
+ DEBUG_puts("1cupsRasterWriteHeader: Unable to update parameters, returning 0.");
return (0);
+ }
+
+ if (r->mode == CUPS_RASTER_WRITE_APPLE)
+ {
+ r->rowheight = h->HWResolution[0] / h->HWResolution[1];
+
+ if (h->HWResolution[0] != (r->rowheight * h->HWResolution[1]))
+ return (0);
+ }
+ else
+ r->rowheight = 1;
/*
* Write the raster header...
cups_raster_t *r, /* I - Raster stream */
cups_page_header2_t *h) /* I - Raster page header */
{
+ DEBUG_printf(("cupsRasterWriteHeader(r=%p, h=%p)", (void *)r, (void *)h));
+
if (r == NULL || r->mode == CUPS_RASTER_READ)
+ {
+ DEBUG_puts("1cupsRasterWriteHeader2: Returning 0.");
return (0);
+ }
+
+ DEBUG_printf(("1cupsRasterWriteHeader2: cupsColorSpace=%s", cups_color_spaces[h->cupsColorSpace]));
+ DEBUG_printf(("1cupsRasterWriteHeader2: cupsBitsPerColor=%u", h->cupsBitsPerColor));
+ DEBUG_printf(("1cupsRasterWriteHeader2: cupsBitsPerPixel=%u", h->cupsBitsPerPixel));
+ DEBUG_printf(("1cupsRasterWriteHeader2: cupsBytesPerLine=%u", h->cupsBytesPerLine));
+ DEBUG_printf(("1cupsRasterWriteHeader2: cupsWidth=%u", h->cupsWidth));
+ DEBUG_printf(("1cupsRasterWriteHeader2: cupsHeight=%u", h->cupsHeight));
/*
* Make a copy of the header, and compute the number of raster
memcpy(&(r->header), h, sizeof(cups_page_header2_t));
if (!cups_raster_update(r))
+ {
+ DEBUG_puts("1cupsRasterWriteHeader: Unable to update parameters, returning 0.");
return (0);
+ }
if (r->mode == CUPS_RASTER_WRITE_APPLE)
{
r->header.cupsBitsPerPixel == 16))
{
unsigned char *bufptr; /* Pointer into write buffer */
- unsigned count; /* Remaining count */
/*
* Allocate a write buffer as needed...
}
/*
- * Byte swap the pixels...
+ * Byte swap the pixels and write them...
*/
- for (bufptr = r->buffer, count = len; count > 1; count -= 2, bufptr += 2)
- {
- bufptr[1] = *p++;
- bufptr[0] = *p++;
- }
-
- if (count) /* This should never happen... */
- *bufptr = *p;
-
- /*
- * Write the byte-swapped buffer...
- */
+ cups_swap_copy(r->buffer, p, len);
bytes = cups_raster_io(r, r->buffer, len);
}
size_t len; /* Length for read/swap */
- DEBUG_printf(("3cups_raster_read_header(r=%p), r->mode=%d", (void *)r, r ? r->mode : 0));
+ DEBUG_printf(("3cups_raster_read_header(r=%p), r->mode=%s", (void *)r, r ? cups_modes[r->mode] : ""));
if (r == NULL || r->mode != CUPS_RASTER_READ)
return (0);
DEBUG_printf(("6cups_raster_io: count=%d, total=%d", (int)count, (int)total));
if (count == 0)
- {
- DEBUG_puts("6cups_raster_io: Returning 0.");
- return (0);
- }
+ break;
else if (count < 0)
{
DEBUG_puts("6cups_raster_io: Returning -1 on error.");
#endif /* DEBUG */
}
+ DEBUG_printf(("6cups_raster_io: iocount=" CUPS_LLFMT, CUPS_LLCAST r->iocount));
DEBUG_printf(("6cups_raster_io: Returning " CUPS_LLFMT ".", CUPS_LLCAST total));
return (total);
total; /* Total bytes read */
- DEBUG_printf(("5cups_raster_read(r=%p, buf=%p, bytes=" CUPS_LLFMT ")", (void *)r, (void *)buf, CUPS_LLCAST bytes));
+ DEBUG_printf(("4cups_raster_read(r=%p, buf=%p, bytes=" CUPS_LLFMT "), offset=" CUPS_LLFMT, (void *)r, (void *)buf, CUPS_LLCAST bytes, CUPS_LLCAST (r->iostart + r->bufptr - r->buffer)));
if (!r->compressed)
return (cups_raster_io(r, buf, bytes));
{
count = (ssize_t)bytes - total;
- DEBUG_printf(("6cups_raster_read: count=" CUPS_LLFMT ", remaining=" CUPS_LLFMT ", buf=%p, bufptr=%p, bufend=%p", CUPS_LLCAST count, CUPS_LLCAST remaining, (void *)buf, (void *)r->bufptr, (void *)r->bufend));
+ DEBUG_printf(("5cups_raster_read: count=" CUPS_LLFMT ", remaining=" CUPS_LLFMT ", buf=%p, bufptr=%p, bufend=%p", CUPS_LLCAST count, CUPS_LLCAST remaining, (void *)buf, (void *)r->bufptr, (void *)r->bufend));
if (remaining == 0)
{
* Read into the raster buffer and then copy...
*/
+#ifdef DEBUG
+ r->iostart += (size_t)(r->bufend - r->buffer);
+#endif /* DEBUG */
+
remaining = (*r->iocb)(r->ctx, r->buffer, r->bufsize);
if (remaining <= 0)
return (0);
return (0);
#ifdef DEBUG
+ r->iostart += (size_t)count;
r->iocount += (size_t)count;
#endif /* DEBUG */
}
}
- DEBUG_printf(("6cups_raster_read: Returning %ld", (long)total));
+ DEBUG_printf(("5cups_raster_read: Returning %ld", (long)total));
return (total);
}
unsigned char *wptr; /* Pointer into write buffer */
unsigned bpp, /* Bytes per pixel */
count; /* Count */
+ _cups_copyfunc_t cf; /* Copy function */
DEBUG_printf(("3cups_raster_write(r=%p, pixels=%p)", (void *)r, (void *)pixels));
/*
+ * Determine whether we need to swap bytes...
+ */
+
+ if (r->swapped && (r->header.cupsBitsPerColor == 16 || r->header.cupsBitsPerPixel == 12 || r->header.cupsBitsPerPixel == 16))
+ {
+ DEBUG_puts("4cups_raster_write: Swapping bytes when writing.");
+ cf = (_cups_copyfunc_t)cups_swap_copy;
+ }
+ else
+ cf = (_cups_copyfunc_t)memcpy;
+
+ /*
* Allocate a write buffer as needed...
*/
*/
*wptr++ = 0;
- for (count = bpp; count > 0; count --)
- *wptr++ = *start++;
+ (*cf)(wptr, start, bpp);
+ wptr += bpp;
}
else if (!memcmp(start, ptr, bpp))
{
break;
*wptr++ = (unsigned char)(count - 1);
- for (count = bpp; count > 0; count --)
- *wptr++ = *ptr++;
+ (*cf)(wptr, ptr, bpp);
+ wptr += bpp;
+ ptr += bpp;
}
else
{
*wptr++ = (unsigned char)(257 - count);
count *= bpp;
- memcpy(wptr, start, count);
+ (*cf)(wptr, start, count);
wptr += count;
}
}
#endif /* WIN32 */
if (errno != EINTR && errno != EAGAIN)
{
- DEBUG_printf(("4cups_read_fd: %s", strerror(errno)));
+ DEBUG_printf(("8cups_read_fd: %s", strerror(errno)));
return (-1);
}
- DEBUG_printf(("4cups_read_fd: Returning %d bytes.", (int)count));
+ DEBUG_printf(("8cups_read_fd: Returning %d bytes.", (int)count));
return (count);
}
}
+/*
+ * 'cups_swap_copy()' - Copy and swap bytes in raster data...
+ */
+
+static void
+cups_swap_copy(
+ unsigned char *dst, /* I - Destination */
+ const unsigned char *src, /* I - Source */
+ size_t bytes) /* I - Number of bytes to swap */
+{
+ bytes /= 2;
+
+ while (bytes > 0)
+ {
+ dst[0] = src[1];
+ dst[1] = src[0];
+
+ dst += 2;
+ src += 2;
+ bytes --;
+ }
+}
+
+
/*
* 'cups_write_fd()' - Write bytes to a file.
*/
#endif /* WIN32 */
if (errno != EINTR && errno != EAGAIN)
{
- DEBUG_printf(("4cups_write_fd: %s", strerror(errno)));
+ DEBUG_printf(("8cups_write_fd: %s", strerror(errno)));
return (-1);
}
* requests when the request requires system group membership - then the
* client knows the root certificate can/should be used.
*
- * Also, for macOS we also look for @AUTHKEY and add an "authkey"
- * parameter as needed...
+ * Also, for macOS we also look for @AUTHKEY and add an "AuthRef key=foo"
+ * method as needed...
*/
char *name, /* Current user name */
*auth_key; /* Auth key buffer */
size_t auth_size; /* Size of remaining buffer */
+ int need_local = 1; /* Do we need to list "Local" method? */
auth_key = auth_str + strlen(auth_str);
auth_size = sizeof(auth_str) - (size_t)(auth_key - auth_str);
+#if defined(SO_PEERCRED) && defined(AF_LOCAL)
+ if (httpAddrFamily(httpGetAddress(con->http)) == AF_LOCAL)
+ {
+ strlcpy(auth_key, ", PeerCred", auth_size);
+ auth_key += 10;
+ auth_size -= 10;
+ }
+#endif /* SO_PEERCRED && AF_LOCAL */
+
for (name = (char *)cupsArrayFirst(con->best->names);
name;
name = (char *)cupsArrayNext(con->best->names))
{
+ cupsdLogClient(con, CUPSD_LOG_DEBUG2, "cupsdSendHeader: require \"%s\"", name);
+
#ifdef HAVE_AUTHORIZATION_H
if (!_cups_strncasecmp(name, "@AUTHKEY(", 9))
{
- snprintf(auth_key, auth_size, ", authkey=\"%s\"", name + 9);
+ snprintf(auth_key, auth_size, ", AuthRef key=\"%s\"", name + 9);
+ need_local = 0;
/* end parenthesis is stripped in conf.c */
break;
}
{
#ifdef HAVE_AUTHORIZATION_H
if (SystemGroupAuthKey)
- snprintf(auth_key, auth_size,
- ", authkey=\"%s\"",
- SystemGroupAuthKey);
+ snprintf(auth_key, auth_size, ", AuthRef key=\"%s\"", SystemGroupAuthKey);
else
#else
- strlcpy(auth_key, ", trc=\"y\"", auth_size);
+ strlcpy(auth_key, ", Local trc=\"y\"", auth_size);
#endif /* HAVE_AUTHORIZATION_H */
+ need_local = 0;
break;
}
}
+
+ if (need_local)
+ strlcat(auth_key, ", Local", auth_size);
}
if (auth_str[0])
cupsdSetString(&ServerKeychain, "/Library/Keychains/System.keychain");
# endif /* HAVE_GNUTLS */
- _httpTLSSetOptions(0);
+ _httpTLSSetOptions(_HTTP_TLS_NONE, _HTTP_TLS_1_0, _HTTP_TLS_MAX);
#endif /* HAVE_SSL */
language = cupsLangDefault();
* SSLOptions [AllowRC4] [AllowSSL3] [AllowDH] [DenyCBC] [DenyTLS1.0] [None]
*/
- int options = 0; /* SSL/TLS options */
+ int options = _HTTP_TLS_NONE,/* SSL/TLS options */
+ min_version = _HTTP_TLS_1_0,
+ max_version = _HTTP_TLS_MAX;
if (value)
{
* Compare...
*/
- if (!_cups_strcasecmp(start, "AllowRC4"))
+ if (!_cups_strcasecmp(start, "AllowRC4"))
options |= _HTTP_TLS_ALLOW_RC4;
- else if (!_cups_strcasecmp(start, "AllowSSL3"))
- options |= _HTTP_TLS_ALLOW_SSL3;
+ else if (!_cups_strcasecmp(start, "AllowSSL3"))
+ min_version = _HTTP_TLS_SSL3;
else if (!_cups_strcasecmp(start, "AllowDH"))
options |= _HTTP_TLS_ALLOW_DH;
else if (!_cups_strcasecmp(start, "DenyCBC"))
options |= _HTTP_TLS_DENY_CBC;
else if (!_cups_strcasecmp(start, "DenyTLS1.0"))
- options |= _HTTP_TLS_DENY_TLS10;
- else if (!_cups_strcasecmp(start, "None"))
- options = 0;
+ min_version = _HTTP_TLS_1_1;
+ else if (!_cups_strcasecmp(start, "MaxTLS1.0"))
+ max_version = _HTTP_TLS_1_0;
+ else if (!_cups_strcasecmp(start, "MaxTLS1.1"))
+ max_version = _HTTP_TLS_1_1;
+ else if (!_cups_strcasecmp(start, "MaxTLS1.2"))
+ max_version = _HTTP_TLS_1_2;
+ else if (!_cups_strcasecmp(start, "MaxTLS1.3"))
+ max_version = _HTTP_TLS_1_3;
+ else if (!_cups_strcasecmp(start, "MinTLS1.0"))
+ min_version = _HTTP_TLS_1_0;
+ else if (!_cups_strcasecmp(start, "MinTLS1.1"))
+ min_version = _HTTP_TLS_1_1;
+ else if (!_cups_strcasecmp(start, "MinTLS1.2"))
+ min_version = _HTTP_TLS_1_2;
+ else if (!_cups_strcasecmp(start, "MinTLS1.3"))
+ min_version = _HTTP_TLS_1_3;
+ else if (!_cups_strcasecmp(start, "None"))
+ options = _HTTP_TLS_NONE;
else if (_cups_strcasecmp(start, "NoEmptyFragments"))
cupsdLogMessage(CUPSD_LOG_WARN, "Unknown SSL option %s at line %d.", start, linenum);
}
}
- _httpTLSSetOptions(options);
+ _httpTLSSetOptions(options, min_version, max_version);
}
#endif /* HAVE_SSL */
else if ((!_cups_strcasecmp(line, "Port") || !_cups_strcasecmp(line, "Listen")
* Write dirty config/state files...
*/
- if (DirtyCleanTime && current_time >= DirtyCleanTime && cupsArrayCount(Clients) == 0)
+ if (DirtyCleanTime && current_time >= DirtyCleanTime)
cupsdCleanDirty();
#ifdef __APPLE__
/*
* "lp" command for CUPS.
*
- * Copyright 2007-2016 by Apple Inc.
+ * Copyright 2007-2017 by Apple Inc.
* Copyright 1997-2007 by Easy Software Products.
*
* These coded instructions, statements, and computer programs are the
if (printer == NULL)
{
- val = NULL;
-
- if ((printer = getenv("LPDEST")) == NULL)
- {
- if ((printer = getenv("PRINTER")) != NULL)
- {
- if (!strcmp(printer, "lp"))
- printer = NULL;
- else
- val = "PRINTER";
- }
- }
- else
- val = "LPDEST";
-
- if (printer && !cupsGetNamedDest(NULL, printer, NULL))
- _cupsLangPrintf(stderr,
- _("%s: Error - %s environment variable names "
- "non-existent destination \"%s\"."), argv[0], val,
- printer);
- else if (cupsLastError() == IPP_NOT_FOUND)
- _cupsLangPrintf(stderr,
- _("%s: Error - no default destination available."),
- argv[0]);
+ if (!cupsGetNamedDest(NULL, NULL, NULL) && cupsLastError() == IPP_STATUS_ERROR_NOT_FOUND)
+ _cupsLangPrintf(stderr, _("%s: Error - %s"), argv[0], cupsLastErrorString());
else
- _cupsLangPrintf(stderr, _("%s: Error - scheduler not responding."),
- argv[0]);
+ _cupsLangPrintf(stderr, _("%s: Error - scheduler not responding."), argv[0]);
return (1);
}
/*
* "lpadmin" command for CUPS.
*
- * Copyright 2007-2016 by Apple Inc.
+ * Copyright 2007-2017 by Apple Inc.
* Copyright 1997-2006 by Easy Software Products.
*
* These coded instructions, statements, and computer programs are the
static int delete_printer_option(http_t *http, char *printer,
char *option);
static int enable_printer(http_t *http, char *printer);
-static char *get_printer_ppd(const char *uri, char *buffer, size_t bufsize);
+static char *get_printer_ppd(const char *uri, char *buffer, size_t bufsize, int *num_options, cups_option_t **options);
static cups_ptype_t get_printer_type(http_t *http, char *printer, char *uri,
size_t urisize);
static int set_printer_options(http_t *http, char *printer,
file = argv[i];
}
+
+ if (*opt == 'i')
+ {
+ /*
+ * Check to see that the specified file is, in fact, a PPD...
+ */
+
+ cups_file_t *fp = cupsFileOpen(file, "r");
+ char line[256];
+
+ if (!cupsFileGets(fp, line, sizeof(line)) || strncmp(line, "*PPD-Adobe", 10))
+ {
+ _cupsLangPuts(stderr, _("lpadmin: System V interface scripts are no longer supported for security reasons."));
+ cupsFileClose(fp);
+ return (1);
+ }
+
+ cupsFileClose(fp);
+ }
break;
case 'E' : /* Enable the printer/enable encryption */
if ((ppd_name = cupsGetOption("ppd-name", num_options, options)) != NULL && !strcmp(ppd_name, "everywhere") && (device_uri = cupsGetOption("device-uri", num_options, options)) != NULL)
{
- if ((file = get_printer_ppd(device_uri, evefile, sizeof(evefile))) == NULL)
+ if ((file = get_printer_ppd(device_uri, evefile, sizeof(evefile), &num_options, &options)) == NULL)
return (1);
num_options = cupsRemoveOption("ppd-name", num_options, &options);
* 'get_printer_ppd()' - Get an IPP Everywhere PPD file for the given URI.
*/
-static char * /* O - Filename or NULL */
-get_printer_ppd(const char *uri, /* I - Printer URI */
- char *buffer, /* I - Filename buffer */
- size_t bufsize) /* I - Size of filename buffer */
+static char * /* O - Filename or NULL */
+get_printer_ppd(
+ const char *uri, /* I - Printer URI */
+ char *buffer, /* I - Filename buffer */
+ size_t bufsize, /* I - Size of filename buffer */
+ int *num_options, /* IO - Number of options */
+ cups_option_t **options) /* IO - Options */
{
http_t *http; /* Connection to printer */
ipp_t *request, /* Get-Printer-Attributes request */
*response; /* Get-Printer-Attributes response */
+ ipp_attribute_t *attr; /* Attribute from response */
char resolved[1024], /* Resolved URI */
scheme[32], /* URI scheme */
userpass[256], /* Username:password */
host[256], /* Hostname */
resource[256]; /* Resource path */
int port; /* Port number */
+ static const char * const pattrs[] = /* Attributes to use */
+ {
+ "job-template",
+ "printer-defaults",
+ "printer-description",
+ "media-col-database"
+ };
/*
request = ippNewRequest(IPP_OP_GET_PRINTER_ATTRIBUTES);
ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, uri);
+ ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD, "requested-attributes", sizeof(pattrs) / sizeof(pattrs[0]), NULL, pattrs);
response = cupsDoRequest(http, request, resource);
- if (!_ppdCreateFromIPP(buffer, bufsize, response))
+ if (_ppdCreateFromIPP(buffer, bufsize, response))
+ {
+ if (!cupsGetOption("printer-geo-location", *num_options, *options) && (attr = ippFindAttribute(response, "printer-geo-location", IPP_TAG_URI)) != NULL)
+ *num_options = cupsAddOption("printer-geo-location", ippGetString(attr, 0, NULL), *num_options, options);
+
+ if (!cupsGetOption("printer-info", *num_options, *options) && (attr = ippFindAttribute(response, "printer-info", IPP_TAG_TEXT)) != NULL)
+ *num_options = cupsAddOption("printer-info", ippGetString(attr, 0, NULL), *num_options, options);
+
+ if (!cupsGetOption("printer-location", *num_options, *options) && (attr = ippFindAttribute(response, "printer-location", IPP_TAG_TEXT)) != NULL)
+ *num_options = cupsAddOption("printer-location", ippGetString(attr, 0, NULL), *num_options, options);
+ }
+ else
_cupsLangPrintf(stderr, _("%s: Unable to create PPD file: %s"), "lpadmin", strerror(errno));
ippDelete(response);
for (ptr = name; *ptr; ptr ++)
if (*ptr == '@')
break;
- else if ((*ptr >= 0 && *ptr <= ' ') || *ptr == 127 || *ptr == '/' ||
- *ptr == '#')
+ else if ((*ptr >= 0 && *ptr <= ' ') || *ptr == 127 || *ptr == '/' || *ptr == '\\' || *ptr == '?' || *ptr == '\'' || *ptr == '\"' || *ptr == '#')
return (0);
/*