]> git.ipfire.org Git - thirdparty/cups.git/blobdiff - scheduler/conf.c
Load cups into easysw/current.
[thirdparty/cups.git] / scheduler / conf.c
index 4306984728d963e38b91b65c7f1f3e20acb4c5a2..7426eab26b433d843ef84900deffa2aa4d9f3b74 100644 (file)
@@ -1,31 +1,22 @@
 /*
- * "$Id: conf.c 5353 2006-03-29 20:31:58Z mike $"
+ * "$Id: conf.c 6649 2007-07-11 21:46:42Z mike $"
  *
  *   Configuration routines for the Common UNIX Printing System (CUPS).
  *
- *   Copyright 1997-2006 by Easy Software Products, all rights reserved.
+ *   Copyright 2007 by Apple Inc.
+ *   Copyright 1997-2007 by Easy Software Products, all rights reserved.
  *
  *   These coded instructions, statements, and computer programs are the
- *   property of Easy Software Products 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 missing or damaged please contact Easy Software Products
- *   at:
- *
- *       Attn: CUPS Licensing Information
- *       Easy Software Products
- *       44141 Airport View Drive, Suite 204
- *       Hollywood, Maryland 20636 USA
- *
- *       Voice: (301) 373-9600
- *       EMail: cups-info@cups.org
- *         WWW: http://www.cups.org
+ *   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/".
  *
  * Contents:
  *
- *   cupsdReadConfiguration() - Read the cupsd.conf file.
- *   check_permissions()      - Fix the mode and ownership of a file or
+ *   cupsdCheckPermissions()  - Fix the mode and ownership of a file or
  *                              directory.
+ *   cupsdReadConfiguration() - Read the cupsd.conf file.
  *   get_address()            - Get an address + port number from a line.
  *   get_addr_and_mask()      - Get an IP address and netmask.
  *   parse_aaa()              - Parse authentication, authorization, and
 #include <stdarg.h>
 #include <grp.h>
 #include <sys/utsname.h>
+#include <syslog.h>
 #include <cups/dir.h>
 
-#ifdef HAVE_VSYSLOG
-#  include <syslog.h>
-#endif /* HAVE_VSYSLOG */
-
 
 /*
  * Possibly missing network definitions...
@@ -87,10 +75,14 @@ typedef struct
 static cupsd_var_t     variables[] =
 {
   { "AccessLog",               &AccessLog,             CUPSD_VARTYPE_STRING },
+#ifdef __APPLE__
+  { "AppleQuotas",             &AppleQuotas,           CUPSD_VARTYPE_BOOLEAN },
+#endif  /* __APPLE__ */
   { "AutoPurgeJobs",           &JobAutoPurge,          CUPSD_VARTYPE_BOOLEAN },
   { "BrowseInterval",          &BrowseInterval,        CUPSD_VARTYPE_INTEGER },
 #ifdef HAVE_LDAP
   { "BrowseLDAPBindDN",                &BrowseLDAPBindDN,      CUPSD_VARTYPE_STRING },
+  { "BrowseLDAPCACertFile",    &BrowseLDAPCACertFile,  CUPSD_VARTYPE_STRING },
   { "BrowseLDAPDN",            &BrowseLDAPDN,          CUPSD_VARTYPE_STRING },
   { "BrowseLDAPPassword",      &BrowseLDAPPassword,    CUPSD_VARTYPE_STRING },
   { "BrowseLDAPServer",                &BrowseLDAPServer,      CUPSD_VARTYPE_STRING },
@@ -113,17 +105,24 @@ static cupsd_var_t        variables[] =
   { "DefaultShared",           &DefaultShared,         CUPSD_VARTYPE_BOOLEAN },
   { "DocumentRoot",            &DocumentRoot,          CUPSD_VARTYPE_STRING },
   { "ErrorLog",                        &ErrorLog,              CUPSD_VARTYPE_STRING },
+  { "ErrorPolicy",             &ErrorPolicy,           CUPSD_VARTYPE_STRING },
   { "FileDevice",              &FileDevice,            CUPSD_VARTYPE_BOOLEAN },
   { "FilterLimit",             &FilterLimit,           CUPSD_VARTYPE_INTEGER },
   { "FilterNice",              &FilterNice,            CUPSD_VARTYPE_INTEGER },
   { "FontPath",                        &FontPath,              CUPSD_VARTYPE_STRING },
-  { "HideImplicitMembers",     &HideImplicitMembers,   CUPSD_VARTYPE_BOOLEAN },
+#ifdef HAVE_GSSAPI
+  { "GSSServiceName",          &GSSServiceName,        CUPSD_VARTYPE_STRING },
+#endif /* HAVE_GSSAPI */
   { "ImplicitClasses",         &ImplicitClasses,       CUPSD_VARTYPE_BOOLEAN },
   { "ImplicitAnyClasses",      &ImplicitAnyClasses,    CUPSD_VARTYPE_BOOLEAN },
   { "JobRetryLimit",           &JobRetryLimit,         CUPSD_VARTYPE_INTEGER },
   { "JobRetryInterval",                &JobRetryInterval,      CUPSD_VARTYPE_INTEGER },
   { "KeepAliveTimeout",                &KeepAliveTimeout,      CUPSD_VARTYPE_INTEGER },
   { "KeepAlive",               &KeepAlive,             CUPSD_VARTYPE_BOOLEAN },
