]> git.ipfire.org Git - thirdparty/cups.git/blobdiff - scheduler/conf.c
Add missing DNSSD.LIB functions.
[thirdparty/cups.git] / scheduler / conf.c
index a58de4204b019058d3dfeb95c3875146589f3b6d..b51c6060c55c421761cac6cae690257a599be6bd 100644 (file)
@@ -1,16 +1,11 @@
 /*
- * "$Id$"
- *
  * Configuration routines for the CUPS scheduler.
  *
- * Copyright 2007-2015 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
- * law.  Distribution and use rights are outlined in the file "LICENSE.txt"
- * which should have been included with this file.  If this file is
- * file is missing or damaged, see the license at "http://www.cups.org/".
+ * Licensed under Apache License v2.0.  See the file "LICENSE" for more
+ * information.
  */
 
 /*
 #include <stdarg.h>
 #include <grp.h>
 #include <sys/utsname.h>
+#ifdef HAVE_ASL_H
+#  include <asl.h>
+#elif defined(HAVE_SYSTEMD_SD_JOURNAL_H)
+#  define SD_JOURNAL_SUPPRESS_LOCATION
+#  include <systemd/sd-journal.h>
+#endif /* HAVE_ASL_H */
 #include <syslog.h>
 
 #ifdef HAVE_LIBPAPER
@@ -79,15 +80,18 @@ static const cupsd_var_t    cupsd_vars[] =
   { "DefaultPolicy",           &DefaultPolicy,         CUPSD_VARTYPE_STRING },
   { "DefaultShared",           &DefaultShared,         CUPSD_VARTYPE_BOOLEAN },
   { "DirtyCleanInterval",      &DirtyCleanInterval,    CUPSD_VARTYPE_TIME },
+#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
+  { "DNSSDHostName",           &DNSSDHostName,         CUPSD_VARTYPE_STRING },
+#endif /* HAVE_DNSSD || HAVE_AVAHI */
   { "ErrorPolicy",             &ErrorPolicy,           CUPSD_VARTYPE_STRING },
   { "FilterLimit",             &FilterLimit,           CUPSD_VARTYPE_INTEGER },
   { "FilterNice",              &FilterNice,            CUPSD_VARTYPE_INTEGER },
 #ifdef HAVE_GSSAPI
   { "GSSServiceName",          &GSSServiceName,        CUPSD_VARTYPE_STRING },
 #endif /* HAVE_GSSAPI */
-#if defined(HAVE_LAUNCHD) || defined(HAVE_SYSTEMD)
+#ifdef HAVE_ONDEMAND
   { "IdleExitTimeout",         &IdleExitTimeout,       CUPSD_VARTYPE_TIME },
-#endif /* HAVE_LAUNCHD || HAVE_SYSTEMD */
+#endif /* HAVE_ONDEMAND */
   { "JobKillDelay",            &JobKillDelay,          CUPSD_VARTYPE_TIME },
   { "JobRetryLimit",           &JobRetryLimit,         CUPSD_VARTYPE_INTEGER },
   { "JobRetryInterval",                &JobRetryInterval,      CUPSD_VARTYPE_TIME },
@@ -134,6 +138,9 @@ static const cupsd_var_t    cupsfiles_vars[] =
   { "AccessLog",               &AccessLog,             CUPSD_VARTYPE_STRING },
   { "CacheDir",                        &CacheDir,              CUPSD_VARTYPE_STRING },
   { "ConfigFilePerm",          &ConfigFilePerm,        CUPSD_VARTYPE_PERM },
+#ifdef HAVE_SSL
+  { "CreateSelfSignedCerts",   &CreateSelfSignedCerts, CUPSD_VARTYPE_BOOLEAN },
+#endif /* HAVE_SSL */
   { "DataDir",                 &DataDir,               CUPSD_VARTYPE_STRING },
   { "DocumentRoot",            &DocumentRoot,          CUPSD_VARTYPE_STRING },
   { "ErrorLog",                        &ErrorLog,              CUPSD_VARTYPE_STRING },
@@ -183,7 +190,7 @@ static void         mime_error_cb(void *ctx, const char *message);
 static int             parse_aaa(cupsd_location_t *loc, char *line,
                                  char *value, int linenum);
 static int             parse_fatal_errors(const char *s);
-static int             parse_groups(const char *s);
+static int             parse_groups(const char *s, int linenum);
 static int             parse_protocols(const char *s);
 static int             parse_variable(const char *filename, int linenum,
                                       const char *line, const char *value,
@@ -269,8 +276,11 @@ cupsdCheckPermissions(
                          "Unable to create directory \"%s\" - %s", filename,
                          strerror(errno));
         else
-         syslog(LOG_ERR, "Unable to create directory \"%s\" - %s", filename,
-                strerror(errno));
+#ifdef HAVE_SYSTEMD_SD_JOURNAL_H
+         sd_journal_print(LOG_ERR, "Unable to create directory \"%s\" - %s", filename, strerror(errno));
+#else
+         syslog(LOG_ERR, "Unable to create directory \"%s\" - %s", filename, strerror(errno));
+#endif /* HAVE_SYSTEMD_SD_JOURNAL_H */
 
         return (-1);
       }
@@ -307,7 +317,11 @@ cupsdCheckPermissions(
     if (create_dir >= 0)
       cupsdLogMessage(CUPSD_LOG_ERROR, "\"%s\" is not a directory.", filename);
     else
+#ifdef HAVE_SYSTEMD_SD_JOURNAL_H
+      sd_journal_print(LOG_ERR, "\"%s\" is not a directory.", filename);
+#else
       syslog(LOG_ERR, "\"%s\" is not a directory.", filename);
+#endif /* HAVE_SYSTEMD_SD_JOURNAL_H */
 
     return (-1);
   }
