]> git.ipfire.org Git - thirdparty/cups.git/commitdiff
Backport CUPS 2.3.x changes to 2.2.x (Issue #5255)
authorMichael R Sweet <michael.r.sweet@gmail.com>
Wed, 7 Mar 2018 03:53:41 +0000 (22:53 -0500)
committerMichael R Sweet <michael.r.sweet@gmail.com>
Wed, 7 Mar 2018 03:53:41 +0000 (22:53 -0500)
- 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)

28 files changed:
CHANGES.md
INSTALL.md
README.md
backend/ipp.c
berkeley/lpr.c
configure
configure.ac
cups/auth.c
cups/cups.h
cups/hash.c
cups/http-private.h
cups/http-support.c
cups/http.c
cups/http.h
cups/ipp-support.c
cups/ipp.c
cups/md5.c
cups/md5passwd.c
cups/ppd-conflicts.c
cups/ppd-localize.c
cups/tls-darwin.c
cups/usersys.c
filter/raster.c
scheduler/client.c
scheduler/conf.c
scheduler/main.c
systemv/lp.c
systemv/lpadmin.c

index 9e83177d246f6499c894beaf87d0b48f47e772d0..7103a2363e0c654b0b56f320d84f4581af08177b 100644 (file)
@@ -1,7 +1,56 @@
-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
 ----------------------
 
index 2c1c64181a5b6b261a2a678e8d4c415593a9de3a..a56668775d3ae37a53d2f13cb5fb4ac1e3b639d7 100644 (file)
@@ -1,4 +1,4 @@
-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
index 17ac7e7db376b65aef3998e1adc2acbff9a66de8..7c6f484d04ec449977d8d03a5cd45a5c920785f0 100644 (file)
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-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...
@@ -148,7 +148,7 @@ This will prevent the filters from misinterpreting your print file.
 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.