+#ifdef HAVE_LAUNCHD
+  { "LaunchdTimeout",          &LaunchdTimeout,        CUPSD_VARTYPE_INTEGER },
+  { "LaunchdConf",             &LaunchdConf,           CUPSD_VARTYPE_STRING },
+#endif /* HAVE_LAUNCHD */
   { "LimitRequestBody",                &MaxRequestSize,        CUPSD_VARTYPE_INTEGER },
   { "ListenBackLog",           &ListenBackLog,         CUPSD_VARTYPE_INTEGER },
   { "LogFilePerm",             &LogFilePerm,           CUPSD_VARTYPE_INTEGER },
@@ -161,13 +160,12 @@ static cupsd_var_t        variables[] =
   { "ServerKey",               &ServerKey,             CUPSD_VARTYPE_STRING },
 #  endif /* HAVE_LIBSSL || HAVE_GNUTLS */
 #endif /* HAVE_SSL */
-#ifdef HAVE_LAUNCHD
-  { "LaunchdTimeout",          &LaunchdTimeout,        CUPSD_VARTYPE_INTEGER },
-  { "LaunchdConf",             &LaunchdConf,           CUPSD_VARTYPE_STRING },
-#endif /* HAVE_LAUNCHD */
   { "ServerName",              &ServerName,            CUPSD_VARTYPE_STRING },
   { "ServerRoot",              &ServerRoot,            CUPSD_VARTYPE_STRING },
   { "StateDir",                        &StateDir,              CUPSD_VARTYPE_STRING },
+#ifdef HAVE_AUTHORIZATION_H
+  { "SystemGroupAuthKey",      &SystemGroupAuthKey,    CUPSD_VARTYPE_STRING },
+#endif /* HAVE_AUTHORIZATION_H */
   { "TempDir",                 &TempDir,               CUPSD_VARTYPE_STRING },
   { "Timeout",                 &Timeout,               CUPSD_VARTYPE_INTEGER },
   { "UseNetworkDefault",       &UseNetworkDefault,     CUPSD_VARTYPE_BOOLEAN }
@@ -188,10 +186,6 @@ static unsigned            zeros[4] =
 /*
  * Local functions...
  */
-static int             check_permissions(const char *filename,
-                                         const char *suffix, int mode,
-                                         int user, int group, int is_dir,
-                                         int create_dir);
 static http_addrlist_t *get_address(const char *value, int defport);
 static int             get_addr_and_mask(const char *value, unsigned *ip,
                                          unsigned *mask);
@@ -204,6 +198,138 @@ static int                read_location(cups_file_t *fp, char *name, int linenum);
 static int             read_policy(cups_file_t *fp, char *name, int linenum);
 
 
+/*
+ * 'cupsdCheckPermissions()' - Fix the mode and ownership of a file or directory.
+ */
+
+int                                    /* O - 0 on success, -1 on error, 1 on warning */
+cupsdCheckPermissions(
+    const char *filename,              /* I - File/directory name */
+    const char *suffix,                        /* I - Additional file/directory name */
+    int        mode,                   /* I - Permissions */
+    int        user,                   /* I - Owner */
+    int        group,                  /* I - Group */
+    int        is_dir,                 /* I - 1 = directory, 0 = file */
+    int        create_dir)             /* I - 1 = create directory, -1 = create w/o logging, 0 = not */
+{
+  int          dir_created = 0;        /* Did we create a directory? */
+  char         pathname[1024];         /* File name with prefix */
+  struct stat  fileinfo;               /* Stat buffer */
+
+
+ /*
+  * Prepend the given root to the filename before testing it...
+  */
+
+  if (suffix)
+  {
+    snprintf(pathname, sizeof(pathname), "%s/%s", filename, suffix);
+    filename = pathname;
+  }
+
+ /*
+  * See if we can stat the file/directory...
+  */
+
+  if (stat(filename, &fileinfo))
+  {
+    if (errno == ENOENT && create_dir)
+    {
+      if (create_dir > 0)
+       cupsdLogMessage(CUPSD_LOG_DEBUG, "Creating missing directory \"%s\"",
+                       filename);
+
+      if (mkdir(filename, mode))
+      {
+        if (create_dir > 0)
+         cupsdLogMessage(CUPSD_LOG_ERROR,
+                         "Unable to create directory \"%s\" - %s", filename,
+                         strerror(errno));
+        else
+         syslog(LOG_ERR, "Unable to create directory \"%s\" - %s", filename,
+                strerror(errno));
+
+        return (-1);
+      }
+
+      dir_created = 1;
+    }
+    else
+      return (create_dir ? -1 : 1);
+  }
+
+ /*
+  * Make sure it's a regular file...
+  */
+
+  if (!dir_created && !is_dir && !S_ISREG(fileinfo.st_mode))
+  {
+    cupsdLogMessage(CUPSD_LOG_ERROR, "\"%s\" is not a regular file!", filename);
+    return (-1);
+  }
+
+  if (!dir_created && is_dir && !S_ISDIR(fileinfo.st_mode))
+  {
+    if (create_dir >= 0)
+      cupsdLogMessage(CUPSD_LOG_ERROR, "\"%s\" is not a directory!", filename);
+    else
+      syslog(LOG_ERR, "\"%s\" is not a directory!", filename);
+
+    return (-1);
+  }
+
+ /*
+  * Fix owner, group, and mode as needed...
+  */
+
+  if (dir_created || fileinfo.st_uid != user || fileinfo.st_gid != group)
+  {
+    if (create_dir >= 0)
+      cupsdLogMessage(CUPSD_LOG_DEBUG, "Repairing ownership of \"%s\"",
+                      filename);
+
+    if (chown(filename, user, group) && !getuid())
+    {
+      if (create_dir >= 0)
+       cupsdLogMessage(CUPSD_LOG_ERROR,
+                       "Unable to change ownership of \"%s\" - %s", filename,
+                       strerror(errno));
+      else
+       syslog(LOG_ERR, "Unable to change ownership of \"%s\" - %s", filename,
+              strerror(errno));
+
+      return (1);
+    }
+  }
+
+  if (dir_created || (fileinfo.st_mode & 07777) != mode)
+  {
+    if (create_dir >= 0)
+      cupsdLogMessage(CUPSD_LOG_DEBUG, "Repairing access permissions of \"%s\"",
+                     filename);
+
+    if (chmod(filename, mode))
+    {
+      if (create_dir >= 0)
+       cupsdLogMessage(CUPSD_LOG_ERROR,
+                       "Unable to change permissions of \"%s\" - %s", filename,
+                       strerror(errno));
+      else
+       syslog(LOG_ERR, "Unable to change permissions of \"%s\" - %s", filename,
+              strerror(errno));
+
+      return (1);
+    }
+  }
+
+ /*
+  * Everything is OK...
+  */
+
+  return (0);
+}
+
+
 /*
  * 'cupsdReadConfiguration()' - Read the cupsd.conf file.
  */