@@ -336,8 +350,11 @@ cupsdCheckPermissions(
                        "Unable to change ownership of \"%s\" - %s", filename,
                        strerror(errno));
       else
-       syslog(LOG_ERR, "Unable to change ownership of \"%s\" - %s", filename,
-              strerror(errno));
+#ifdef HAVE_SYSTEMD_SD_JOURNAL_H
+       sd_journal_print(LOG_ERR, "Unable to change ownership of \"%s\" - %s", filename, strerror(errno));
+#else
+       syslog(LOG_ERR, "Unable to change ownership of \"%s\" - %s", filename, strerror(errno));
+#endif /* HAVE_SYSTEMD_SD_JOURNAL_H */
 
       return (1);
     }
@@ -356,8 +373,11 @@ cupsdCheckPermissions(
                        "Unable to change permissions of \"%s\" - %s", filename,
                        strerror(errno));
       else
-       syslog(LOG_ERR, "Unable to change permissions of \"%s\" - %s", filename,
-              strerror(errno));
+#ifdef HAVE_SYSTEMD_SD_JOURNAL_H
+       sd_journal_print(LOG_ERR, "Unable to change permissions of \"%s\" - %s", filename, strerror(errno));
+#else
+       syslog(LOG_ERR, "Unable to change permissions of \"%s\" - %s", filename, strerror(errno));
+#endif /* HAVE_SYSTEMD_SD_JOURNAL_H */
 
       return (1);
     }
@@ -597,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();
@@ -686,6 +706,7 @@ cupsdReadConfiguration(void)
   FatalErrors              = parse_fatal_errors(CUPS_DEFAULT_FATAL_ERRORS);
   default_auth_type        = CUPSD_AUTH_BASIC;
 #ifdef HAVE_SSL
+  CreateSelfSignedCerts    = TRUE;
   DefaultEncryption        = HTTP_ENCRYPT_REQUIRED;
 #endif /* HAVE_SSL */
   DirtyCleanInterval       = DEFAULT_KEEPALIVE;
@@ -725,6 +746,7 @@ cupsdReadConfiguration(void)
 
 #if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
   cupsdSetString(&DNSSDSubTypes, "_cups,_print");
+  cupsdClearString(&DNSSDHostName);
 #endif /* HAVE_DNSSD || HAVE_AVAHI */
 
   cupsdSetString(&LPDConfigFile, CUPS_DEFAULT_LPD_CONFIG_FILE);
@@ -757,9 +779,9 @@ cupsdReadConfiguration(void)
   DefaultLeaseDuration       = 86400;
   MaxLeaseDuration           = 0;
 
-#if defined(HAVE_LAUNCHD) || defined(HAVE_SYSTEMD)
+#ifdef HAVE_ONDEMAND
   IdleExitTimeout = 60;
-#endif /* HAVE_LAUNCHD || HAVE_SYSTEMD */
+#endif /* HAVE_ONDEMAND */
 
  /*
   * Setup environment variables...
@@ -782,8 +804,11 @@ cupsdReadConfiguration(void)
       if (TestConfigFile)
         printf("\"%s\" contains errors.\n", CupsFilesFile);
       else
-        syslog(LOG_LPR, "Unable to read \"%s\" due to errors.",
-               CupsFilesFile);
+#ifdef HAVE_SYSTEMD_SD_JOURNAL_H
+       sd_journal_print(LOG_ERR, "Unable to read \"%s\" due to errors.", CupsFilesFile);
+#else
+        syslog(LOG_LPR, "Unable to read \"%s\" due to errors.", CupsFilesFile);
+#endif /* HAVE_SYSTEMD_SD_JOURNAL_H */
 
       return (0);
     }
@@ -792,8 +817,12 @@ cupsdReadConfiguration(void)
     cupsdLogMessage(CUPSD_LOG_INFO, "No %s, using defaults.", CupsFilesFile);
   else
   {
-    syslog(LOG_LPR, "Unable to open \"%s\": %s", CupsFilesFile,
-          strerror(errno));
+#ifdef HAVE_SYSTEMD_SD_JOURNAL_H
+    sd_journal_print(LOG_ERR, "Unable to open \"%s\" - %s", CupsFilesFile, strerror(errno));
+#else
+    syslog(LOG_LPR, "Unable to open \"%s\" - %s", CupsFilesFile, strerror(errno));
+#endif /* HAVE_SYSTEMD_SD_JOURNAL_H */
+
     return (0);
   }
 
@@ -806,8 +835,12 @@ cupsdReadConfiguration(void)
 
   if ((fp = cupsFileOpen(ConfigurationFile, "r")) == NULL)
   {
-    syslog(LOG_LPR, "Unable to open \"%s\": %s", ConfigurationFile,
-          strerror(errno));
+#ifdef HAVE_SYSTEMD_SD_JOURNAL_H
+    sd_journal_print(LOG_ERR, "Unable to open \"%s\" - %s", ConfigurationFile, strerror(errno));
+#else
+    syslog(LOG_LPR, "Unable to open \"%s\" - %s", ConfigurationFile, strerror(errno));
+#endif /* HAVE_SYSTEMD_SD_JOURNAL_H */
+
     return (0);
   }
 
@@ -820,8 +853,11 @@ cupsdReadConfiguration(void)
     if (TestConfigFile)
       printf("\"%s\" contains errors.\n", ConfigurationFile);
     else