index 588ad995ed572e7361dc62b31976a918f7076395..a2548c25d669ba5284cd9d58da9890e7e4e3c896 100644 (file)
@@ -47,6 +47,8 @@ extern void   xpc_connection_set_target_uid(xpc_connection_t connection,
 #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
 
 
 /*
@@ -69,6 +71,7 @@ typedef struct _cups_monitor_s                /**** Monitoring data ****/
   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;
 
 
@@ -1448,6 +1451,7 @@ main(int  argc,                           /* I - Number of command-line args */
   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)
   {
@@ -2568,22 +2572,24 @@ monitor_printer(
 
         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;
         }
 
@@ -2601,6 +2607,26 @@ monitor_printer(
            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);
 
index e83f52e0b6257348879655d99a95995dfe8f5708..09e0bf1e5ecbeb0b8d2e5cb33677f66ca0754828 100644 (file)
@@ -32,8 +32,7 @@ main(int  argc,                               /* I - Number of command-line arguments */
   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 */
@@ -345,33 +344,10 @@ main(int  argc,                           /* I - Number of command-line arguments */
 
   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);
   }
index c8b573f2eed5ab9f194608cc7eb2be72269e53e1..21eca2648db86c49bafca1b6ea2315d96de9c174 100755 (executable)
--- a/configure
+++ b/configure
@@ -1,6 +1,6 @@
 #! /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>.
 #
@@ -580,8 +580,8 @@ MAKEFLAGS=
 # 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/'
 
@@ -1482,7 +1482,7 @@ if test "$ac_init_help" = "long"; then
   # 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]...
 
@@ -1547,7 +1547,7 @@ fi
 
 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
 
@@ -1728,7 +1728,7 @@ fi
 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.
@@ -2192,7 +2192,7 @@ cat >config.log <<_ACEOF
 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 $@
@@ -2667,7 +2667,7 @@ fi
 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"
 
@@ -10901,7 +10901,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
 # 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
@@ -10964,7 +10964,7 @@ _ACEOF
 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\\"
 
index ac78c48ad6d1ecf8a83b4c5a65e9ded16119d31e..ed26daa88df154147841140b540be65ad9f3fc58 100644 (file)
@@ -1,7 +1,7 @@
 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
@@ -15,7 +15,7 @@ dnl We need at least autoconf 2.60...
 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)
index c051c86ba81e840e6f7a932dd7fe8ad9c6735ffc..fa37070d491c0296a1efacdc7d159f6d1e3c745e 100644 (file)
@@ -47,6 +47,10 @@ extern const char *cssmErrorString(int error);
  * 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
@@ -112,8 +116,10 @@ cupsDoAuthentication(
     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 */
@@ -163,122 +169,237 @@ cupsDoAuthentication(
   }
 
  /*
-  * 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);
 }
 
 
@@ -336,7 +457,7 @@ _cupsSetNegotiateAuthString(
                                      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)
   {
    /*
@@ -412,7 +533,7 @@ _cupsSetNegotiateAuthString(
       }
     }
   }
-#endif /* HAVE_GSS_ACQUIRED_CRED_EX_F */
+#  endif /* HAVE_GSS_ACQUIRED_CRED_EX_F */
 
   if (GSS_ERROR(major_status))
   {
@@ -422,11 +543,11 @@ _cupsSetNegotiateAuthString(
     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)
   {
@@ -464,8 +585,259 @@ _cupsSetNegotiateAuthString(
 
   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.
@@ -650,6 +1022,8 @@ cups_local_auth(http_t *http)              /* I - HTTP connection to server */
   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 */
@@ -668,13 +1042,14 @@ cups_local_auth(http_t *http)            /* I - HTTP connection to server */
   * 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...
@@ -686,12 +1061,9 @@ cups_local_auth(http_t *http)             /* I - HTTP connection to server */
     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)",
@@ -745,6 +1117,15 @@ cups_local_auth(http_t *http)             /* I - HTTP connection to server */
   }
 #  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
@@ -752,16 +1133,9 @@ cups_local_auth(http_t *http)             /* I - HTTP connection to server */
   * 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...
@@ -784,6 +1158,9 @@ cups_local_auth(http_t *http)              /* I - HTTP connection to server */
   }
 #  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...
@@ -797,33 +1174,9 @@ cups_local_auth(http_t *http)             /* I - HTTP connection to server */
     * 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...
index 8f5c818f563aa3a0f621db16b92c235b47ed839f..1c750b20614358daa81b8d5b78b3d71095f9ba77 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * 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
@@ -47,10 +47,10 @@ extern "C" {
  * 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
index ede546167b202bdde7f74ed56ccdf8b7db5ab7c0..aa6aca310fb0c913aa7ae360d5856d62d03333e5 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * 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
@@ -21,6 +21,8 @@
 #  include <CommonCrypto/CommonDigest.h>
 #elif defined(HAVE_GNUTLS)
 #  include <gnutls/crypto.h>
+#else
+#  include "md5-private.h"
 #endif /* __APPLE__ */
 
 
@@ -53,7 +55,24 @@ cupsHashData(const char    *algorithm,       /* I - Algorithm name */
   }
 
 #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...
@@ -171,7 +190,9 @@ cupsHashData(const char    *algorithm,      /* I - Algorithm name */
   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;
@@ -219,10 +240,20 @@ cupsHashData(const char    *algorithm,    /* I - Algorithm name */
 
 #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__ */
 
@@ -243,3 +274,51 @@ cupsHashData(const char    *algorithm,     /* I - Algorithm name */
   _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);
+}
index f71e564b259881cc4d6fcb0e182e584e32a5622b..4f118bae57a95f12341a7d6aab8b042dd07a838d 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * 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
@@ -68,7 +68,6 @@ typedef int socklen_t;
 #  endif /* __APPLE__ && !_SOCKLEN_T */
 
 #  include <cups/http.h>
-#  include "md5-private.h"
 #  include "ipp-private.h"
 
 #  ifdef HAVE_GNUTLS
@@ -180,13 +179,17 @@ extern "C" {
 
 #  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...
@@ -297,10 +300,10 @@ struct _http_s                            /**** HTTP connection structure ****/
   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 */
 
@@ -442,7 +445,7 @@ extern void         _httpTLSInitialize(void);
 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);
index 76dbb7dbf0926dca038b4ea4578ab7bfea096a50..cbee9ab9d28ed891850b78ab0a42ee8ed90aa317 100644 (file)
@@ -502,7 +502,6 @@ httpAssembleUUID(const char *server,        /* I - Server name */
                 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 */
 
 
@@ -517,9 +516,7 @@ httpAssembleUUID(const char *server,        /* I - Server name */
            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...
@@ -1360,6 +1357,9 @@ _httpStatus(cups_lang_t   *lang,  /* I - Language */
     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;
index 61b88c9db73a38d0bab9896fb996b7c092a0c973..6c0b7e3b9e4c28217c07523f3503d9e1f64724da 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * 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
@@ -39,6 +39,7 @@
  * 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,
@@ -2659,105 +2660,7 @@ httpSetField(http_t       *http,        /* I - HTTP connection */
       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);
 }
 
 
@@ -3035,7 +2938,7 @@ _httpUpdate(http_t        *http,  /* I - HTTP connection */
       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));
@@ -3689,6 +3592,118 @@ httpWriteResponse(http_t        *http,  /* I - HTTP connection */
 }
 
 
+/*
+ * '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.
@@ -4056,7 +4071,7 @@ http_read(http_t *http,                   /* I - HTTP connection */
 
   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))
     {
@@ -4651,7 +4666,7 @@ http_write(http_t     *http,              /* I - HTTP connection */
   {
     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 */
@@ -4695,7 +4710,7 @@ http_write(http_t     *http,              /* I - HTTP connection */
          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;
index c61a79ee3dfd1af99706c4ab50646afe3a7d66ed..156efeaa888a6aa4c358ea71086001c1d094ea32 100644 (file)
@@ -248,10 +248,11 @@ typedef enum http_status_e                /**** HTTP status codes ****/
 
   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 */
@@ -285,6 +286,8 @@ typedef enum http_status_e          /**** HTTP status codes ****/
   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
index 675e5f380c36eb95aef5bd5b48e41efdcde590c5..d1ad65c8b5608dde98526c7b9dd13a527255a00a 100644 (file)
@@ -1,8 +1,8 @@
 /*
  * 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
@@ -960,9 +960,12 @@ ippCreateRequestedArray(ipp_t *request)    /* I - IPP request */
     "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",
@@ -1001,6 +1004,7 @@ ippCreateRequestedArray(ipp_t *request)   /* I - IPP request */
     "media-bottom-margin-supported",
     "media-col",
     "media-col-default",
+    "media-col-ready",
     "media-col-supported",
     "media-color-supported",
     "media-default",
@@ -1015,6 +1019,7 @@ ippCreateRequestedArray(ipp_t *request)   /* I - IPP request */
     "media-left-margin-supported",
     "media-order-count-supported",
     "media-pre-printed-supported",
+    "media-ready",
     "media-recycled-supported",
     "media-right-margin-supported",
     "media-size-supported",
@@ -1277,9 +1282,12 @@ ippCreateRequestedArray(ipp_t *request)  /* I - IPP request */
     "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",
@@ -1383,6 +1391,7 @@ ippCreateRequestedArray(ipp_t *request)   /* I - IPP request */
     "media-bottom-margin-supported",
     "media-col",
     "media-col-default",
+    "media-col-ready",
     "media-col-supported",
     "media-color-supported",
     "media-default",
@@ -1397,6 +1406,7 @@ ippCreateRequestedArray(ipp_t *request)   /* I - IPP request */
     "media-left-margin-supported",
     "media-order-count-supported",
     "media-pre-printed-supported",
+    "media-ready",
     "media-recycled-supported",
     "media-right-margin-supported",
     "media-size-supported",
@@ -1582,10 +1592,12 @@ ippCreateRequestedArray(ipp_t *request) /* I - IPP request */
     "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 */
@@ -1599,8 +1611,6 @@ ippCreateRequestedArray(ipp_t *request)   /* I - IPP request */
     "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 */
@@ -1623,6 +1633,8 @@ ippCreateRequestedArray(ipp_t *request)   /* I - IPP request */
     "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",
index 772b2f0a538ef91e496340a2df72b9e31edd805f..0adc3efcf7dc54cbcf1b288ae8b7357c89baec38 100644 (file)
@@ -4306,18 +4306,22 @@ ippSetString(ipp_t           *ipp,      /* I  - IPP message */
 {
   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);
 
  /*
index c0f5dd73fcebf99d55f80f5bf6728c74e5fc6183..d5057bf191eea0e9872af77a24793578e3f77ebb 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * 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]*/)
@@ -116,10 +117,10 @@ _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
@@ -133,7 +134,7 @@ _cups_md5_process(_cups_md5_state_t *pms, const unsigned char *data /*[64]*/)
        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
@@ -150,15 +151,15 @@ _cups_md5_process(_cups_md5_state_t *pms, const unsigned char *data /*[64]*/)
        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. */
@@ -178,13 +179,13 @@ _cups_md5_process(_cups_md5_state_t *pms, const unsigned char *data /*[64]*/)
     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. */
@@ -204,13 +205,13 @@ _cups_md5_process(_cups_md5_state_t *pms, const unsigned char *data /*[64]*/)
     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. */
@@ -230,13 +231,13 @@ _cups_md5_process(_cups_md5_state_t *pms, const unsigned char *data /*[64]*/)
     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. */
@@ -256,7 +257,7 @@ _cups_md5_process(_cups_md5_state_t *pms, const unsigned char *data /*[64]*/)
     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
@@ -337,3 +338,4 @@ _cupsMD5Finish(_cups_md5_state_t *pms, unsigned char digest[16])
     for (i = 0; i < 16; ++i)
        digest[i] = (unsigned char)(pms->abcd[i >> 2] >> ((i & 3) << 3));
 }
+#endif /* !__APPLE__ && !HAVE_GNUTLS */
index a9817aaa22583afacf1074da6741baca7ab77a52..49add7d7e18ee94426b261ae106f3d9e6dabcc9a 100644 (file)
@@ -1,7 +1,7 @@
 /*
- * 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 */
@@ -31,7 +34,6 @@ httpMD5(const char *username,         /* I - User name */
         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 */
 
@@ -41,15 +43,13 @@ httpMD5(const char *username,               /* I - User name */
   */
 
   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));
 }
 
 
@@ -57,6 +57,8 @@ httpMD5(const char *username,         /* I - User name */
  * '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 */
@@ -65,7 +67,6 @@ httpMD5Final(const char *nonce,               /* I - Server nonce value */
             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 */
@@ -76,10 +77,8 @@ httpMD5Final(const char *nonce,              /* I - Server nonce value */
   */
 
   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
@@ -88,17 +87,16 @@ httpMD5Final(const char *nonce,             /* I - Server nonce value */
   */
 
   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 */
@@ -106,23 +104,5 @@ httpMD5String(const unsigned char *sum,    /* I - MD5 sum data */
               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));
 }
index 8f875a57e3a367ab12b1c71a41e214aefe19aac0..24330ecb03e07b01567a02760c7dc048a77463d7 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * 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
@@ -29,7 +29,6 @@
 
 enum
 {
-  _PPD_NORMAL_CONSTRAINTS,
   _PPD_OPTION_CONSTRAINTS,
   _PPD_INSTALLABLE_CONSTRAINTS,
   _PPD_ALL_CONSTRAINTS
@@ -998,7 +997,7 @@ ppd_test_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...
index ed75bf86b521a6756924adeae6b27658e95c15aa..9537ef5b9cc88efbd4f9d703c4e4ddcb2c192958 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * 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
@@ -277,7 +277,7 @@ ppdLocalizeIPPReason(
 
   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...
index 92430aca0f7f8cc5303260b1fb5a2af7bac00d83..80cd66025bd688ba71e668fe1d592b93076d6357 100644 (file)
@@ -1,8 +1,8 @@
 /*
  * 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
@@ -53,7 +53,9 @@ static char           *tls_keypath = NULL;
                                        /* 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;
 
 
 /*
@@ -807,7 +809,6 @@ httpCredentialsString(
     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)
@@ -820,9 +821,7 @@ httpCredentialsString(
 
     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]);
 
@@ -1139,10 +1138,16 @@ _httpTLSRead(http_t *http,              /* I - HTTP connection */
  */
 
 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;
+  }
 }
 
 
@@ -1174,7 +1179,7 @@ _httpTLSStart(http_t *http)               /* I - HTTP connection */
   {
     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
@@ -1217,22 +1222,23 @@ _httpTLSStart(http_t *http)             /* I - HTTP connection */
 
   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));
     }
   }
 
@@ -1532,7 +1538,28 @@ _httpTLSStart(http_t *http)              /* I - HTTP connection */
 
   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)
     {
@@ -1653,6 +1680,12 @@ _httpTLSStart(http_t *http)              /* I - HTTP connection */
            break;
       }
     }
+
+   /*
+    * Restore the previous timeout settings...
+    */
+
+    httpSetTimeout(http, old_timeout, old_cb, old_data);
   }
 
   if (error)
@@ -2085,7 +2118,7 @@ http_cdsa_read(
 
   http = (http_t *)connection;
 
-  if (!http->blocking)
+  if (!http->blocking || http->timeout_value > 0.0)
   {
    /*
     * Make sure we have data before we read...
index 2a004b540217ee1c6aa9a016c7a87854bb312784..99601e4c44fadae5159fa4119bbea81a836a025a 100644 (file)
@@ -54,7 +54,9 @@
 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 */
@@ -957,7 +959,7 @@ _cupsSetDefaults(void)
     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 */
 }
 
@@ -1164,11 +1166,15 @@ cups_init_client_conf(
 
   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
@@ -1336,7 +1342,9 @@ cups_set_ssl_options(
   * 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 */
@@ -1364,20 +1372,38 @@ cups_set_ssl_options(
     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 */
 
index bacf5ba78f44420f6ef897c534de648dab3e21ef..edb650dfccc6e56209d3733c2edb52d634424055 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * 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.
@@ -50,11 +50,96 @@ struct _cups_raster_s                       /**** Raster stream data ****/
                        *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...
@@ -62,13 +147,12 @@ struct _cups_raster_s                      /**** Raster stream data ****/
 
 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);
 
 
@@ -356,6 +440,8 @@ cupsRasterOpen(int         fd,              /* I - File descriptor */
                                               @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
@@ -387,12 +473,15 @@ cupsRasterOpenIO(
   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);
   }
 
@@ -412,6 +501,7 @@ cupsRasterOpenIO(
       _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);
     }
 
@@ -426,6 +516,7 @@ cupsRasterOpenIO(
     {
       _cupsRasterAddError("Unknown raster format %08x!\n", r->sync);
       free(r);
+      DEBUG_puts("1cupsRasterOpenIO: Unknown format, returning NULL.");
       return (NULL);
     }
 
@@ -435,6 +526,8 @@ cupsRasterOpenIO(
         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 ||
@@ -452,12 +545,14 @@ cupsRasterOpenIO(
        _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
   {
@@ -496,10 +591,13 @@ cupsRasterOpenIO(
       _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);
 }
 
@@ -522,6 +620,8 @@ cupsRasterReadHeader(
     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...
   */
@@ -529,6 +629,7 @@ cupsRasterReadHeader(
   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);
   }
 
@@ -538,6 +639,14 @@ cupsRasterReadHeader(
 
   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);
 }
 
@@ -563,6 +672,7 @@ cupsRasterReadHeader2(
   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);
   }
 
@@ -572,6 +682,14 @@ cupsRasterReadHeader2(
 
   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);
 }
 
@@ -777,7 +895,10 @@ cupsRasterReadPixels(cups_raster_t *r,     /* I - Raster stream */
            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...
@@ -847,8 +968,20 @@ cupsRasterWriteHeader(
     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
@@ -859,7 +992,20 @@ cupsRasterWriteHeader(
   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...
@@ -1019,8 +1165,20 @@ cupsRasterWriteHeader2(
     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
@@ -1030,7 +1188,10 @@ cupsRasterWriteHeader2(
   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)
   {
@@ -1202,7 +1363,6 @@ cupsRasterWritePixels(cups_raster_t *r,   /* I - Raster stream */
          r->header.cupsBitsPerPixel == 16))
     {
       unsigned char    *bufptr;        /* Pointer into write buffer */
-      unsigned         count;          /* Remaining count */
 
      /*
       * Allocate a write buffer as needed...
@@ -1223,21 +1383,10 @@ cupsRasterWritePixels(cups_raster_t *r, /* I - Raster stream */
       }
 
      /*
-      * 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);
     }
@@ -1368,7 +1517,7 @@ cups_raster_read_header(
   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);
@@ -1523,10 +1672,7 @@ cups_raster_io(cups_raster_t *r, /* I - Raster stream */
 
     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.");
@@ -1538,6 +1684,7 @@ cups_raster_io(cups_raster_t *r,  /* I - Raster stream */
 #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);
@@ -1558,7 +1705,7 @@ cups_raster_read(cups_raster_t *r,        /* I - Raster stream */
                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));
@@ -1602,7 +1749,7 @@ cups_raster_read(cups_raster_t *r,        /* I - Raster stream */
   {
     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)
     {
@@ -1612,6 +1759,10 @@ cups_raster_read(cups_raster_t *r,       /* I - Raster stream */
         * 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);
@@ -1635,6 +1786,7 @@ cups_raster_read(cups_raster_t *r,        /* I - Raster stream */
          return (0);
 
 #ifdef DEBUG
+       r->iostart += (size_t)count;
         r->iocount += (size_t)count;
 #endif /* DEBUG */
 
@@ -1687,7 +1839,7 @@ cups_raster_read(cups_raster_t *r,        /* I - Raster stream */
     }
   }
 
-  DEBUG_printf(("6cups_raster_read: Returning %ld", (long)total));
+  DEBUG_printf(("5cups_raster_read: Returning %ld", (long)total));
 
   return (total);
 }
@@ -1850,11 +2002,24 @@ cups_raster_write(
   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...
   */
 
@@ -1905,8 +2070,8 @@ cups_raster_write(
       */
 
       *wptr++ = 0;
-      for (count = bpp; count > 0; count --)
-        *wptr++ = *start++;
+      (*cf)(wptr, start, bpp);
+      wptr += bpp;
     }
     else if (!memcmp(start, ptr, bpp))
     {
@@ -1919,8 +2084,9 @@ cups_raster_write(
          break;
 
       *wptr++ = (unsigned char)(count - 1);
-      for (count = bpp; count > 0; count --)
-        *wptr++ = *ptr++;
+      (*cf)(wptr, ptr, bpp);
+      wptr += bpp;
+      ptr  += bpp;
     }
     else
     {
@@ -1941,7 +2107,7 @@ cups_raster_write(
       *wptr++ = (unsigned char)(257 - count);
 
       count *= bpp;
-      memcpy(wptr, start, count);
+      (*cf)(wptr, start, count);
       wptr += count;
     }
   }
@@ -1973,11 +2139,11 @@ cups_read_fd(void          *ctx,        /* I - File descriptor as pointer */
 #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);
 }
@@ -2009,6 +2175,30 @@ cups_swap(unsigned char *buf,            /* I - Buffer to swap */
 }
 
 
+/*
+ * '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.
  */
@@ -2030,7 +2220,7 @@ cups_write_fd(void          *ctx, /* I - File descriptor pointer */
 #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);
     }
 
index d628dc6c3417c7f6b0a53ab473f35c930a4e19f5..c36c1d24d6244f33249a66ecc16a609495fcee3f 100644 (file)
@@ -2369,25 +2369,38 @@ cupsdSendHeader(
       * 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;
         }
@@ -2397,16 +2410,18 @@ cupsdSendHeader(
        {
 #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])
index bc52d2add18543bb02ac61ae2b6a969021fe4f75..8c2694f74b649bc19fc353d5bb0f68648aa34d2c 100644 (file)
@@ -617,7 +617,7 @@ cupsdReadConfiguration(void)
   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();
@@ -2999,7 +2999,9 @@ read_cupsd_conf(cups_file_t *fp)  /* I - File to read from */
       * 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)
       {
@@ -3023,24 +3025,40 @@ read_cupsd_conf(cups_file_t *fp)        /* I - File to read from */
          * 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")
index 8925c8373336d9a4855ca8e5b0606dc4c6968ef3..acf031684e66a7423a38822e49a866e6baac0bd6 100644 (file)
@@ -893,7 +893,7 @@ main(int  argc,                             /* I - Number of command-line args */
     * Write dirty config/state files...
     */
 
-    if (DirtyCleanTime && current_time >= DirtyCleanTime && cupsArrayCount(Clients) == 0)
+    if (DirtyCleanTime && current_time >= DirtyCleanTime)
       cupsdCleanDirty();
 
 #ifdef __APPLE__
index 9672b080ae7990df0bebd024659b779afe8802b7..5033459d0b242d01ebcc1720056d0c980cfbd807 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * "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
@@ -586,33 +586,10 @@ main(int  argc,                           /* I - Number of command-line arguments */
 
   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);
   }
index c608c2d30f01451e995eb8c732040be154f16441..bf238ed42b272fb0ae2e0ee2b8fa045d5ebc74e8 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * "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
@@ -33,7 +33,7 @@ static int            delete_printer_from_class(http_t *http, char *printer,
 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,
@@ -218,6 +218,25 @@ main(int  argc,                    /* I - Number of command-line arguments */
 
                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 */
@@ -593,7 +612,7 @@ main(int  argc,                     /* I - Number of command-line arguments */
 
   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);
@@ -1144,20 +1163,31 @@ enable_printer(http_t *http,            /* I - Server connection */
  * '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"
+  };
 
 
  /*
@@ -1198,9 +1228,21 @@ get_printer_ppd(const char *uri, /* I - Printer URI */
 
   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);
@@ -1572,8 +1614,7 @@ validate_name(const char *name)           /* I - Name to check */
   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);
 
  /*