@@ -243,6 +369,7 @@ cupsdReadConfiguration(void)
   if (NumBrowsers > 0)
   {
     free(Browsers);
+    Browsers = NULL;
 
     NumBrowsers = 0;
   }
@@ -281,12 +408,20 @@ cupsdReadConfiguration(void)
   cupsdSetString(&AccessLog, CUPS_LOGDIR "/access_log");
   cupsdSetString(&ErrorLog, CUPS_LOGDIR "/error_log");
   cupsdSetString(&PageLog, CUPS_LOGDIR "/page_log");
-  cupsdSetString(&Printcap, "/etc/printcap");
+  cupsdSetString(&Printcap, CUPS_DEFAULT_PRINTCAP);
   cupsdSetString(&PrintcapGUI, "/usr/bin/glpoptions");
   cupsdSetString(&FontPath, CUPS_FONTPATH);
   cupsdSetString(&RemoteRoot, "remroot");
   cupsdSetString(&ServerHeader, "CUPS/1.2");
   cupsdSetString(&StateDir, CUPS_STATEDIR);
+#ifdef HAVE_GSSAPI
+  cupsdSetString(&GSSServiceName, CUPS_DEFAULT_GSSSERVICENAME);
+#endif /* HAVE_GSSAPI */
+
+  if (!strcmp(CUPS_DEFAULT_PRINTCAP, "/etc/printers.conf"))
+    PrintcapFormat = PRINTCAP_SOLARIS;
+  else
+    PrintcapFormat = PRINTCAP_BSD;
 
   strlcpy(temp, ConfigurationFile, sizeof(temp));
   if ((slash = strrchr(temp, '/')) != NULL)
@@ -414,11 +549,14 @@ cupsdReadConfiguration(void)
   cupsdClearString(&BrowseLocalOptions);
   cupsdClearString(&BrowseRemoteOptions);
 
+  cupsdSetString(&ErrorPolicy, "stop-printer");
+
 #ifdef HAVE_LDAP
   cupsdClearString(&BrowseLDAPBindDN);
   cupsdClearString(&BrowseLDAPDN);
   cupsdClearString(&BrowseLDAPPassword);
   cupsdClearString(&BrowseLDAPServer);
+  cupsdClearString(&BrowseLDAPCACertFile);
 #endif /* HAVE_LDAP */
 
   JobHistory          = DEFAULT_HISTORY;
@@ -428,11 +566,15 @@ cupsdReadConfiguration(void)
   MaxActiveJobs       = 0;
   MaxJobsPerUser      = 0;
   MaxJobsPerPrinter   = 0;
-  MaxCopies           = 100;
+  MaxCopies           = CUPS_DEFAULT_MAX_COPIES;
 
   cupsdDeleteAllPolicies();
   cupsdClearString(&DefaultPolicy);
 
+#ifdef HAVE_AUTHORIZATION_H
+  cupsdClearString(&SystemGroupAuthKey);
+#endif /* HAVE_AUTHORIZATION_H */
+
   MaxSubscriptions           = 100;
   MaxSubscriptionsPerJob     = 0;
   MaxSubscriptionsPerPrinter = 0;
@@ -445,6 +587,10 @@ cupsdReadConfiguration(void)
   cupsdSetString(&LaunchdConf, CUPS_DEFAULT_LAUNCHD_CONF);
 #endif /* HAVE_LAUNCHD */
 
+#ifdef __APPLE__
+  AppleQuotas = TRUE;
+#endif  /* __APPLE__ */
+
  /*
   * Read the configuration file...
   */
@@ -461,6 +607,14 @@ cupsdReadConfiguration(void)
 
   RunUser = getuid();
 
+ /*
+  * See if the ServerName is an IP address...
+  */
+
+  for (slash = ServerName; isdigit(*slash & 255) || *slash == '.'; slash ++);
+
+  ServerNameIsIP = !*slash;
+
  /*
   * Use the default system group if none was supplied in cupsd.conf...
   */
@@ -622,21 +776,29 @@ cupsdReadConfiguration(void)
   * writable by the user and group in the cupsd.conf file...
   */
 