-      syslog(LOG_LPR, "Unable to read \"%s\" due to errors.",
-            ConfigurationFile);
+#ifdef HAVE_SYSTEMD_SD_JOURNAL_H
+      sd_journal_print(LOG_ERR, "Unable to read \"%s\" due to errors.", ConfigurationFile);
+#else
+      syslog(LOG_LPR, "Unable to read \"%s\" due to errors.", ConfigurationFile);
+#endif /* HAVE_SYSTEMD_SD_JOURNAL_H */
 
     return (0);
   }
@@ -843,6 +879,7 @@ cupsdReadConfiguration(void)
     if (!ServerAlias)
       ServerAlias = cupsArrayNew(NULL, NULL);
 
+    cupsdAddAlias(ServerAlias, ServerName);
     cupsdLogMessage(CUPSD_LOG_DEBUG, "Added auto ServerAlias %s", ServerName);
   }
   else
@@ -918,7 +955,7 @@ cupsdReadConfiguration(void)
 
   if (NumSystemGroups == 0)
   {
-    if (!parse_groups(CUPS_DEFAULT_SYSTEM_GROUPS))
+    if (!parse_groups(CUPS_DEFAULT_SYSTEM_GROUPS, 0))
     {
      /*
       * Find the group associated with GID 0...
@@ -948,25 +985,24 @@ cupsdReadConfiguration(void)
   * Open the system log for cupsd if necessary...
   */
 
-#ifdef HAVE_VSYSLOG
+  if (!LogStderr)
+  {
+    if (!strcmp(AccessLog, "stderr"))
+      cupsdSetString(&AccessLog, "syslog");
+
+    if (!strcmp(ErrorLog, "stderr"))
+      cupsdSetString(&ErrorLog, "syslog");
+
+    if (!strcmp(PageLog, "stderr"))
+      cupsdSetString(&PageLog, "syslog");
+  }
+
+#if defined(HAVE_VSYSLOG) && !defined(HAVE_ASL_H) && !defined(HAVE_SYSTEMD_SD_JOURNAL_H)
   if (!strcmp(AccessLog, "syslog") ||
       !strcmp(ErrorLog, "syslog") ||
       !strcmp(PageLog, "syslog"))
     openlog("cupsd", LOG_PID | LOG_NOWAIT | LOG_NDELAY, LOG_LPR);
-#endif /* HAVE_VSYSLOG */
-
- /*
-  * Make sure each of the log files exists and gets rotated as necessary...
-  */
-
-  if (strcmp(AccessLog, "syslog"))
-    cupsdCheckLogFile(&AccessFile, AccessLog);
-
-  if (strcmp(ErrorLog, "syslog"))
-    cupsdCheckLogFile(&ErrorFile, ErrorLog);
-
-  if (strcmp(PageLog, "syslog"))
-    cupsdCheckLogFile(&PageFile, PageLog);
+#endif /* HAVE_VSYSLOG && !HAVE_ASL_H && !HAVE_SYSTEMD_SD_JOURNAL_H */
 
  /*
   * Log the configuration file that was used...
@@ -1065,11 +1101,15 @@ cupsdReadConfiguration(void)
     cupsdSetStringf(&CacheDir, "%s/%s", ServerRoot, CacheDir);
 
 #ifdef HAVE_SSL
-  if (ServerKeychain[0] != '/')
+  if (!_cups_strcasecmp(ServerKeychain, "internal"))
+    cupsdClearString(&ServerKeychain);
+  else if (ServerKeychain[0] != '/')
     cupsdSetStringf(&ServerKeychain, "%s/%s", ServerRoot, ServerKeychain);
 
-  cupsdLogMessage(CUPSD_LOG_DEBUG, "Using keychain \"%s\" for server name \"%s\".", ServerKeychain, ServerName);
-  cupsSetServerCredentials(ServerKeychain, ServerName, 1);
+  cupsdLogMessage(CUPSD_LOG_DEBUG, "Using keychain \"%s\" for server name \"%s\".", ServerKeychain ? ServerKeychain : "internal", ServerName);
+  if (!CreateSelfSignedCerts)
+    cupsdLogMessage(CUPSD_LOG_DEBUG, "Self-signed TLS certificate generation is disabled.");
+  cupsSetServerCredentials(ServerKeychain, ServerName, CreateSelfSignedCerts);
 #endif /* HAVE_SSL */
 
  /*
@@ -1442,13 +1482,25 @@ cupsdReadConfiguration(void)
     }
   }
 
-  cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdReadConfiguration: NumPolicies=%d",
-                  cupsArrayCount(Policies));
-  for (i = 0, p = (cupsd_policy_t *)cupsArrayFirst(Policies);
-       p;
-       i ++, p = (cupsd_policy_t *)cupsArrayNext(Policies))
-    cupsdLogMessage(CUPSD_LOG_DEBUG2,
-                    "cupsdReadConfiguration: Policies[%d]=\"%s\"", i, p->name);
+  if (LogLevel >= CUPSD_LOG_DEBUG2)
+  {
+    cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdReadConfiguration: NumPolicies=%d",
+                   cupsArrayCount(Policies));
+    for (i = 0, p = (cupsd_policy_t *)cupsArrayFirst(Policies);
+        p;
+        i ++, p = (cupsd_policy_t *)cupsArrayNext(Policies))
+    {
+      int              j;              /* Looping var */
+      cupsd_location_t *loc;           /* Current location */
+
+      cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdReadConfiguration: Policies[%d]=\"%s\"", i, p->name);
+
+      for (j = 0, loc = (cupsd_location_t *)cupsArrayFirst(p->ops); loc; j ++, loc = (cupsd_location_t *)cupsArrayNext(p->ops))
+      {
+        cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdReadConfiguration:     ops[%d]=%s", j, ippOpString(loc->op));
+      }
+    }
+  }
 
  /*
   * If we are doing a full reload or the server root has changed, flush
@@ -2195,7 +2247,6 @@ parse_aaa(cupsd_location_t *loc,  /* I - Location */
       if (loc->level == CUPSD_AUTH_ANON)
        loc->level = CUPSD_AUTH_USER;
     }