-  check_permissions(CacheDir, NULL, 0775, RunUser, Group, 1, 1);
-/*  check_permissions(CacheDir, "ppd", 0755, RunUser, Group, 1, 1);*/
-
-  check_permissions(StateDir, NULL, 0755, RunUser, Group, 1, 1);
-  check_permissions(StateDir, "certs", RunUser ? 0711 : 0511, User,
-                    SystemGroupIDs[0], 1, 1);
-
-  check_permissions(ServerRoot, NULL, 0755, RunUser, Group, 1, 0);
-  check_permissions(ServerRoot, "ppd", 0755, RunUser, Group, 1, 1);
-  check_permissions(ServerRoot, "ssl", 0700, RunUser, Group, 1, 0);
-  check_permissions(ServerRoot, "cupsd.conf", ConfigFilePerm, RunUser, Group,
-                    0, 0);
-  check_permissions(ServerRoot, "classes.conf", 0600, RunUser, Group, 0, 0);
-  check_permissions(ServerRoot, "printers.conf", 0600, RunUser, Group, 0, 0);
-  check_permissions(ServerRoot, "passwd.md5", 0600, User, Group, 0, 0);
+  if (cupsdCheckPermissions(RequestRoot, NULL, 0710, RunUser,
+                           Group, 1, 1) < 0 ||
+      cupsdCheckPermissions(CacheDir, NULL, 0775, RunUser,
+                           Group, 1, 1) < 0 ||
+      cupsdCheckPermissions(StateDir, NULL, 0755, RunUser,
+                           Group, 1, 1) < 0 ||
+      cupsdCheckPermissions(StateDir, "certs", RunUser ? 0711 : 0511, User,
+                           SystemGroupIDs[0], 1, 1) < 0 ||
+      cupsdCheckPermissions(ServerRoot, NULL, 0755, RunUser, 
+                           Group, 1, 0) < 0 ||
+      cupsdCheckPermissions(ServerRoot, "ppd", 0755, RunUser,
+                           Group, 1, 1) < 0 ||
+      cupsdCheckPermissions(ServerRoot, "ssl", 0700, RunUser,
+                           Group, 1, 0) < 0 ||
+      cupsdCheckPermissions(ServerRoot, "cupsd.conf", ConfigFilePerm, RunUser,
+                           Group, 0, 0) < 0 ||
+      cupsdCheckPermissions(ServerRoot, "classes.conf", 0600, RunUser,
+                           Group, 0, 0) < 0 ||
+      cupsdCheckPermissions(ServerRoot, "printers.conf", 0600, RunUser,
+                           Group, 0, 0) < 0 ||
+      cupsdCheckPermissions(ServerRoot, "passwd.md5", 0600, User,
+                           Group, 0, 0) < 0)
+    return (0);
 
  /*
   * Update TempDir to the default if it hasn't been set already...
@@ -663,23 +825,20 @@ cupsdReadConfiguration(void)
                        "TMPDIR (%s) has the wrong permissions!", tmpdir);
       else
         cupsdSetString(&TempDir, tmpdir);
-
-      if (!TempDir)
-        cupsdLogMessage(CUPSD_LOG_INFO, "Using default TempDir of %s/tmp...",
-                       RequestRoot);
     }
 
     if (!TempDir)
+    {
+      cupsdLogMessage(CUPSD_LOG_INFO, "Using default TempDir of %s/tmp...",
+                     RequestRoot);
       cupsdSetStringf(&TempDir, "%s/tmp", RequestRoot);
+    }
   }
 
  /*
-  * Make sure the request and temporary directories have the right
-  * permissions...
+  * Make sure the temporary directory has the right permissions...
   */
 
-  check_permissions(RequestRoot, NULL, 0710, RunUser, Group, 1, 1);
-
   if (!strncmp(TempDir, RequestRoot, strlen(RequestRoot)) ||
       access(TempDir, 0))
   {
@@ -688,7 +847,8 @@ cupsdReadConfiguration(void)
     * is under the spool directory or does not exist...
     */
 
-    check_permissions(TempDir, NULL, 01770, RunUser, Group, 1, 1);
+    if (cupsdCheckPermissions(TempDir, NULL, 01770, RunUser, Group, 1, 1) < 0)
+      return (0);
   }
 
   if (!strncmp(TempDir, RequestRoot, strlen(RequestRoot)))
@@ -758,7 +918,7 @@ cupsdReadConfiguration(void)
   if (MaxActiveJobs > (MaxFDs / 3))
     MaxActiveJobs = MaxFDs / 3;
 
-  if (Classification && strcasecmp(Classification, "none") == 0)
+  if (Classification && !strcasecmp(Classification, "none"))
     cupsdClearString(&Classification);
 
   if (Classification)
@@ -778,6 +938,24 @@ cupsdReadConfiguration(void)
                   "Allowing up to %d client connections per host.",
                   MaxClientsPerHost);
 
+ /*
+  * Make sure that BrowseTimeout is at least twice the interval...
+  */
+
+  if (BrowseTimeout < (2 * BrowseInterval) || BrowseTimeout <= 0)
+  {
+    cupsdLogMessage(CUPSD_LOG_ALERT, "Invalid BrowseTimeout value %d!",
+                    BrowseTimeout);
+
+    if (BrowseInterval)
+      BrowseTimeout = BrowseInterval * 2;
+    else
+      BrowseTimeout = DEFAULT_TIMEOUT;
+
+    cupsdLogMessage(CUPSD_LOG_ALERT, "Reset BrowseTimeout to %d!",
+                    BrowseTimeout);
+  }
+
  /*
   * Update the default policy, as needed...
   */
@@ -859,11 +1037,11 @@ cupsdReadConfiguration(void)
                      "CUPS-Delete-Printer CUPS-Add-Class CUPS-Delete-Class "
                      "CUPS-Accept-Jobs CUPS-Reject-Jobs CUPS-Set-Default>");
       cupsdLogMessage(CUPSD_LOG_INFO, "Order Deny,Allow");
-      cupsdLogMessage(CUPSD_LOG_INFO, "AuthType Basic");
+      cupsdLogMessage(CUPSD_LOG_INFO, "AuthType Default");
 
       po = cupsdAddPolicyOp(p, NULL, IPP_PAUSE_PRINTER);
       po->order_type = AUTH_ALLOW;