-#ifdef HAVE_GSSAPI
     else if (!_cups_strcasecmp(value, "negotiate"))
     {
       loc->type = CUPSD_AUTH_NEGOTIATE;
@@ -2203,7 +2254,6 @@ parse_aaa(cupsd_location_t *loc,  /* I - Location */
       if (loc->level == CUPSD_AUTH_ANON)
        loc->level = CUPSD_AUTH_USER;
     }
-#endif /* HAVE_GSSAPI */
     else
     {
       cupsdLogMessage(CUPSD_LOG_WARN,
@@ -2458,7 +2508,8 @@ parse_fatal_errors(const char *s) /* I - FatalErrors string */
  */
 
 static int                             /* O - 1 on success, 0 on failure */
-parse_groups(const char *s)            /* I - Space-delimited groups */
+parse_groups(const char *s,            /* I - Space-delimited groups */
+             int        linenum)        /* I - Line number in cups-files.conf */
 {
   int          status;                 /* Return status */
   char         value[1024],            /* Value string */
@@ -2514,7 +2565,14 @@ parse_groups(const char *s)              /* I - Space-delimited groups */
       NumSystemGroups ++;
     }
     else
+    {
+      if (linenum)
+        cupsdLogMessage(CUPSD_LOG_ERROR, "Unknown SystemGroup \"%s\" on line %d of %s.", valstart, linenum, CupsFilesFile);
+      else
+        cupsdLogMessage(CUPSD_LOG_ERROR, "Unknown default SystemGroup \"%s\".", valstart);
+
       status = 0;
+    }
 
     endgrent();
 
@@ -2839,7 +2897,7 @@ parse_variable(
        else
          snprintf(temp, sizeof(temp), "%s/%s", ServerRoot, value);
 
-       if (access(temp, 0))
+       if (access(temp, 0) && _cups_strcasecmp(value, "internal") && _cups_strcasecmp(line, "ServerKeychain"))
        {
          cupsdLogMessage(CUPSD_LOG_ERROR,
                          "File or directory for \"%s %s\" on line %d of %s "
@@ -2871,13 +2929,10 @@ read_cupsd_conf(cups_file_t *fp)        /* I - File to read from */
                                        /* Line from file */
                        temp[HTTP_MAX_BUFFER],
                                        /* Temporary buffer for value */
-                       *value,         /* Pointer to value */
-                       *valueptr;      /* Pointer into value */
+                       *value;         /* Pointer to value */
   int                  valuelen;       /* Length of value */
   http_addrlist_t      *addrlist,      /* Address list */
                        *addr;          /* Current address */
-  cups_file_t          *incfile;       /* Include file */
-  char                 incname[1024];  /* Include filename */
 
 
  /*
@@ -2892,28 +2947,7 @@ read_cupsd_conf(cups_file_t *fp) /* I - File to read from */
     * Decode the directive...
     */
 
-    if (!_cups_strcasecmp(line, "Include") && value)
-    {
-     /*
-      * Include filename
-      */
-
-      if (value[0] == '/')
-        strlcpy(incname, value, sizeof(incname));
-      else
-        snprintf(incname, sizeof(incname), "%s/%s", ServerRoot, value);
-
-      if ((incfile = cupsFileOpen(incname, "rb")) == NULL)
-        cupsdLogMessage(CUPSD_LOG_ERROR,
-                       "Unable to include config file \"%s\" - %s",
-                       incname, strerror(errno));
-      else
-      {
-        read_cupsd_conf(incfile);
-       cupsFileClose(incfile);
-      }
-    }
-    else if (!_cups_strcasecmp(line, "<Location") && value)
+    if (!_cups_strcasecmp(line, "<Location") && value)
     {
      /*
       * <Location path>
@@ -2951,10 +2985,12 @@ read_cupsd_conf(cups_file_t *fp)        /* I - File to read from */
     else if (!_cups_strcasecmp(line, "SSLOptions"))
     {
      /*
-      * SSLOptions [AllowRC4] [AllowSSL3] [None]
+      * 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)
       {
@@ -2978,18 +3014,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, "None"))
-           options = 0;
+         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"))
+           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")
@@ -3037,9 +3095,9 @@ read_cupsd_conf(cups_file_t *fp)  /* I - File to read from */
 
         if (lis)
        {
-#if defined(HAVE_LAUNCHD) || defined(HAVE_SYSTEMD)
+#ifdef HAVE_ONDEMAND
          if (!lis->on_demand)
-#endif /* HAVE_LAUNCHD || HAVE_SYSTEMD */
+#endif /* HAVE_ONDEMAND */
          {
            httpAddrString(&lis->address, temp, sizeof(temp));
            cupsdLogMessage(CUPSD_LOG_WARN,
@@ -3137,10 +3195,8 @@ read_cupsd_conf(cups_file_t *fp) /* I - File to read from */
        default_auth_type = CUPSD_AUTH_NONE;
       else if (!_cups_strcasecmp(value, "basic"))
        default_auth_type = CUPSD_AUTH_BASIC;
-#ifdef HAVE_GSSAPI
       else if (!_cups_strcasecmp(value, "negotiate"))
         default_auth_type = CUPSD_AUTH_NEGOTIATE;
-#endif /* HAVE_GSSAPI */
       else if (!_cups_strcasecmp(value, "auto"))
         default_auth_type = CUPSD_AUTH_AUTO;
       else
@@ -3282,36 +3338,11 @@ read_cupsd_conf(cups_file_t *fp)        /* I - File to read from */
        cupsdSetStringf(&ServerHeader, CUPS_MINIMAL " (%s %s; %s) IPP/2.1",
                        plat.sysname, plat.release, plat.machine);
       else if (!_cups_strcasecmp(value, "None"))
-       cupsdClearString(&ServerHeader);
+       cupsdSetString(&ServerHeader, "");
       else
        cupsdLogMessage(CUPSD_LOG_WARN, "Unknown ServerTokens %s on line %d of %s.",
                         value, linenum, ConfigurationFile);
     }
-    else if (!_cups_strcasecmp(line, "PassEnv") && value)
-    {
-     /*
-      * PassEnv variable [... variable]
-      */
-
-      for (; *value;)
-      {
-        for (valuelen = 0; value[valuelen]; valuelen ++)
-         if (_cups_isspace(value[valuelen]) || value[valuelen] == ',')
-           break;
-
-        if (value[valuelen])
-        {
-         value[valuelen] = '\0';
-         valuelen ++;
-       }
-
-        cupsdSetEnv(value, NULL);
-
-        for (value += valuelen; *value; value ++)
-         if (!_cups_isspace(*value) || *value != ',')
-           break;
-      }
-    }
     else if (!_cups_strcasecmp(line, "ServerAlias") && value)
     {
      /*
@@ -3340,30 +3371,6 @@ read_cupsd_conf(cups_file_t *fp) /* I - File to read from */
            break;
       }
     }
-    else if (!_cups_strcasecmp(line, "SetEnv") && value)
-    {
-     /*
-      * SetEnv variable value
-      */
-
-      for (valueptr = value; *valueptr && !isspace(*valueptr & 255); valueptr ++);
-
-      if (*valueptr)
-      {
-       /*
-        * Found a value...
-       */
-
-        while (isspace(*valueptr & 255))
-         *valueptr++ = '\0';
-
-        cupsdSetEnv(value, valueptr);
-      }
-      else
-        cupsdLogMessage(CUPSD_LOG_ERROR,
-                       "Missing value for SetEnv directive on line %d of %s.",
-                       linenum, ConfigurationFile);
-    }
     else if (!_cups_strcasecmp(line, "AccessLog") ||
              !_cups_strcasecmp(line, "CacheDir") ||
              !_cups_strcasecmp(line, "ConfigFilePerm") ||
@@ -3377,6 +3384,7 @@ read_cupsd_conf(cups_file_t *fp)  /* I - File to read from */
              !_cups_strcasecmp(line, "LogFilePerm") ||
              !_cups_strcasecmp(line, "LPDConfigFile") ||
              !_cups_strcasecmp(line, "PageLog") ||
+             !_cups_strcasecmp(line, "PassEnv") ||
              !_cups_strcasecmp(line, "Printcap") ||
              !_cups_strcasecmp(line, "PrintcapFormat") ||
              !_cups_strcasecmp(line, "RemoteRoot") ||
@@ -3386,6 +3394,7 @@ read_cupsd_conf(cups_file_t *fp)  /* I - File to read from */
              !_cups_strcasecmp(line, "ServerKey") ||
              !_cups_strcasecmp(line, "ServerKeychain") ||
              !_cups_strcasecmp(line, "ServerRoot") ||
+             !_cups_strcasecmp(line, "SetEnv") ||
              !_cups_strcasecmp(line, "SMBConfigFile") ||
              !_cups_strcasecmp(line, "StateDir") ||
              !_cups_strcasecmp(line, "SystemGroup") ||
@@ -3415,10 +3424,49 @@ read_cupsd_conf(cups_file_t *fp)        /* I - File to read from */
 static int                             /* O - 1 on success, 0 on failure */
 read_cups_files_conf(cups_file_t *fp)  /* I - File to read from */
 {
-  int          linenum;                /* Current line number */
+  int          i,                      /* Looping var */
+               linenum;                /* Current line number */
   char         line[HTTP_MAX_BUFFER],  /* Line from file */
                *value;                 /* Value from line */
   struct group *group;                 /* Group */
+  static const char * const prohibited_env[] =
+  {                                    /* Prohibited environment variables */
+    "APPLE_LANGUAGE",
+    "AUTH_DOMAIN",
+    "AUTH_INFO_REQUIRED",
+    "AUTH_NEGOTIATE",
+    "AUTH_PASSWORD",
+    "AUTH_UID",
+    "AUTH_USERNAME",
+    "CHARSET",
+    "CLASS",
+    "CLASSIFICATION",
+    "CONTENT_TYPE",
+    "CUPS_CACHEDIR",
+    "CUPS_DATADIR",
+    "CUPS_DOCROOT",
+    "CUPS_FILETYPE",
+    "CUPS_FONTPATH",
+    "CUPS_MAX_MESSAGE",
+    "CUPS_REQUESTROOT",
+    "CUPS_SERVERBIN",
+    "CUPS_SERVERROOT",
+    "CUPS_STATEDIR",
+    "DEVICE_URI",
+    "FINAL_CONTENT_TYPE",
+    "HOME",
+    "LANG",
+    "PPD",
+    "PRINTER",
+    "PRINTER_INFO",
+    "PRINTER_LOCATION",
+    "PRINTER_STATE_REASONS",
+    "RIP_CACHE",
+    "SERVER_ADMIN",
+    "SOFTWARE",
+    "TMPDIR",
+    "USER"
+  };
 
 
  /*
@@ -3456,6 +3504,47 @@ read_cups_files_conf(cups_file_t *fp)    /* I - File to read from */
        }
       }
     }
+    else if (!_cups_strcasecmp(line, "PassEnv") && value)
+    {
+     /*
+      * PassEnv variable [... variable]
+      */
+
+      int valuelen;                    /* Length of variable name */
+
+      for (; *value;)
+      {
+        for (valuelen = 0; value[valuelen]; valuelen ++)
+         if (_cups_isspace(value[valuelen]) || value[valuelen] == ',')
+           break;
+
+        if (value[valuelen])
+        {
+         value[valuelen] = '\0';
+         valuelen ++;
+       }
+
+        for (i = 0; i < (int)(sizeof(prohibited_env) / sizeof(prohibited_env[0])); i ++)
+        {
+          if (!strcmp(value, prohibited_env[i]))
+          {
+           cupsdLogMessage(CUPSD_LOG_ERROR, "Environment variable \"%s\" cannot be passed through on line %d of %s.", value, linenum, CupsFilesFile);
+
+           if (FatalErrors & CUPSD_FATAL_CONFIG)
+             return (0);
+           else
+             break;
+          }
+       }
+
+        if (i >= (int)(sizeof(prohibited_env) / sizeof(prohibited_env[0])))
+          cupsdSetEnv(value, NULL);
+
+        for (value += valuelen; *value; value ++)
+         if (!_cups_isspace(*value) || *value != ',')
+           break;
+      }
+    }
     else if (!_cups_strcasecmp(line, "PrintcapFormat") && value)
     {
      /*
@@ -3501,17 +3590,54 @@ read_cups_files_conf(cups_file_t *fp)   /* I - File to read from */
           return (0);
       }
     }
+    else if (!_cups_strcasecmp(line, "SetEnv") && value)
+    {
+     /*
+      * SetEnv variable value
+      */
+
+      char *valueptr;                  /* Pointer to environment variable value */
+
+      for (valueptr = value; *valueptr && !isspace(*valueptr & 255); valueptr ++);
+
+      if (*valueptr)
+      {
+       /*
+        * Found a value...
+       */
+
+        while (isspace(*valueptr & 255))
+         *valueptr++ = '\0';
+
+        for (i = 0; i < (int)(sizeof(prohibited_env) / sizeof(prohibited_env[0])); i ++)
+        {
+          if (!strcmp(value, prohibited_env[i]))
+          {
+           cupsdLogMessage(CUPSD_LOG_ERROR, "Environment variable \"%s\" cannot be set  on line %d of %s.", value, linenum, CupsFilesFile);
+
+           if (FatalErrors & CUPSD_FATAL_CONFIG)
+             return (0);
+           else
+             break;
+          }
+       }
+
+        if (i >= (int)(sizeof(prohibited_env) / sizeof(prohibited_env[0])))
+         cupsdSetEnv(value, valueptr);
+      }
+      else
+        cupsdLogMessage(CUPSD_LOG_ERROR,
+                       "Missing value for SetEnv directive on line %d of %s.",
+                       linenum, ConfigurationFile);
+    }
     else if (!_cups_strcasecmp(line, "SystemGroup") && value)
     {
      /*
       * SystemGroup (admin) group(s)...
       */
 
-      if (!parse_groups(value))
+      if (!parse_groups(value, linenum))
       {
-       cupsdLogMessage(CUPSD_LOG_ERROR,
-                       "Unknown SystemGroup \"%s\" on line %d of %s.", value,
-                       linenum, CupsFilesFile);
         if (FatalErrors & CUPSD_FATAL_CONFIG)
           return (0);
       }
@@ -3789,11 +3915,9 @@ read_policy(cups_file_t *fp,             /* I - Configuration file */
         if (num_ops < (int)(sizeof(ops) / sizeof(ops[0])))
        {
          if (!_cups_strcasecmp(value, "All"))
-           ops[num_ops] = IPP_ANY_OPERATION;
+           ops[num_ops ++] = IPP_ANY_OPERATION;
          else if ((ops[num_ops] = ippOpValue(value)) == IPP_BAD_OPERATION)
-           cupsdLogMessage(CUPSD_LOG_ERROR,
-                           "Bad IPP operation name \"%s\" on line %d of %s.",
-                           value, linenum, ConfigurationFile);
+           cupsdLogMessage(CUPSD_LOG_ERROR, "Bad IPP operation name \"%s\" on line %d of %s.", value, linenum, ConfigurationFile);
           else
            num_ops ++;
        }
@@ -3990,121 +4114,106 @@ set_policy_defaults(cupsd_policy_t *pol)/* I - Policy */
   * Verify that we have an explicit policy for Validate-Job, Cancel-Jobs,
   * Cancel-My-Jobs, Close-Job, and CUPS-Get-Document, which ensures that
   * upgrades do not introduce new security issues...
+  *
+  * CUPS STR #4659: Allow a lone <Limit All> policy.
   */
 
-  if ((op = cupsdFindPolicyOp(pol, IPP_VALIDATE_JOB)) == NULL ||
-      op->op == IPP_ANY_OPERATION)
+  if (cupsArrayCount(pol->ops) > 1)
   {
-    if ((op = cupsdFindPolicyOp(pol, IPP_PRINT_JOB)) != NULL &&
-       op->op != IPP_ANY_OPERATION)
+    if ((op = cupsdFindPolicyOp(pol, IPP_VALIDATE_JOB)) == NULL ||
+       op->op == IPP_ANY_OPERATION)
     {
-     /*
-      * Add a new limit for Validate-Job using the Print-Job limit as a
-      * template...
-      */
+      if ((op = cupsdFindPolicyOp(pol, IPP_PRINT_JOB)) != NULL &&
+         op->op != IPP_ANY_OPERATION)
+      {
+       /*
+       * Add a new limit for Validate-Job using the Print-Job limit as a
+       * template...
+       */
 
-      cupsdLogMessage(CUPSD_LOG_WARN,
-                     "No limit for Validate-Job defined in policy %s "
-                     "- using Print-Job's policy.", pol->name);
+       cupsdLogMessage(CUPSD_LOG_WARN, "No limit for Validate-Job defined in policy %s - using Print-Job's policy.", pol->name);
 
-      cupsdAddPolicyOp(pol, op, IPP_VALIDATE_JOB);
+       cupsdAddPolicyOp(pol, op, IPP_VALIDATE_JOB);
+      }
+      else
+       cupsdLogMessage(CUPSD_LOG_WARN, "No limit for Validate-Job defined in policy %s and no suitable template found.", pol->name);
     }
-    else
-      cupsdLogMessage(CUPSD_LOG_WARN,
-                     "No limit for Validate-Job defined in policy %s "
-                     "and no suitable template found.", pol->name);
-  }
 
-  if ((op = cupsdFindPolicyOp(pol, IPP_CANCEL_JOBS)) == NULL ||
-      op->op == IPP_ANY_OPERATION)
-  {
-    if ((op = cupsdFindPolicyOp(pol, IPP_PAUSE_PRINTER)) != NULL &&
-       op->op != IPP_ANY_OPERATION)
+    if ((op = cupsdFindPolicyOp(pol, IPP_CANCEL_JOBS)) == NULL ||
+       op->op == IPP_ANY_OPERATION)
     {
-     /*
-      * Add a new limit for Cancel-Jobs using the Pause-Printer limit as a
-      * template...
-      */
+      if ((op = cupsdFindPolicyOp(pol, IPP_PAUSE_PRINTER)) != NULL &&
+         op->op != IPP_ANY_OPERATION)
+      {
+       /*
+       * Add a new limit for Cancel-Jobs using the Pause-Printer limit as a
+       * template...
+       */
 
-      cupsdLogMessage(CUPSD_LOG_WARN,
-                     "No limit for Cancel-Jobs defined in policy %s "
-                     "- using Pause-Printer's policy.", pol->name);
+       cupsdLogMessage(CUPSD_LOG_WARN, "No limit for Cancel-Jobs defined in policy %s - using Pause-Printer's policy.", pol->name);
 
-      cupsdAddPolicyOp(pol, op, IPP_CANCEL_JOBS);
+       cupsdAddPolicyOp(pol, op, IPP_CANCEL_JOBS);
+      }
+      else
+       cupsdLogMessage(CUPSD_LOG_WARN, "No limit for Cancel-Jobs defined in policy %s and no suitable template found.", pol->name);
     }
-    else
-      cupsdLogMessage(CUPSD_LOG_WARN,
-                     "No limit for Cancel-Jobs defined in policy %s "
-                     "and no suitable template found.", pol->name);
-  }
 
-  if ((op = cupsdFindPolicyOp(pol, IPP_CANCEL_MY_JOBS)) == NULL ||
-      op->op == IPP_ANY_OPERATION)
-  {
-    if ((op = cupsdFindPolicyOp(pol, IPP_SEND_DOCUMENT)) != NULL &&
-       op->op != IPP_ANY_OPERATION)
+    if ((op = cupsdFindPolicyOp(pol, IPP_CANCEL_MY_JOBS)) == NULL ||
+       op->op == IPP_ANY_OPERATION)
     {
-     /*
-      * Add a new limit for Cancel-My-Jobs using the Send-Document limit as
-      * a template...
-      */
+      if ((op = cupsdFindPolicyOp(pol, IPP_SEND_DOCUMENT)) != NULL &&
+         op->op != IPP_ANY_OPERATION)
+      {
+       /*
+       * Add a new limit for Cancel-My-Jobs using the Send-Document limit as
+       * a template...
+       */
 
-      cupsdLogMessage(CUPSD_LOG_WARN,
-                     "No limit for Cancel-My-Jobs defined in policy %s "
-                     "- using Send-Document's policy.", pol->name);
+       cupsdLogMessage(CUPSD_LOG_WARN, "No limit for Cancel-My-Jobs defined in policy %s - using Send-Document's policy.", pol->name);
 
-      cupsdAddPolicyOp(pol, op, IPP_CANCEL_MY_JOBS);
+       cupsdAddPolicyOp(pol, op, IPP_CANCEL_MY_JOBS);
+      }
+      else
+       cupsdLogMessage(CUPSD_LOG_WARN, "No limit for Cancel-My-Jobs defined in policy %s and no suitable template found.", pol->name);
     }
-    else
-      cupsdLogMessage(CUPSD_LOG_WARN,
-                     "No limit for Cancel-My-Jobs defined in policy %s "
-                     "and no suitable template found.", pol->name);
-  }
 
-  if ((op = cupsdFindPolicyOp(pol, IPP_CLOSE_JOB)) == NULL ||
-      op->op == IPP_ANY_OPERATION)
-  {
-    if ((op = cupsdFindPolicyOp(pol, IPP_SEND_DOCUMENT)) != NULL &&
-       op->op != IPP_ANY_OPERATION)
+    if ((op = cupsdFindPolicyOp(pol, IPP_CLOSE_JOB)) == NULL ||
+       op->op == IPP_ANY_OPERATION)
     {
-     /*
-      * Add a new limit for Close-Job using the Send-Document limit as a
-      * template...
-      */
+      if ((op = cupsdFindPolicyOp(pol, IPP_SEND_DOCUMENT)) != NULL &&
+         op->op != IPP_ANY_OPERATION)
+      {
+       /*
+       * Add a new limit for Close-Job using the Send-Document limit as a
+       * template...
+       */
 
-      cupsdLogMessage(CUPSD_LOG_WARN,
-                     "No limit for Close-Job defined in policy %s "
-                     "- using Send-Document's policy.", pol->name);
+       cupsdLogMessage(CUPSD_LOG_WARN, "No limit for Close-Job defined in policy %s - using Send-Document's policy.", pol->name);
 
-      cupsdAddPolicyOp(pol, op, IPP_CLOSE_JOB);
+       cupsdAddPolicyOp(pol, op, IPP_CLOSE_JOB);
+      }
+      else
+       cupsdLogMessage(CUPSD_LOG_WARN, "No limit for Close-Job defined in policy %s and no suitable template found.", pol->name);
     }
-    else
-      cupsdLogMessage(CUPSD_LOG_WARN,
-                     "No limit for Close-Job defined in policy %s "
-                     "and no suitable template found.", pol->name);
-  }
 
-  if ((op = cupsdFindPolicyOp(pol, CUPS_GET_DOCUMENT)) == NULL ||
-      op->op == IPP_ANY_OPERATION)
-  {
-    if ((op = cupsdFindPolicyOp(pol, IPP_SEND_DOCUMENT)) != NULL &&
-       op->op != IPP_ANY_OPERATION)
+    if ((op = cupsdFindPolicyOp(pol, CUPS_GET_DOCUMENT)) == NULL ||
+       op->op == IPP_ANY_OPERATION)
     {
-     /*
-      * Add a new limit for CUPS-Get-Document using the Send-Document
-      * limit as a template...
-      */
+      if ((op = cupsdFindPolicyOp(pol, IPP_SEND_DOCUMENT)) != NULL &&
+         op->op != IPP_ANY_OPERATION)
+      {
+       /*
+       * Add a new limit for CUPS-Get-Document using the Send-Document
+       * limit as a template...
+       */
 
-      cupsdLogMessage(CUPSD_LOG_WARN,
-                     "No limit for CUPS-Get-Document defined in policy %s "
-                     "- using Send-Document's policy.", pol->name);
+       cupsdLogMessage(CUPSD_LOG_WARN, "No limit for CUPS-Get-Document defined in policy %s - using Send-Document's policy.", pol->name);
 
-      cupsdAddPolicyOp(pol, op, CUPS_GET_DOCUMENT);
+       cupsdAddPolicyOp(pol, op, CUPS_GET_DOCUMENT);
+      }
+      else
+       cupsdLogMessage(CUPSD_LOG_WARN, "No limit for CUPS-Get-Document defined in policy %s and no suitable template found.", pol->name);
     }
-    else
-      cupsdLogMessage(CUPSD_LOG_WARN,
-                     "No limit for CUPS-Get-Document defined in policy %s "
-                     "and no suitable template found.", pol->name);
   }
 
  /*
@@ -4114,18 +4223,14 @@ set_policy_defaults(cupsd_policy_t *pol)/* I - Policy */
 
   if (!pol->job_access)
   {
-    cupsdLogMessage(CUPSD_LOG_WARN,
-                   "No JobPrivateAccess defined in policy %s "
-                   "- using defaults.", pol->name);
+    cupsdLogMessage(CUPSD_LOG_WARN, "No JobPrivateAccess defined in policy %s - using defaults.", pol->name);
     cupsdAddString(&(pol->job_access), "@OWNER");
     cupsdAddString(&(pol->job_access), "@SYSTEM");
   }
 
   if (!pol->job_attrs)
   {
-    cupsdLogMessage(CUPSD_LOG_WARN,
-                   "No JobPrivateValues defined in policy %s "
-                   "- using defaults.", pol->name);
+    cupsdLogMessage(CUPSD_LOG_WARN, "No JobPrivateValues defined in policy %s - using defaults.", pol->name);
     cupsdAddString(&(pol->job_attrs), "job-name");
     cupsdAddString(&(pol->job_attrs), "job-originating-host-name");
     cupsdAddString(&(pol->job_attrs), "job-originating-user-name");
@@ -4134,18 +4239,14 @@ set_policy_defaults(cupsd_policy_t *pol)/* I - Policy */
 
   if (!pol->sub_access)
   {
-    cupsdLogMessage(CUPSD_LOG_WARN,
-                   "No SubscriptionPrivateAccess defined in policy %s "
-                   "- using defaults.", pol->name);
+    cupsdLogMessage(CUPSD_LOG_WARN, "No SubscriptionPrivateAccess defined in policy %s - using defaults.", pol->name);
     cupsdAddString(&(pol->sub_access), "@OWNER");
     cupsdAddString(&(pol->sub_access), "@SYSTEM");
   }
 
   if (!pol->sub_attrs)
   {
-    cupsdLogMessage(CUPSD_LOG_WARN,
-                   "No SubscriptionPrivateValues defined in policy %s "
-                   "- using defaults.", pol->name);
+    cupsdLogMessage(CUPSD_LOG_WARN, "No SubscriptionPrivateValues defined in policy %s - using defaults.", pol->name);
     cupsdAddString(&(pol->sub_attrs), "notify-events");
     cupsdAddString(&(pol->sub_attrs), "notify-pull-method");
     cupsdAddString(&(pol->sub_attrs), "notify-recipient-uri");
@@ -4153,8 +4254,3 @@ set_policy_defaults(cupsd_policy_t *pol)/* I - Policy */
     cupsdAddString(&(pol->sub_attrs), "notify-user-data");
   }
 }
-
-
-/*
- * End of "$Id$".
- */