-      po->type       = AUTH_BASIC;
+      po->type       = DefaultAuthType;
       po->level      = AUTH_USER;
 
       cupsdAddName(po, "@SYSTEM");
@@ -1076,113 +1254,6 @@ cupsdReadConfiguration(void)
 }
 
 
-/*
- * 'check_permissions()' - Fix the mode and ownership of a file or directory.
- */
-
-static int                             /* O - 0 on success, -1 on error */
-check_permissions(const char *filename,        /* I - File/directory name */
-                  const char *suffix,  /* I - Additional file/directory name */
-                  int        mode,     /* I - Permissions */
-                 int        user,      /* I - Owner */
-                 int        group,     /* I - Group */
-                 int        is_dir,    /* I - 1 = directory, 0 = file */
-                 int        create_dir)/* I - 1 = create directory, 0 = not */
-{
-  int          dir_created = 0;        /* Did we create a directory? */
-  char         pathname[1024];         /* File name with prefix */
-  struct stat  fileinfo;               /* Stat buffer */
-
-
- /*
-  * Prepend the given root to the filename before testing it...
-  */
-
-  if (suffix)
-  {
-    snprintf(pathname, sizeof(pathname), "%s/%s", filename, suffix);
-    filename = pathname;
-  }
-
- /*
-  * See if we can stat the file/directory...
-  */
-
-  if (stat(filename, &fileinfo))
-  {
-    if (errno == ENOENT && create_dir)
-    {
-      cupsdLogMessage(CUPSD_LOG_ERROR, "Creating missing directory \"%s\"",
-                      filename);
-
-      if (mkdir(filename, mode))
-      {
-        cupsdLogMessage(CUPSD_LOG_ERROR,
-                       "Unable to create directory \"%s\" - %s", filename,
-                       strerror(errno));
-        return (-1);
-      }
-
-      dir_created = 1;
-    }
-    else
-      return (-1);
-  }
-
- /*
-  * Make sure it's a regular file...
-  */
-
-  if (!dir_created && !is_dir && !S_ISREG(fileinfo.st_mode))
-  {
-    cupsdLogMessage(CUPSD_LOG_ERROR, "\"%s\" is not a regular file!", filename);
-    return (-1);
-  }
-
-  if (!dir_created && is_dir && !S_ISDIR(fileinfo.st_mode))
-  {
-    cupsdLogMessage(CUPSD_LOG_ERROR, "\"%s\" is not a directory!", filename);
-    return (-1);
-  }
-
- /*
-  * Fix owner, group, and mode as needed...
-  */
-
-  if (dir_created || fileinfo.st_uid != user || fileinfo.st_gid != group)
-  {
-    cupsdLogMessage(CUPSD_LOG_WARN, "Repairing ownership of \"%s\"", filename);
-
-    if (chown(filename, user, group))
-    {
-      cupsdLogMessage(CUPSD_LOG_ERROR,
-                      "Unable to change ownership of \"%s\" - %s", filename,
-                     strerror(errno));
-      return (-1);
-    }
-  }
-
-  if (dir_created || (fileinfo.st_mode & 07777) != mode)
-  {
-    cupsdLogMessage(CUPSD_LOG_WARN, "Repairing access permissions of \"%s\"", filename);
-
-    if (chmod(filename, mode))
-    {
-      cupsdLogMessage(CUPSD_LOG_ERROR,
-                      "Unable to change permissions of \"%s\" - %s", filename,
-                     strerror(errno));
-      return (-1);
-    }
-  }
-
- /*
-  * Everything is OK...
-  */
-
-  return (0);
-}
-
-
 /*
  * 'get_address()' - Get an address + port number from a line.
  */
@@ -1276,33 +1347,14 @@ get_addr_and_mask(const char *value,    /* I - String from config file */
   const char   *maskval,               /* Pointer to start of mask value */
                *ptr,                   /* Pointer into value */
                *ptr2;                  /* ... */
-  static unsigned netmasks[4][4] =     /* Standard IPv4 netmasks... */
-  {
-    { 0xffffffff, 0xffffffff, 0xffffffff, 0xff000000 },
-    { 0xffffffff, 0xffffffff, 0xffffffff, 0xffff0000 },
-    { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffff00 },
-    { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff }
-  };
-#ifdef AF_INET6
-  static unsigned netmasks6[8][4] =    /* Standard IPv6 netmasks... */
-  {
-    { 0xffff0000, 0x00000000, 0x00000000, 0x00000000 },
-    { 0xffffffff, 0x00000000, 0x00000000, 0x00000000 },
-    { 0xffffffff, 0xffff0000, 0x00000000, 0x00000000 },
-    { 0xffffffff, 0xffffffff, 0x00000000, 0x00000000 },
-    { 0xffffffff, 0xffffffff, 0xffff0000, 0x00000000 },
-    { 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000 },
-    { 0xffffffff, 0xffffffff, 0xffffffff, 0xffff0000 },
-    { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff }
-  };
-#endif /* AF_INET6 */
 
 
  /*
   * Get the address...
   */
 
-  memset(ip, 0, sizeof(unsigned) * 4);
+  ip[0]   = ip[1]   = ip[2]   = ip[3]   = 0x00000000;
+  mask[0] = mask[1] = mask[2] = mask[3] = 0xffffffff;
 
   if ((maskval = strchr(value, '/')) != NULL)
     maskval ++;
@@ -1333,6 +1385,7 @@ get_addr_and_mask(const char *value,      /* I - String from config file */
             ptr2 = strchr(ptr2 + 1, ':'), j ++);
 
         i = 7 - j;
+       ptr ++;
       }
       else if (isxdigit(*ptr & 255))
       {
@@ -1342,9 +1395,9 @@ get_addr_and_mask(const char *value,      /* I - String from config file */
          return (0);
 
         if (i & 1)
-          ip[i] |= ipval;
+          ip[i / 2] |= ipval;
        else
-          ip[i] |= ipval << 16;
+          ip[i / 2] |= ipval << 16;
       }
       else
         return (0);
@@ -1353,7 +1406,10 @@ get_addr_and_mask(const char *value,     /* I - String from config file */
         ptr ++;
     }
 
-    ipcount = i;
+    if (*ptr != ']')
+      return (0);
+
+    ptr ++;
 
     if (*ptr && *ptr != '/')
       return (0);
@@ -1365,70 +1421,55 @@ get_addr_and_mask(const char *value,    /* I - String from config file */
     * Parse dotted-decimal IPv4 address...
     */
 
-    family  = AF_INET;
-    ipcount = sscanf(value, "%u.%u.%u.%u", ip + 0, ip + 1, ip + 2, ip + 3);
+    unsigned val[4];                   /* IPv4 address values */
 
-    ip[3] |= ((((ip[0] << 8) | ip[1]) << 8) | ip[2]) << 8;
-    ip[0] = ip[1] = ip[2] = 0;
-  }
 
-  if (*maskval)
-  {
+    family  = AF_INET;
+    ipcount = sscanf(value, "%u.%u.%u.%u", val + 0, val + 1, val + 2, val + 3);
+
    /*
-    * Get the netmask value(s)...
+    * Range check the IP numbers...
     */
 
-    memset(mask, 0, sizeof(unsigned) * 4);
+    for (i = 0; i < ipcount; i ++)
+      if (val[i] > 255)
+        return (0);
 
-#ifdef AF_INET6
-    if (*maskval == '[')
-    {
-     /*
-      * Get hexadecimal mask value...
-      */
+   /*
+    * Make sure the trailing values are zeroed, as some C libraries like
+    * glibc apparently like to fill the unused arguments with garbage...
+    */
 
-      for (i = 0, ptr = maskval + 1; *ptr && i < 8; i ++)
-      {
-       if (*ptr == ']')
-         break;
-       else if (!strncmp(ptr, "::", 2))
-       {
-          for (ptr2 = strchr(ptr + 2, ':'), j = 0;
-              ptr2;
-              ptr2 = strchr(ptr2 + 1, ':'), j ++);
+    for (i = ipcount; i < 4; i ++)
+      val[i] = 0;
 
-          i = 7 - j;
-       }
-       else if (isxdigit(*ptr & 255))
-       {
-          ipval = strtoul(ptr, (char **)&ptr, 16);
+   /*
+    * Merge everything into a 32-bit IPv4 address in ip[3]...
+    */
 
-         if (ipval > 0xffff)
-           return (0);
+    ip[3] = (((((val[0] << 8) | val[1]) << 8) | val[2]) << 8) | val[3];
 
-          if (i & 1)
-            mask[i] |= ipval;
-         else
-            mask[i] |= ipval << 16;
-       }
-       else
-          return (0);
+    if (ipcount < 4)
+      mask[3] = (0xffffffff << (32 - 8 * ipcount)) & 0xffffffff;
+  }
 
-        while (*ptr == ':')
-          ptr ++;
-      }
+  if (*maskval)
+  {
+   /*
+    * Get the netmask value(s)...
+    */
+
+    memset(mask, 0, sizeof(unsigned) * 4);
 
-      if (*ptr)
-       return (0);
-    }
-    else
-#endif /* AF_INET6 */
     if (strchr(maskval, '.'))
     {
      /*
       * Get dotted-decimal mask...
       */
 
+      if (family != AF_INET)
+        return (0);
+
       if (sscanf(maskval, "%u.%u.%u.%u", mask + 0, mask + 1, mask + 2, mask + 3) != 4)
         return (0);
 
@@ -1446,6 +1487,9 @@ get_addr_and_mask(const char *value,      /* I - String from config file */
 #ifdef AF_INET6
       if (family == AF_INET6)
       {
+        if (i > 128)
+         return (0);
+
         i = 128 - i;
 
        if (i <= 96)
@@ -1477,29 +1521,24 @@ get_addr_and_mask(const char *value,    /* I - String from config file */
       else
 #endif /* AF_INET6 */
       {
-        i = 32 - i;
+        if (i > 32)
+         return (0);
 
         mask[0] = 0xffffffff;
         mask[1] = 0xffffffff;
         mask[2] = 0xffffffff;
 
-       if (i > 0)
-          mask[3] = (0xffffffff << i) & 0xffffffff;
+       if (i < 32)
+          mask[3] = (0xffffffff << (32 - i)) & 0xffffffff;
        else
          mask[3] = 0xffffffff;
       }
     }
   }
-#ifdef AF_INET6
-  else if (family == AF_INET6)
-    memcpy(mask, netmasks6[ipcount - 1], sizeof(unsigned) * 4);
-#endif /* AF_INET6 */
-  else
-    memcpy(mask, netmasks[ipcount - 1], sizeof(unsigned) * 4);
 
   cupsdLogMessage(CUPSD_LOG_DEBUG2,
                   "get_addr_and_mask(value=\"%s\", "
-                  "ip=[%08x:%08x:%08x:%08x], mask=[%08x:%08x:%08x:%08x]",
+                  "ip=[%08x:%08x:%08x:%08x], mask=[%08x:%08x:%08x:%08x])",
              value, ip[0], ip[1], ip[2], ip[3], mask[0], mask[1], mask[2],
             mask[3]);
 
@@ -1633,7 +1672,12 @@ parse_aaa(cupsd_location_t *loc, /* I - Location */
       else
        cupsdDenyIP(loc, ones, zeros);
     }
+#ifdef AF_INET6
+    else if (value[0] == '*' || value[0] == '.' || 
+             (!isdigit(value[0] & 255) && value[0] != '['))
+#else
     else if (value[0] == '*' || value[0] == '.' || !isdigit(value[0] & 255))
+#endif /* AF_INET6 */
     {
      /*
       * Host or domain name...
@@ -1669,7 +1713,7 @@ parse_aaa(cupsd_location_t *loc,  /* I - Location */
   else if (!strcasecmp(line, "AuthType"))
   {
    /*
-    * AuthType {none,basic,digest,basicdigest}
+    * AuthType {none,basic,digest,basicdigest,negotiate,default}
     */
 
     if (!strcasecmp(value, "none"))
@@ -1698,6 +1742,22 @@ parse_aaa(cupsd_location_t *loc, /* I - Location */
       if (loc->level == AUTH_ANON)
        loc->level = AUTH_USER;
     }
+    else if (!strcasecmp(value, "default"))
+    {
+      loc->type = DefaultAuthType;
+
+      if (loc->level == AUTH_ANON)
+       loc->level = AUTH_USER;
+    }
+#ifdef HAVE_GSSAPI
+    else if (!strcasecmp(value, "negotiate"))
+    {
+      loc->type = AUTH_NEGOTIATE;
+
+      if (loc->level == AUTH_ANON)
+       loc->level = AUTH_USER;
+    }
+#endif /* HAVE_GSSAPI */
     else
     {
       cupsdLogMessage(CUPSD_LOG_WARN,
@@ -1737,7 +1797,7 @@ parse_aaa(cupsd_location_t *loc,  /* I - Location */
 
       cupsdLogMessage(CUPSD_LOG_WARN,
                       "\"AuthClass %s\" is deprecated; consider using "
-                     "\"Require @groupname\" on line %d.",
+                     "\"Require user @groupname\" on line %d.",
                      value, linenum);
     }
     else if (!strcasecmp(value, "system"))
@@ -1748,7 +1808,7 @@ parse_aaa(cupsd_location_t *loc,  /* I - Location */
 
       cupsdLogMessage(CUPSD_LOG_WARN,
                       "\"AuthClass %s\" is deprecated; consider using "
-                     "\"Require @SYSTEM\" on line %d.",
+                     "\"Require user @SYSTEM\" on line %d.",
                      value, linenum);
     }
     else
@@ -1765,7 +1825,7 @@ parse_aaa(cupsd_location_t *loc,  /* I - Location */
 
     cupsdLogMessage(CUPSD_LOG_WARN,
                     "\"AuthGroupName %s\" directive is deprecated; consider "
-                   "using \"Require @%s\" on line %d.",
+                   "using \"Require user @%s\" on line %d.",
                    value, value, linenum);
   }
   else if (!strcasecmp(line, "Require"))
@@ -1806,6 +1866,20 @@ parse_aaa(cupsd_location_t *loc, /* I - Location */
       while (isspace(*value & 255))
        value ++;
 
+#ifdef HAVE_AUTHORIZATION_H
+      if (!strncmp(value, "@AUTHKEY(", 9))
+      {
+       /*
+       * Grab "@AUTHKEY(name)" value...
+       */
+
+        for (valptr = value + 9; *valptr != ')' && *valptr; valptr ++);
+
+       if (*valptr)
+         *valptr++ = '\0';
+      }
+      else
+#endif /* HAVE_AUTHORIZATION_H */
       if (*value == '\"' || *value == '\'')
       {
        /*
@@ -1941,6 +2015,13 @@ parse_protocols(const char *s)           /* I - Space-delimited protocols */
        *valend;                        /* End of value */
 
 
+ /*
+  * Empty protocol line yields NULL pointer...
+  */
+
+  if (!s)
+    return (0);
+
  /*
   * Loop through the value string,...
   */
@@ -1976,7 +2057,7 @@ parse_protocols(const char *s)            /* I - Space-delimited protocols */
       protocols |= BROWSE_DNSSD;
     else if (!strcasecmp(valstart, "all"))
       protocols |= BROWSE_ALL;
-    else
+    else if (strcasecmp(valstart, "none"))
       return (-1);
 
     for (valstart = valend; *valstart; valstart ++)
@@ -2405,7 +2486,12 @@ read_configuration(cups_file_t *fp)      /* I - File to read from */
          else
            cupsdDenyIP(location, ones, zeros);
        }
-       else if (value[0] == '*' || value[0] == '.' || !isdigit(value[0]))
+#ifdef AF_INET6
+       else if (value[0] == '*' || value[0] == '.' || 
+                (!isdigit(value[0] & 255) && value[0] != '['))
+#else
+       else if (value[0] == '*' || value[0] == '.' || !isdigit(value[0] & 255))
+#endif /* AF_INET6 */
        {
         /*
           * Host or domain name...
@@ -2489,7 +2575,12 @@ read_configuration(cups_file_t *fp)      /* I - File to read from */
       *    nnn.nnn.nnn.nnn/mmm.mmm.mmm.mmm
       */
 
-      if (value[0] == '*' || value[0] == '.' || !isdigit(value[0]))
+#ifdef AF_INET6
+      if (value[0] == '*' || value[0] == '.' || 
+          (!isdigit(value[0] & 255) && value[0] != '['))
+#else
+      if (value[0] == '*' || value[0] == '.' || !isdigit(value[0] & 255))
+#endif /* AF_INET6 */
       {
        /*
         * Host or domain name...
@@ -2571,19 +2662,19 @@ read_configuration(cups_file_t *fp)     /* I - File to read from */
   
          if (relay->from.type == AUTH_IP)
            snprintf(temp2, sizeof(temp2), "%u.%u.%u.%u/%u.%u.%u.%u",
-                    relay->from.mask.ip.address[0],
-                    relay->from.mask.ip.address[1],
-                    relay->from.mask.ip.address[2],
-                    relay->from.mask.ip.address[3],
-                    relay->from.mask.ip.netmask[0],
-                    relay->from.mask.ip.netmask[1],
-                    relay->from.mask.ip.netmask[2],
-                    relay->from.mask.ip.netmask[3]);
+                    relay->from.mask.ip.address[0] >> 24,
+                    (relay->from.mask.ip.address[0] >> 16) & 255,
+                    (relay->from.mask.ip.address[0] >> 8) & 255,
+                    relay->from.mask.ip.address[0] & 255,
+                    relay->from.mask.ip.netmask[0] >> 24,
+                    (relay->from.mask.ip.netmask[0] >> 16) & 255,
+                    (relay->from.mask.ip.netmask[0] >> 8) & 255,
+                    relay->from.mask.ip.netmask[0] & 255);
          else
            strlcpy(temp2, relay->from.mask.name.name, sizeof(temp2));
   
          cupsdLogMessage(CUPSD_LOG_INFO, "Relaying from %s to %s:%d (IPv4)",
-                         temp, temp2, ntohs(relay->to.ipv4.sin_port));
+                         temp2, temp, ntohs(relay->to.ipv4.sin_port));
   
          NumRelays ++;
        }
@@ -2667,7 +2758,7 @@ read_configuration(cups_file_t *fp)       /* I - File to read from */
     else if (!strcasecmp(line, "DefaultAuthType"))
     {
      /*
-      * DefaultAuthType {basic,digest,basicdigest}
+      * DefaultAuthType {basic,digest,basicdigest,negotiate}
       */
 
       if (!strcasecmp(value, "basic"))
@@ -2676,6 +2767,10 @@ read_configuration(cups_file_t *fp)      /* I - File to read from */
        DefaultAuthType = AUTH_DIGEST;
       else if (!strcasecmp(value, "basicdigest"))
        DefaultAuthType = AUTH_BASICDIGEST;
+#ifdef HAVE_GSSAPI
+      else if (!strcasecmp(value, "negotiate"))
+        DefaultAuthType = AUTH_NEGOTIATE;
+#endif /* HAVE_GSSAPI */
       else
       {
        cupsdLogMessage(CUPSD_LOG_WARN,
@@ -2706,6 +2801,19 @@ read_configuration(cups_file_t *fp)      /* I - File to read from */
       }
     }
 #endif /* HAVE_SSL */
+#ifdef HAVE_GSSAPI
+    else if (!strcasecmp(line, "Krb5Keytab"))
+    {
+      cupsdSetStringf(&Krb5Keytab, "KRB5_KTNAME=%s", value);
+      putenv(Krb5Keytab);
+
+#  ifdef HAVE_GSSKRB5_REGISTER_ACCEPTOR_IDENTITY
+      gsskrb5_register_acceptor_identity(value);
+#  else
+      cupsdSetEnv("KRB5_KTNAME", value);
+#  endif /* HAVE_GSSKRB5_REGISTER_ACCEPTOR_IDENTITY */
+    }
+#endif /* HAVE_GSSAPI */
     else if (!strcasecmp(line, "User"))
     {
      /*
@@ -2948,6 +3056,11 @@ read_configuration(cups_file_t *fp)      /* I - File to read from */
       switch (var->type)
       {
         case CUPSD_VARTYPE_INTEGER :
+           if (!value)
+             cupsdLogMessage(CUPSD_LOG_ERROR,
+                             "Missing integer value for %s on line %d!",
+                             line, linenum);
+           else
            {
              int       n;              /* Number */
              char      *units;         /* Units */
@@ -2967,16 +3080,25 @@ read_configuration(cups_file_t *fp)     /* I - File to read from */
                  n *= 262144;
              }
 
-             *((int *)var->ptr) = n;
+              if (n < 0)
+               cupsdLogMessage(CUPSD_LOG_ERROR,
+                               "Bad negative integer value for %s on line %d!",
+                               line, linenum);
+             else
+               *((int *)var->ptr) = n;
            }
            break;
 
        case CUPSD_VARTYPE_BOOLEAN :
-           if (!strcasecmp(value, "true") ||
-               !strcasecmp(value, "on") ||
-               !strcasecmp(value, "enabled") ||
-               !strcasecmp(value, "yes") ||
-               atoi(value) != 0)
+           if (!value)
+             cupsdLogMessage(CUPSD_LOG_ERROR,
+                             "Missing boolean value for %s on line %d!",
+                             line, linenum);
+            else if (!strcasecmp(value, "true") ||
+                    !strcasecmp(value, "on") ||
+                    !strcasecmp(value, "enabled") ||
+                    !strcasecmp(value, "yes") ||
+                    atoi(value) != 0)
               *((int *)var->ptr) = TRUE;
            else if (!strcasecmp(value, "false") ||
                     !strcasecmp(value, "off") ||
@@ -3251,5 +3373,5 @@ read_policy(cups_file_t *fp,              /* I - Configuration file */
 
 
 /*
- * End of "$Id: conf.c 5353 2006-03-29 20:31:58Z mike $".
+ * End of "$Id: conf.c 6649 2007-07-11 21:46:42Z mike $".
  */