X-Git-Url: http://git.ipfire.org/?p=thirdparty%2Fcups.git;a=blobdiff_plain;f=scheduler%2Fconf.c;h=3cde8bd2989e527642003a32c41e85294f5a9040;hp=9b48da5032b4d200c2e9a99cd50d74058b4d7225;hb=57b7b66b58a66426494ec13ffb18f730afeab8b5;hpb=3dd9c340583c44d4dcb7223efbd0a815e0027ff7 diff --git a/scheduler/conf.c b/scheduler/conf.c index 9b48da503..3cde8bd29 100644 --- a/scheduler/conf.c +++ b/scheduler/conf.c @@ -1,37 +1,14 @@ /* - * "$Id: conf.c 9352 2010-11-06 04:55:26Z mike $" + * Configuration routines for the CUPS scheduler. * - * Configuration routines for the CUPS scheduler. + * Copyright 2007-2016 by Apple Inc. + * Copyright 1997-2007 by Easy Software Products, all rights reserved. * - * Copyright 2007-2012 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/". - * - * Contents: - * - * cupsdAddAlias() - Add a host alias. - * cupsdCheckPermissions() - Fix the mode and ownership of a file or - * directory. - * cupsdDefaultAuthType() - Get the default AuthType. - * cupsdFreeAliases() - Free all of the alias entries. - * 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. - * mime_error_cb() - Log a MIME error. - * parse_aaa() - Parse authentication, authorization, and access - * control lines. - * parse_fatal_errors() - Parse FatalErrors values in a string. - * parse_groups() - Parse system group names in a string. - * parse_protocols() - Parse browse protocols in a string. - * read_configuration() - Read a configuration file. - * read_location() - Read a definition. - * read_policy() - Read a definition. - * set_policy_defaults() - Set default policy values as needed. + * 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 + * missing or damaged, see the license at "http://www.cups.org/". */ /* @@ -42,6 +19,12 @@ #include #include #include +#ifdef HAVE_ASL_H +# include +#elif defined(HAVE_SYSTEMD_SD_JOURNAL_H) +# define SD_JOURNAL_SUPPRESS_LOCATION +# include +#endif /* HAVE_ASL_H */ #include #ifdef HAVE_LIBPAPER @@ -68,7 +51,8 @@ typedef enum CUPSD_VARTYPE_TIME, /* Time interval option */ CUPSD_VARTYPE_STRING, /* String option */ CUPSD_VARTYPE_BOOLEAN, /* Boolean option */ - CUPSD_VARTYPE_PATHNAME /* File/directory name option */ + CUPSD_VARTYPE_PATHNAME, /* File/directory name option */ + CUPSD_VARTYPE_PERM /* File/directory permissions */ } cupsd_vartype_t; typedef struct @@ -83,51 +67,42 @@ typedef struct * Local globals... */ -static int default_auth_type = CUPSD_AUTH_AUTO; - /* Default AuthType, if not specified */ -static const cupsd_var_t variables[] = +static const cupsd_var_t cupsd_vars[] = { - { "AccessLog", &AccessLog, CUPSD_VARTYPE_STRING }, { "AutoPurgeJobs", &JobAutoPurge, CUPSD_VARTYPE_BOOLEAN }, #if defined(HAVE_DNSSD) || defined(HAVE_AVAHI) { "BrowseDNSSDSubTypes", &DNSSDSubTypes, CUPSD_VARTYPE_STRING }, #endif /* HAVE_DNSSD || HAVE_AVAHI */ { "BrowseWebIF", &BrowseWebIF, CUPSD_VARTYPE_BOOLEAN }, { "Browsing", &Browsing, CUPSD_VARTYPE_BOOLEAN }, - { "CacheDir", &CacheDir, CUPSD_VARTYPE_STRING }, { "Classification", &Classification, CUPSD_VARTYPE_STRING }, { "ClassifyOverride", &ClassifyOverride, CUPSD_VARTYPE_BOOLEAN }, - { "ConfigFilePerm", &ConfigFilePerm, CUPSD_VARTYPE_INTEGER }, - { "DataDir", &DataDir, CUPSD_VARTYPE_STRING }, { "DefaultLanguage", &DefaultLanguage, CUPSD_VARTYPE_STRING }, { "DefaultLeaseDuration", &DefaultLeaseDuration, CUPSD_VARTYPE_TIME }, { "DefaultPaperSize", &DefaultPaperSize, CUPSD_VARTYPE_STRING }, { "DefaultPolicy", &DefaultPolicy, CUPSD_VARTYPE_STRING }, { "DefaultShared", &DefaultShared, CUPSD_VARTYPE_BOOLEAN }, { "DirtyCleanInterval", &DirtyCleanInterval, CUPSD_VARTYPE_TIME }, - { "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 }, #ifdef HAVE_GSSAPI { "GSSServiceName", &GSSServiceName, CUPSD_VARTYPE_STRING }, #endif /* HAVE_GSSAPI */ +#ifdef HAVE_ONDEMAND + { "IdleExitTimeout", &IdleExitTimeout, CUPSD_VARTYPE_TIME }, +#endif /* HAVE_ONDEMAND */ { "JobKillDelay", &JobKillDelay, CUPSD_VARTYPE_TIME }, { "JobRetryLimit", &JobRetryLimit, CUPSD_VARTYPE_INTEGER }, { "JobRetryInterval", &JobRetryInterval, CUPSD_VARTYPE_TIME }, { "KeepAliveTimeout", &KeepAliveTimeout, CUPSD_VARTYPE_TIME }, { "KeepAlive", &KeepAlive, CUPSD_VARTYPE_BOOLEAN }, #ifdef HAVE_LAUNCHD - { "LaunchdTimeout", &LaunchdTimeout, CUPSD_VARTYPE_TIME }, + { "LaunchdTimeout", &IdleExitTimeout, CUPSD_VARTYPE_TIME }, #endif /* HAVE_LAUNCHD */ { "LimitRequestBody", &MaxRequestSize, CUPSD_VARTYPE_INTEGER }, { "ListenBackLog", &ListenBackLog, CUPSD_VARTYPE_INTEGER }, { "LogDebugHistory", &LogDebugHistory, CUPSD_VARTYPE_INTEGER }, - { "LogFilePerm", &LogFilePerm, CUPSD_VARTYPE_INTEGER }, - { "LPDConfigFile", &LPDConfigFile, CUPSD_VARTYPE_STRING }, { "MaxActiveJobs", &MaxActiveJobs, CUPSD_VARTYPE_INTEGER }, { "MaxClients", &MaxClients, CUPSD_VARTYPE_INTEGER }, { "MaxClientsPerHost", &MaxClientsPerHost, CUPSD_VARTYPE_INTEGER }, @@ -137,7 +112,7 @@ static const cupsd_var_t variables[] = { "MaxJobs", &MaxJobs, CUPSD_VARTYPE_INTEGER }, { "MaxJobsPerPrinter", &MaxJobsPerPrinter, CUPSD_VARTYPE_INTEGER }, { "MaxJobsPerUser", &MaxJobsPerUser, CUPSD_VARTYPE_INTEGER }, - { "MaxJobTime", &MaxJobTime, CUPSD_VARTYPE_INTEGER }, + { "MaxJobTime", &MaxJobTime, CUPSD_VARTYPE_TIME }, { "MaxLeaseDuration", &MaxLeaseDuration, CUPSD_VARTYPE_TIME }, { "MaxLogSize", &MaxLogSize, CUPSD_VARTYPE_INTEGER }, { "MaxRequestSize", &MaxRequestSize, CUPSD_VARTYPE_INTEGER }, @@ -146,38 +121,53 @@ static const cupsd_var_t variables[] = { "MaxSubscriptionsPerPrinter",&MaxSubscriptionsPerPrinter, CUPSD_VARTYPE_INTEGER }, { "MaxSubscriptionsPerUser", &MaxSubscriptionsPerUser, CUPSD_VARTYPE_INTEGER }, { "MultipleOperationTimeout", &MultipleOperationTimeout, CUPSD_VARTYPE_TIME }, - { "PageLog", &PageLog, CUPSD_VARTYPE_STRING }, { "PageLogFormat", &PageLogFormat, CUPSD_VARTYPE_STRING }, { "PreserveJobFiles", &JobFiles, CUPSD_VARTYPE_TIME }, { "PreserveJobHistory", &JobHistory, CUPSD_VARTYPE_TIME }, - { "Printcap", &Printcap, CUPSD_VARTYPE_STRING }, { "ReloadTimeout", &ReloadTimeout, CUPSD_VARTYPE_TIME }, - { "RemoteRoot", &RemoteRoot, CUPSD_VARTYPE_STRING }, - { "RequestRoot", &RequestRoot, CUPSD_VARTYPE_STRING }, { "RIPCache", &RIPCache, CUPSD_VARTYPE_STRING }, { "RootCertDuration", &RootCertDuration, CUPSD_VARTYPE_TIME }, { "ServerAdmin", &ServerAdmin, CUPSD_VARTYPE_STRING }, + { "ServerName", &ServerName, CUPSD_VARTYPE_STRING }, + { "StrictConformance", &StrictConformance, CUPSD_VARTYPE_BOOLEAN }, + { "Timeout", &Timeout, CUPSD_VARTYPE_TIME }, + { "WebInterface", &WebInterface, CUPSD_VARTYPE_BOOLEAN } +}; +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 }, + { "FileDevice", &FileDevice, CUPSD_VARTYPE_BOOLEAN }, + { "FontPath", &FontPath, CUPSD_VARTYPE_STRING }, + { "LogFilePerm", &LogFilePerm, CUPSD_VARTYPE_PERM }, + { "LPDConfigFile", &LPDConfigFile, CUPSD_VARTYPE_STRING }, + { "PageLog", &PageLog, CUPSD_VARTYPE_STRING }, + { "Printcap", &Printcap, CUPSD_VARTYPE_STRING }, + { "RemoteRoot", &RemoteRoot, CUPSD_VARTYPE_STRING }, + { "RequestRoot", &RequestRoot, CUPSD_VARTYPE_STRING }, { "ServerBin", &ServerBin, CUPSD_VARTYPE_PATHNAME }, #ifdef HAVE_SSL - { "ServerCertificate", &ServerCertificate, CUPSD_VARTYPE_PATHNAME }, -# if defined(HAVE_LIBSSL) || defined(HAVE_GNUTLS) - { "ServerKey", &ServerKey, CUPSD_VARTYPE_PATHNAME }, -# endif /* HAVE_LIBSSL || HAVE_GNUTLS */ + { "ServerKeychain", &ServerKeychain, CUPSD_VARTYPE_PATHNAME }, #endif /* HAVE_SSL */ - { "ServerName", &ServerName, CUPSD_VARTYPE_STRING }, { "ServerRoot", &ServerRoot, CUPSD_VARTYPE_PATHNAME }, { "SMBConfigFile", &SMBConfigFile, CUPSD_VARTYPE_STRING }, { "StateDir", &StateDir, CUPSD_VARTYPE_STRING }, - { "StrictConformance", &StrictConformance, CUPSD_VARTYPE_BOOLEAN }, + { "SyncOnClose", &SyncOnClose, CUPSD_VARTYPE_BOOLEAN }, #ifdef HAVE_AUTHORIZATION_H { "SystemGroupAuthKey", &SystemGroupAuthKey, CUPSD_VARTYPE_STRING }, #endif /* HAVE_AUTHORIZATION_H */ - { "TempDir", &TempDir, CUPSD_VARTYPE_PATHNAME }, - { "Timeout", &Timeout, CUPSD_VARTYPE_TIME }, - { "WebInterface", &WebInterface, CUPSD_VARTYPE_BOOLEAN } + { "TempDir", &TempDir, CUPSD_VARTYPE_PATHNAME } }; -#define NUM_VARS (sizeof(variables) / sizeof(variables[0])) +static int default_auth_type = CUPSD_AUTH_AUTO; + /* Default AuthType, if not specified */ static const unsigned ones[4] = { @@ -202,7 +192,12 @@ static int parse_aaa(cupsd_location_t *loc, char *line, static int parse_fatal_errors(const char *s); static int parse_groups(const char *s); static int parse_protocols(const char *s); -static int read_configuration(cups_file_t *fp); +static int parse_variable(const char *filename, int linenum, + const char *line, const char *value, + size_t num_vars, + const cupsd_var_t *vars); +static int read_cupsd_conf(cups_file_t *fp); +static int read_cups_files_conf(cups_file_t *fp); static int read_location(cups_file_t *fp, char *name, int linenum); static int read_policy(cups_file_t *fp, char *name, int linenum); static void set_policy_defaults(cupsd_policy_t *pol); @@ -240,9 +235,9 @@ 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 */ + mode_t mode, /* I - Permissions */ + uid_t user, /* I - Owner */ + gid_t 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 */ { @@ -281,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); } @@ -319,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); } @@ -348,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); } @@ -368,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); } @@ -419,7 +427,7 @@ cupsdDefaultAuthType(void) * to use it... */ - if (gss_init_sec_context == NULL) + if (&gss_init_sec_context == NULL) return (default_auth_type = CUPSD_AUTH_BASIC); # endif /* __APPLE__ */ @@ -581,7 +589,7 @@ cupsdReadConfiguration(void) cupsdSetString(&Printcap, CUPS_DEFAULT_PRINTCAP); cupsdSetString(&FontPath, CUPS_FONTPATH); cupsdSetString(&RemoteRoot, "remroot"); - cupsdSetStringf(&ServerHeader, "CUPS/%d.%d", CUPS_VERSION_MAJOR, + cupsdSetStringf(&ServerHeader, "CUPS/%d.%d IPP/2.1", CUPS_VERSION_MAJOR, CUPS_VERSION_MINOR); cupsdSetString(&StateDir, CUPS_STATEDIR); @@ -603,12 +611,13 @@ cupsdReadConfiguration(void) ClassifyOverride = 0; #ifdef HAVE_SSL -# ifdef HAVE_CDSASSL - cupsdSetString(&ServerCertificate, "/Library/Keychains/System.keychain"); +# ifdef HAVE_GNUTLS + cupsdSetString(&ServerKeychain, "ssl"); # else - cupsdSetString(&ServerCertificate, "ssl/server.crt"); - cupsdSetString(&ServerKey, "ssl/server.key"); -# endif /* HAVE_CDSASSL */ + cupsdSetString(&ServerKeychain, "/Library/Keychains/System.keychain"); +# endif /* HAVE_GNUTLS */ + + _httpTLSSetOptions(0); #endif /* HAVE_SSL */ language = cupsLangDefault(); @@ -695,10 +704,10 @@ cupsdReadConfiguration(void) AccessLogLevel = CUPSD_ACCESSLOG_ACTIONS; ConfigFilePerm = CUPS_DEFAULT_CONFIG_FILE_PERM; FatalErrors = parse_fatal_errors(CUPS_DEFAULT_FATAL_ERRORS); - default_auth_type = CUPSD_AUTH_BASIC; + default_auth_type = CUPSD_AUTH_BASIC; #ifdef HAVE_SSL + CreateSelfSignedCerts = TRUE; DefaultEncryption = HTTP_ENCRYPT_REQUIRED; - SSLOptions = CUPSD_SSL_NONE; #endif /* HAVE_SSL */ DirtyCleanInterval = DEFAULT_KEEPALIVE; JobKillDelay = DEFAULT_TIMEOUT; @@ -724,7 +733,9 @@ cupsdReadConfiguration(void) NumSystemGroups = 0; ReloadTimeout = DEFAULT_KEEPALIVE; RootCertDuration = 300; + Sandboxing = CUPSD_SANDBOXING_STRICT; StrictConformance = FALSE; + SyncOnClose = FALSE; Timeout = DEFAULT_TIMEOUT; WebInterface = CUPS_DEFAULT_WEBIF; @@ -757,7 +768,7 @@ cupsdReadConfiguration(void) cupsdClearString(&DefaultPolicy); #ifdef HAVE_AUTHORIZATION_H - cupsdClearString(&SystemGroupAuthKey); + cupsdSetString(&SystemGroupAuthKey, CUPS_DEFAULT_SYSTEM_AUTHKEY); #endif /* HAVE_AUTHORIZATION_H */ MaxSubscriptions = 100; @@ -767,9 +778,9 @@ cupsdReadConfiguration(void) DefaultLeaseDuration = 86400; MaxLeaseDuration = 0; -#ifdef HAVE_LAUNCHD - LaunchdTimeout = 10; -#endif /* HAVE_LAUNCHD */ +#ifdef HAVE_ONDEMAND + IdleExitTimeout = 60; +#endif /* HAVE_ONDEMAND */ /* * Setup environment variables... @@ -778,21 +789,77 @@ cupsdReadConfiguration(void) cupsdInitEnv(); /* - * Read the configuration file... + * Read the cups-files.conf file... + */ + + if ((fp = cupsFileOpen(CupsFilesFile, "r")) != NULL) + { + status = read_cups_files_conf(fp); + + cupsFileClose(fp); + + if (!status) + { + if (TestConfigFile) + printf("\"%s\" contains errors.\n", CupsFilesFile); + else +#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); + } + } + else if (errno == ENOENT) + cupsdLogMessage(CUPSD_LOG_INFO, "No %s, using defaults.", CupsFilesFile); + else + { +#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); + } + + if (!ErrorLog) + cupsdSetString(&ErrorLog, CUPS_LOGDIR "/error_log"); + + /* + * Read the cupsd.conf file... */ if ((fp = cupsFileOpen(ConfigurationFile, "r")) == NULL) + { +#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); + } - status = read_configuration(fp); + status = read_cupsd_conf(fp); cupsFileClose(fp); if (!status) - return (0); + { + if (TestConfigFile) + printf("\"%s\" contains errors.\n", ConfigurationFile); + else +#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 */ - if (!ErrorLog) - cupsdSetString(&ErrorLog, CUPS_LOGDIR "/error_log"); + return (0); + } RunUser = getuid(); @@ -906,28 +973,34 @@ cupsdReadConfiguration(void) } /* - * Open the system log for cupsd if necessary... + * Make sure ConfigFilePerm and LogFilePerm have sane values... */ -#ifdef HAVE_VSYSLOG - if (!strcmp(AccessLog, "syslog") || - !strcmp(ErrorLog, "syslog") || - !strcmp(PageLog, "syslog")) - openlog("cupsd", LOG_PID | LOG_NOWAIT | LOG_NDELAY, LOG_LPR); -#endif /* HAVE_VSYSLOG */ + ConfigFilePerm &= 0664; + LogFilePerm &= 0664; /* - * Make sure each of the log files exists and gets rotated as necessary... + * Open the system log for cupsd if necessary... */ - if (strcmp(AccessLog, "syslog")) - cupsdCheckLogFile(&AccessFile, AccessLog); + if (!LogStderr) + { + if (!strcmp(AccessLog, "stderr")) + cupsdSetString(&AccessLog, "syslog"); + + if (!strcmp(ErrorLog, "stderr")) + cupsdSetString(&ErrorLog, "syslog"); - if (strcmp(ErrorLog, "syslog")) - cupsdCheckLogFile(&ErrorFile, ErrorLog); + if (!strcmp(PageLog, "stderr")) + cupsdSetString(&PageLog, "syslog"); + } - if (strcmp(PageLog, "syslog")) - cupsdCheckLogFile(&PageFile, PageLog); +#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 && !HAVE_ASL_H && !HAVE_SYSTEMD_SD_JOURNAL_H */ /* * Log the configuration file that was used... @@ -954,8 +1027,11 @@ cupsdReadConfiguration(void) * Log the error and reset the group to a safe value... */ - cupsdLogMessage(CUPSD_LOG_NOTICE, + cupsdLogMessage(CUPSD_LOG_ERROR, "Group and SystemGroup cannot use the same groups."); + if (FatalErrors & (CUPSD_FATAL_CONFIG | CUPSD_FATAL_PERMISSIONS)) + return (0); + cupsdLogMessage(CUPSD_LOG_INFO, "Resetting Group to \"nobody\"..."); group = getgrnam("nobody"); @@ -1023,24 +1099,15 @@ cupsdReadConfiguration(void) cupsdSetStringf(&CacheDir, "%s/%s", ServerRoot, CacheDir); #ifdef HAVE_SSL - if (ServerCertificate[0] != '/') - cupsdSetStringf(&ServerCertificate, "%s/%s", ServerRoot, ServerCertificate); - - if (!strncmp(ServerRoot, ServerCertificate, strlen(ServerRoot)) && - cupsdCheckPermissions(ServerCertificate, NULL, 0600, RunUser, Group, - 0, 0) < 0 && - (FatalErrors & CUPSD_FATAL_PERMISSIONS)) - return (0); - -# if defined(HAVE_LIBSSL) || defined(HAVE_GNUTLS) - if (ServerKey[0] != '/') - cupsdSetStringf(&ServerKey, "%s/%s", ServerRoot, ServerKey); - - if (!strncmp(ServerRoot, ServerKey, strlen(ServerRoot)) && - cupsdCheckPermissions(ServerKey, NULL, 0600, RunUser, Group, 0, 0) < 0 && - (FatalErrors & CUPSD_FATAL_PERMISSIONS)) - return (0); -# endif /* HAVE_LIBSSL || HAVE_GNUTLS */ + 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 ? ServerKeychain : "internal", ServerName); + if (!CreateSelfSignedCerts) + cupsdLogMessage(CUPSD_LOG_DEBUG, "Self-signed TLS certificate generation is disabled."); + cupsSetServerCredentials(ServerKeychain, ServerName, CreateSelfSignedCerts); #endif /* HAVE_SSL */ /* @@ -1052,7 +1119,7 @@ cupsdReadConfiguration(void) if ((cupsdCheckPermissions(RequestRoot, NULL, 0710, RunUser, Group, 1, 1) < 0 || - cupsdCheckPermissions(CacheDir, NULL, 0775, RunUser, + cupsdCheckPermissions(CacheDir, NULL, 0770, RunUser, Group, 1, 1) < 0 || cupsdCheckPermissions(temp, NULL, 0775, RunUser, Group, 1, 1) < 0 || @@ -1066,7 +1133,9 @@ cupsdReadConfiguration(void) Group, 1, 1) < 0 || cupsdCheckPermissions(ServerRoot, "ssl", 0700, RunUser, Group, 1, 0) < 0 || - cupsdCheckPermissions(ServerRoot, "cupsd.conf", ConfigFilePerm, RunUser, + cupsdCheckPermissions(ConfigurationFile, NULL, ConfigFilePerm, RunUser, + Group, 0, 0) < 0 || + cupsdCheckPermissions(CupsFilesFile, NULL, ConfigFilePerm, RunUser, Group, 0, 0) < 0 || cupsdCheckPermissions(ServerRoot, "classes.conf", 0600, RunUser, Group, 0, 0) < 0 || @@ -1081,11 +1150,20 @@ cupsdReadConfiguration(void) * Update TempDir to the default if it hasn't been set already... */ +#ifdef __APPLE__ + if (TempDir && !RunUser && + (!strncmp(TempDir, "/private/tmp", 12) || !strncmp(TempDir, "/tmp", 4))) + { + cupsdLogMessage(CUPSD_LOG_ERROR, "Cannot use %s for TempDir.", TempDir); + cupsdClearString(&TempDir); + } +#endif /* __APPLE__ */ + if (!TempDir) { #ifdef __APPLE__ if ((tmpdir = getenv("TMPDIR")) != NULL && - strncmp(tmpdir, "/private/tmp", 12)) + strncmp(tmpdir, "/private/tmp", 12) && strncmp(tmpdir, "/tmp", 4)) #else if ((tmpdir = getenv("TMPDIR")) != NULL) #endif /* __APPLE__ */ @@ -1108,15 +1186,17 @@ cupsdReadConfiguration(void) else cupsdSetString(&TempDir, tmpdir); } + } - if (!TempDir) - { - cupsdLogMessage(CUPSD_LOG_INFO, "Using default TempDir of %s/tmp...", - RequestRoot); - cupsdSetStringf(&TempDir, "%s/tmp", RequestRoot); - } + if (!TempDir) + { + cupsdLogMessage(CUPSD_LOG_INFO, "Using default TempDir of %s/tmp...", + RequestRoot); + cupsdSetStringf(&TempDir, "%s/tmp", RequestRoot); } + setenv("TMPDIR", TempDir, 1); + /* * Make sure the temporary directory has the right permissions... */ @@ -1140,6 +1220,19 @@ cupsdReadConfiguration(void) cupsdUpdateEnv(); + /* + * Validate the default error policy... + */ + + if (strcmp(ErrorPolicy, "retry-current-job") && + strcmp(ErrorPolicy, "abort-job") && + strcmp(ErrorPolicy, "retry-job") && + strcmp(ErrorPolicy, "stop-printer")) + { + cupsdLogMessage(CUPSD_LOG_ALERT, "Invalid ErrorPolicy \"%s\", resetting to \"stop-printer\".", ErrorPolicy); + cupsdSetString(&ErrorPolicy, "stop-printer"); + } + /* * Update default paper size setting as needed... */ @@ -1262,6 +1355,7 @@ cupsdReadConfiguration(void) cupsdAddString(&(p->job_attrs), "job-name"); cupsdAddString(&(p->job_attrs), "job-originating-host-name"); cupsdAddString(&(p->job_attrs), "job-originating-user-name"); + cupsdAddString(&(p->job_attrs), "phone"); cupsdLogMessage(CUPSD_LOG_INFO, "SubscriptionPrivateAccess default"); cupsdAddString(&(p->sub_access), "@OWNER"); @@ -1470,7 +1564,7 @@ cupsdReadConfiguration(void) if (!mimeType(MimeDatabase, "application", "octet-stream")) NumMimeTypes ++; - if ((MimeTypes = calloc(NumMimeTypes, sizeof(const char *))) == NULL) + if ((MimeTypes = calloc((size_t)NumMimeTypes, sizeof(const char *))) == NULL) { cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to allocate memory for %d MIME types.", @@ -1744,7 +1838,8 @@ get_addr_and_mask(const char *value, /* I - String from config file */ * Merge everything into a 32-bit IPv4 address in ip[3]... */ - ip[3] = (((((val[0] << 8) | val[1]) << 8) | val[2]) << 8) | val[3]; + ip[3] = ((((((unsigned)val[0] << 8) | (unsigned)val[1]) << 8) | + (unsigned)val[2]) << 8) | (unsigned)val[3]; if (ipcount < 4) mask[3] = (0xffffffff << (32 - 8 * ipcount)) & 0xffffffff; @@ -1812,7 +1907,8 @@ get_addr_and_mask(const char *value, /* I - String from config file */ * Merge everything into a 32-bit IPv4 address in ip[3]... */ - ip[3] = (((((val[0] << 8) | val[1]) << 8) | val[2]) << 8) | val[3]; + ip[3] = ((((((unsigned)val[0] << 8) | (unsigned)val[1]) << 8) | + (unsigned)val[2]) << 8) | (unsigned)val[3]; if (ipcount < 4) mask[3] = (0xffffffff << (32 - 8 * ipcount)) & 0xffffffff; @@ -1839,7 +1935,8 @@ get_addr_and_mask(const char *value, /* I - String from config file */ mask + 3) != 4) return (0); - mask[3] |= ((((mask[0] << 8) | mask[1]) << 8) | mask[2]) << 8; + mask[3] |= (((((unsigned)mask[0] << 8) | (unsigned)mask[1]) << 8) | + (unsigned)mask[2]) << 8; mask[0] = mask[1] = mask[2] = 0; } else @@ -1962,8 +2059,8 @@ parse_aaa(cupsd_location_t *loc, /* I - Location */ else if (!_cups_strcasecmp(value, "always")) { cupsdLogMessage(CUPSD_LOG_ERROR, - "Encryption value \"%s\" on line %d is invalid in this " - "context. Using \"required\" instead.", value, linenum); + "Encryption value \"%s\" on line %d of %s is invalid in this " + "context. Using \"required\" instead.", value, linenum, ConfigurationFile); loc->encryption = HTTP_ENCRYPT_REQUIRED; } @@ -1974,7 +2071,7 @@ parse_aaa(cupsd_location_t *loc, /* I - Location */ else { cupsdLogMessage(CUPSD_LOG_ERROR, - "Unknown Encryption value %s on line %d.", value, linenum); + "Unknown Encryption value %s on line %d of %s.", value, linenum, ConfigurationFile); return (0); } } @@ -1990,8 +2087,8 @@ parse_aaa(cupsd_location_t *loc, /* I - Location */ loc->order_type = CUPSD_AUTH_DENY; else { - cupsdLogMessage(CUPSD_LOG_ERROR, "Unknown Order value %s on line %d.", - value, linenum); + cupsdLogMessage(CUPSD_LOG_ERROR, "Unknown Order value %s on line %d of %s.", + value, linenum, ConfigurationFile); return (0); } } @@ -2093,8 +2190,8 @@ parse_aaa(cupsd_location_t *loc, /* I - Location */ if (!get_addr_and_mask(value, ip, mask)) { - cupsdLogMessage(CUPSD_LOG_ERROR, "Bad netmask value %s on line %d.", - value, linenum); + cupsdLogMessage(CUPSD_LOG_ERROR, "Bad netmask value %s on line %d of %s.", + value, linenum, ConfigurationFile); return (0); } @@ -2129,20 +2226,6 @@ parse_aaa(cupsd_location_t *loc, /* I - Location */ if (loc->level == CUPSD_AUTH_ANON) loc->level = CUPSD_AUTH_USER; } - else if (!_cups_strcasecmp(value, "digest")) - { - loc->type = CUPSD_AUTH_DIGEST; - - if (loc->level == CUPSD_AUTH_ANON) - loc->level = CUPSD_AUTH_USER; - } - else if (!_cups_strcasecmp(value, "basicdigest")) - { - loc->type = CUPSD_AUTH_BASICDIGEST; - - if (loc->level == CUPSD_AUTH_ANON) - loc->level = CUPSD_AUTH_USER; - } else if (!_cups_strcasecmp(value, "default")) { loc->type = CUPSD_AUTH_DEFAULT; @@ -2162,8 +2245,8 @@ parse_aaa(cupsd_location_t *loc, /* I - Location */ else { cupsdLogMessage(CUPSD_LOG_WARN, - "Unknown authorization type %s on line %d.", - value, linenum); + "Unknown authorization type %s on line %d of %s.", + value, linenum, ConfigurationFile); return (0); } } @@ -2189,8 +2272,8 @@ parse_aaa(cupsd_location_t *loc, /* I - Location */ cupsdLogMessage(CUPSD_LOG_WARN, "\"AuthClass %s\" is deprecated; consider using " - "\"Require valid-user\" on line %d.", - value, linenum); + "\"Require valid-user\" on line %d of %s.", + value, linenum, ConfigurationFile); } else if (!_cups_strcasecmp(value, "group")) { @@ -2198,8 +2281,8 @@ parse_aaa(cupsd_location_t *loc, /* I - Location */ cupsdLogMessage(CUPSD_LOG_WARN, "\"AuthClass %s\" is deprecated; consider using " - "\"Require user @groupname\" on line %d.", - value, linenum); + "\"Require user @groupname\" on line %d of %s.", + value, linenum, ConfigurationFile); } else if (!_cups_strcasecmp(value, "system")) { @@ -2209,14 +2292,14 @@ parse_aaa(cupsd_location_t *loc, /* I - Location */ cupsdLogMessage(CUPSD_LOG_WARN, "\"AuthClass %s\" is deprecated; consider using " - "\"Require user @SYSTEM\" on line %d.", - value, linenum); + "\"Require user @SYSTEM\" on line %d of %s.", + value, linenum, ConfigurationFile); } else { cupsdLogMessage(CUPSD_LOG_WARN, - "Unknown authorization class %s on line %d.", - value, linenum); + "Unknown authorization class %s on line %d of %s.", + value, linenum, ConfigurationFile); return (0); } } @@ -2226,8 +2309,8 @@ parse_aaa(cupsd_location_t *loc, /* I - Location */ cupsdLogMessage(CUPSD_LOG_WARN, "\"AuthGroupName %s\" directive is deprecated; consider " - "using \"Require user @%s\" on line %d.", - value, value, linenum); + "using \"Require user @%s\" on line %d of %s.", + value, value, linenum, ConfigurationFile); } else if (!_cups_strcasecmp(line, "Require")) { @@ -2253,8 +2336,8 @@ parse_aaa(cupsd_location_t *loc, /* I - Location */ loc->level = CUPSD_AUTH_GROUP; else { - cupsdLogMessage(CUPSD_LOG_WARN, "Unknown Require type %s on line %d.", - value, linenum); + cupsdLogMessage(CUPSD_LOG_WARN, "Unknown Require type %s on line %d of %s.", + value, linenum, ConfigurationFile); return (0); } @@ -2316,8 +2399,8 @@ parse_aaa(cupsd_location_t *loc, /* I - Location */ loc->satisfy = CUPSD_AUTH_SATISFY_ANY; else { - cupsdLogMessage(CUPSD_LOG_WARN, "Unknown Satisfy value %s on line %d.", - value, linenum); + cupsdLogMessage(CUPSD_LOG_WARN, "Unknown Satisfy value %s on line %d of %s.", + value, linenum, ConfigurationFile); return (0); } } @@ -2548,114 +2631,421 @@ parse_protocols(const char *s) /* I - Space-delimited protocols */ /* - * 'read_configuration()' - Read a configuration file. + * 'parse_variable()' - Parse a variable line. */ static int /* O - 1 on success, 0 on failure */ -read_configuration(cups_file_t *fp) /* I - File to read from */ +parse_variable( + const char *filename, /* I - Name of configuration file */ + int linenum, /* I - Line in configuration file */ + const char *line, /* I - Line from configuration file */ + const char *value, /* I - Value from configuration file */ + size_t num_vars, /* I - Number of variables */ + const cupsd_var_t *vars) /* I - Variables */ { - int i; /* Looping var */ - int linenum; /* Current line number */ - char line[HTTP_MAX_BUFFER], - /* Line from file */ - temp[HTTP_MAX_BUFFER], - /* Temporary buffer for value */ - *value, /* Pointer to value */ - *valueptr; /* Pointer into value */ - int valuelen; /* Length of value */ - cupsd_var_t const *var; /* Current variable */ - http_addrlist_t *addrlist, /* Address list */ - *addr; /* Current address */ - cups_file_t *incfile; /* Include file */ - char incname[1024]; /* Include filename */ - struct group *group; /* Group */ + size_t i; /* Looping var */ + const cupsd_var_t *var; /* Variables */ + char temp[1024]; /* Temporary string */ - /* - * Loop through each line in the file... - */ - - linenum = 0; + for (i = num_vars, var = vars; i > 0; i --, var ++) + if (!_cups_strcasecmp(line, var->name)) + break; - while (cupsFileGetConf(fp, line, sizeof(line), &value, &linenum)) + if (i == 0) { /* - * Decode the directive... + * Unknown directive! Output an error message and continue... */ - if (!_cups_strcasecmp(line, "Include") && value) - { - /* - * Include filename - */ + if (!value) + cupsdLogMessage(CUPSD_LOG_ERROR, "Missing value for %s on line %d of %s.", + line, linenum, filename); + else + cupsdLogMessage(CUPSD_LOG_ERROR, "Unknown directive %s on line %d of %s.", + line, linenum, filename); - if (value[0] == '/') - strlcpy(incname, value, sizeof(incname)); - else - snprintf(incname, sizeof(incname), "%s/%s", ServerRoot, value); + return (0); + } - if ((incfile = cupsFileOpen(incname, "rb")) == NULL) - cupsdLogMessage(CUPSD_LOG_ERROR, - "Unable to include config file \"%s\" - %s", - incname, strerror(errno)); - else - { - read_configuration(incfile); - cupsFileClose(incfile); - } - } - else if (!_cups_strcasecmp(line, " - */ + switch (var->type) + { + case CUPSD_VARTYPE_INTEGER : + if (!value) + { + cupsdLogMessage(CUPSD_LOG_ERROR, + "Missing integer value for %s on line %d of %s.", + line, linenum, filename); + return (0); + } + else if (!isdigit(*value & 255)) + { + cupsdLogMessage(CUPSD_LOG_ERROR, + "Bad integer value for %s on line %d of %s.", + line, linenum, filename); + return (0); + } + else + { + int n; /* Number */ + char *units; /* Units */ - linenum = read_location(fp, value, linenum); - if (linenum == 0) - return (0); - } - else if (!_cups_strcasecmp(line, " - */ + n = strtol(value, &units, 0); - linenum = read_policy(fp, value, linenum); - if (linenum == 0) - return (0); - } - else if (!_cups_strcasecmp(line, "FatalErrors")) - FatalErrors = parse_fatal_errors(value); - else if (!_cups_strcasecmp(line, "FaxRetryInterval") && value) - { - JobRetryInterval = atoi(value); - cupsdLogMessage(CUPSD_LOG_WARN, - "FaxRetryInterval is deprecated; use " - "JobRetryInterval on line %d.", linenum); - } - else if (!_cups_strcasecmp(line, "FaxRetryLimit") && value) - { - JobRetryLimit = atoi(value); - cupsdLogMessage(CUPSD_LOG_WARN, - "FaxRetryLimit is deprecated; use " - "JobRetryLimit on line %d.", linenum); - } - else if ((!_cups_strcasecmp(line, "Port") || !_cups_strcasecmp(line, "Listen") -#ifdef HAVE_SSL - || !_cups_strcasecmp(line, "SSLPort") || !_cups_strcasecmp(line, "SSLListen") -#endif /* HAVE_SSL */ - ) && value) - { - /* - * Add listening address(es) to the list... - */ + if (units && *units) + { + if (tolower(units[0] & 255) == 'g') + n *= 1024 * 1024 * 1024; + else if (tolower(units[0] & 255) == 'm') + n *= 1024 * 1024; + else if (tolower(units[0] & 255) == 'k') + n *= 1024; + else if (tolower(units[0] & 255) == 't') + n *= 262144; + else + { + cupsdLogMessage(CUPSD_LOG_ERROR, + "Unknown integer value for %s on line %d of %s.", + line, linenum, filename); + return (0); + } + } - cupsd_listener_t *lis; /* New listeners array */ + if (n < 0) + { + cupsdLogMessage(CUPSD_LOG_ERROR, + "Bad negative integer value for %s on line %d of " + "%s.", line, linenum, filename); + return (0); + } + else + { + *((int *)var->ptr) = n; + } + } + break; + case CUPSD_VARTYPE_PERM : + if (!value) + { + cupsdLogMessage(CUPSD_LOG_ERROR, + "Missing permissions value for %s on line %d of %s.", + line, linenum, filename); + return (0); + } + else if (!isdigit(*value & 255)) + { + /* TODO: Add chmod UGO syntax support */ + cupsdLogMessage(CUPSD_LOG_ERROR, + "Bad permissions value for %s on line %d of %s.", + line, linenum, filename); + return (0); + } + else + { + int n = strtol(value, NULL, 8); + /* Permissions value */ - /* - * Get the address list... - */ + if (n < 0) + { + cupsdLogMessage(CUPSD_LOG_ERROR, + "Bad negative permissions value for %s on line %d of " + "%s.", line, linenum, filename); + return (0); + } + else + { + *((mode_t *)var->ptr) = (mode_t)n; + } + } + break; + + case CUPSD_VARTYPE_TIME : + if (!value) + { + cupsdLogMessage(CUPSD_LOG_ERROR, + "Missing time interval value for %s on line %d of " + "%s.", line, linenum, filename); + return (0); + } + else if (!_cups_strncasecmp(line, "PreserveJob", 11) && + (!_cups_strcasecmp(value, "true") || + !_cups_strcasecmp(value, "on") || + !_cups_strcasecmp(value, "enabled") || + !_cups_strcasecmp(value, "yes"))) + { + *((int *)var->ptr) = INT_MAX; + } + else if (!_cups_strcasecmp(value, "false") || + !_cups_strcasecmp(value, "off") || + !_cups_strcasecmp(value, "disabled") || + !_cups_strcasecmp(value, "no")) + { + *((int *)var->ptr) = 0; + } + else if (!isdigit(*value & 255)) + { + cupsdLogMessage(CUPSD_LOG_ERROR, + "Unknown time interval value for %s on line %d of " + "%s.", line, linenum, filename); + return (0); + } + else + { + double n; /* Number */ + char *units; /* Units */ + + n = strtod(value, &units); + + if (units && *units) + { + if (tolower(units[0] & 255) == 'w') + n *= 7 * 24 * 60 * 60; + else if (tolower(units[0] & 255) == 'd') + n *= 24 * 60 * 60; + else if (tolower(units[0] & 255) == 'h') + n *= 60 * 60; + else if (tolower(units[0] & 255) == 'm') + n *= 60; + else + { + cupsdLogMessage(CUPSD_LOG_ERROR, + "Unknown time interval value for %s on line " + "%d of %s.", line, linenum, filename); + return (0); + } + } + + if (n < 0.0 || n > INT_MAX) + { + cupsdLogMessage(CUPSD_LOG_ERROR, + "Bad time value for %s on line %d of %s.", + line, linenum, filename); + return (0); + } + else + { + *((int *)var->ptr) = (int)n; + } + } + break; + + case CUPSD_VARTYPE_BOOLEAN : + if (!value) + { + cupsdLogMessage(CUPSD_LOG_ERROR, + "Missing boolean value for %s on line %d of %s.", + line, linenum, filename); + return (0); + } + else if (!_cups_strcasecmp(value, "true") || + !_cups_strcasecmp(value, "on") || + !_cups_strcasecmp(value, "enabled") || + !_cups_strcasecmp(value, "yes") || + atoi(value) != 0) + { + *((int *)var->ptr) = TRUE; + } + else if (!_cups_strcasecmp(value, "false") || + !_cups_strcasecmp(value, "off") || + !_cups_strcasecmp(value, "disabled") || + !_cups_strcasecmp(value, "no") || + !_cups_strcasecmp(value, "0")) + { + *((int *)var->ptr) = FALSE; + } + else + { + cupsdLogMessage(CUPSD_LOG_ERROR, + "Unknown boolean value %s on line %d of %s.", + value, linenum, filename); + return (0); + } + break; + + case CUPSD_VARTYPE_PATHNAME : + if (!value) + { + cupsdLogMessage(CUPSD_LOG_ERROR, + "Missing pathname value for %s on line %d of %s.", + line, linenum, filename); + return (0); + } + + if (value[0] == '/') + strlcpy(temp, value, sizeof(temp)); + else + snprintf(temp, sizeof(temp), "%s/%s", ServerRoot, value); + + 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 " + "does not exist.", line, value, linenum, filename); + return (0); + } + + cupsdSetString((char **)var->ptr, temp); + break; + + case CUPSD_VARTYPE_STRING : + cupsdSetString((char **)var->ptr, value); + break; + } + + return (1); +} + + +/* + * 'read_cupsd_conf()' - Read the cupsd.conf configuration file. + */ + +static int /* O - 1 on success, 0 on failure */ +read_cupsd_conf(cups_file_t *fp) /* I - File to read from */ +{ + int linenum; /* Current line number */ + char line[HTTP_MAX_BUFFER], + /* Line from file */ + temp[HTTP_MAX_BUFFER], + /* Temporary buffer for value */ + *value, /* Pointer to value */ + *valueptr; /* Pointer into 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 */ + + + /* + * Loop through each line in the file... + */ + + linenum = 0; + + while (cupsFileGetConf(fp, line, sizeof(line), &value, &linenum)) + { + /* + * 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, " + */ + + linenum = read_location(fp, value, linenum); + if (linenum == 0) + return (0); + } + else if (!_cups_strcasecmp(line, " + */ + + linenum = read_policy(fp, value, linenum); + if (linenum == 0) + return (0); + } + else if (!_cups_strcasecmp(line, "FaxRetryInterval") && value) + { + JobRetryInterval = atoi(value); + cupsdLogMessage(CUPSD_LOG_WARN, + "FaxRetryInterval is deprecated; use " + "JobRetryInterval on line %d of %s.", linenum, ConfigurationFile); + } + else if (!_cups_strcasecmp(line, "FaxRetryLimit") && value) + { + JobRetryLimit = atoi(value); + cupsdLogMessage(CUPSD_LOG_WARN, + "FaxRetryLimit is deprecated; use " + "JobRetryLimit on line %d of %s.", linenum, ConfigurationFile); + } +#ifdef HAVE_SSL + else if (!_cups_strcasecmp(line, "SSLOptions")) + { + /* + * SSLOptions [AllowRC4] [AllowSSL3] [None] + */ + + int options = 0; /* SSL/TLS options */ + + if (value) + { + char *start, /* Start of option */ + *end; /* End of option */ + + for (start = value; *start; start = end) + { + /* + * Find end of keyword... + */ + + end = start; + while (*end && !_cups_isspace(*end)) + end ++; + + if (*end) + *end++ = '\0'; + + /* + * Compare... + */ + + 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, "NoEmptyFragments")) + cupsdLogMessage(CUPSD_LOG_WARN, "Unknown SSL option %s at line %d.", start, linenum); + } + } + + _httpTLSSetOptions(options); + } +#endif /* HAVE_SSL */ + else if ((!_cups_strcasecmp(line, "Port") || !_cups_strcasecmp(line, "Listen") +#ifdef HAVE_SSL + || !_cups_strcasecmp(line, "SSLPort") || !_cups_strcasecmp(line, "SSLListen") +#endif /* HAVE_SSL */ + ) && value) + { + /* + * Add listening address(es) to the list... + */ + + cupsd_listener_t *lis; /* New listeners array */ + + + /* + * Get the address list... + */ addrlist = get_address(value, IPP_PORT); @@ -2680,14 +3070,20 @@ read_configuration(cups_file_t *fp) /* I - File to read from */ lis; lis = (cupsd_listener_t *)cupsArrayNext(Listeners)) if (httpAddrEqual(&(addr->addr), &(lis->address)) && - _httpAddrPort(&(addr->addr)) == _httpAddrPort(&(lis->address))) + httpAddrPort(&(addr->addr)) == httpAddrPort(&(lis->address))) break; if (lis) { - httpAddrString(&lis->address, temp, sizeof(temp)); - cupsdLogMessage(CUPSD_LOG_WARN, - "Duplicate listen address \"%s\" ignored.", temp); +#ifdef HAVE_ONDEMAND + if (!lis->on_demand) +#endif /* HAVE_ONDEMAND */ + { + httpAddrString(&lis->address, temp, sizeof(temp)); + cupsdLogMessage(CUPSD_LOG_WARN, + "Duplicate listen address \"%s\" ignored.", temp); + } + continue; } @@ -2736,11 +3132,11 @@ read_configuration(cups_file_t *fp) /* I - File to read from */ else #endif /* AF_LOCAL */ cupsdLogMessage(CUPSD_LOG_INFO, "Listening to %s:%d (IPv%d)", temp, - _httpAddrPort(&(lis->address)), - _httpAddrFamily(&(lis->address)) == AF_INET ? 4 : 6); + httpAddrPort(&(lis->address)), + httpAddrFamily(&(lis->address)) == AF_INET ? 4 : 6); if (!httpAddrLocalhost(&(lis->address))) - RemotePort = _httpAddrPort(&(lis->address)); + RemotePort = httpAddrPort(&(lis->address)); } /* @@ -2762,27 +3158,23 @@ read_configuration(cups_file_t *fp) /* I - File to read from */ if (protocols < 0) { cupsdLogMessage(CUPSD_LOG_ERROR, - "Unknown browse protocol \"%s\" on line %d.", - value, linenum); + "Unknown browse protocol \"%s\" on line %d of %s.", + value, linenum, ConfigurationFile); break; } BrowseLocalProtocols = protocols; } - else if (!_cups_strcasecmp(line, "default_auth_type") && value) + else if (!_cups_strcasecmp(line, "DefaultAuthType") && value) { /* - * default_auth_type {basic,digest,basicdigest,negotiate} + * DefaultAuthType {basic,digest,basicdigest,negotiate} */ if (!_cups_strcasecmp(value, "none")) default_auth_type = CUPSD_AUTH_NONE; else if (!_cups_strcasecmp(value, "basic")) default_auth_type = CUPSD_AUTH_BASIC; - else if (!_cups_strcasecmp(value, "digest")) - default_auth_type = CUPSD_AUTH_DIGEST; - else if (!_cups_strcasecmp(value, "basicdigest")) - default_auth_type = CUPSD_AUTH_BASICDIGEST; #ifdef HAVE_GSSAPI else if (!_cups_strcasecmp(value, "negotiate")) default_auth_type = CUPSD_AUTH_NEGOTIATE; @@ -2792,8 +3184,8 @@ read_configuration(cups_file_t *fp) /* I - File to read from */ else { cupsdLogMessage(CUPSD_LOG_WARN, - "Unknown default authorization type %s on line %d.", - value, linenum); + "Unknown default authorization type %s on line %d of %s.", + value, linenum, ConfigurationFile); if (FatalErrors & CUPSD_FATAL_CONFIG) return (0); } @@ -2814,88 +3206,13 @@ read_configuration(cups_file_t *fp) /* I - File to read from */ else { cupsdLogMessage(CUPSD_LOG_WARN, - "Unknown default encryption %s on line %d.", - value, linenum); + "Unknown default encryption %s on line %d of %s.", + value, linenum, ConfigurationFile); if (FatalErrors & CUPSD_FATAL_CONFIG) return (0); } } #endif /* HAVE_SSL */ - else if (!_cups_strcasecmp(line, "User") && value) - { - /* - * User ID to run as... - */ - - if (isdigit(value[0] & 255)) - { - int uid = atoi(value); - - if (!uid) - cupsdLogMessage(CUPSD_LOG_ERROR, - "Will not use User 0 as specified on line %d " - "for security reasons. You must use a non-" - "privileged account instead.", - linenum); - else - User = atoi(value); - } - else - { - struct passwd *p; /* Password information */ - - endpwent(); - p = getpwnam(value); - - if (p) - { - if (!p->pw_uid) - cupsdLogMessage(CUPSD_LOG_ERROR, - "Will not use User %s (UID=0) as specified on line " - "%d for security reasons. You must use a non-" - "privileged account instead.", - value, linenum); - else - User = p->pw_uid; - } - else - cupsdLogMessage(CUPSD_LOG_ERROR, - "Unknown User \"%s\" on line %d, ignoring.", - value, linenum); - } - } - else if (!_cups_strcasecmp(line, "Group") && value) - { - /* - * Group ID to run as... - */ - - if (isdigit(value[0])) - Group = atoi(value); - else - { - endgrent(); - group = getgrnam(value); - - if (group != NULL) - Group = group->gr_gid; - else - cupsdLogMessage(CUPSD_LOG_ERROR, - "Unknown Group \"%s\" on line %d, ignoring.", - value, linenum); - } - } - else if (!_cups_strcasecmp(line, "SystemGroup") && value) - { - /* - * SystemGroup (admin) group(s)... - */ - - if (!parse_groups(value)) - cupsdLogMessage(CUPSD_LOG_ERROR, - "Unknown SystemGroup \"%s\" on line %d, ignoring.", - value, linenum); - } else if (!_cups_strcasecmp(line, "HostNameLookups") && value) { /* @@ -2911,8 +3228,8 @@ read_configuration(cups_file_t *fp) /* I - File to read from */ else if (!_cups_strcasecmp(value, "double")) HostNameLookups = 2; else - cupsdLogMessage(CUPSD_LOG_WARN, "Unknown HostNameLookups %s on line %d.", - value, linenum); + cupsdLogMessage(CUPSD_LOG_WARN, "Unknown HostNameLookups %s on line %d of %s.", + value, linenum, ConfigurationFile); } else if (!_cups_strcasecmp(line, "AccessLogLevel") && value) { @@ -2926,9 +3243,11 @@ read_configuration(cups_file_t *fp) /* I - File to read from */ AccessLogLevel = CUPSD_ACCESSLOG_ACTIONS; else if (!_cups_strcasecmp(value, "config")) AccessLogLevel = CUPSD_ACCESSLOG_CONFIG; + else if (!_cups_strcasecmp(value, "none")) + AccessLogLevel = CUPSD_ACCESSLOG_NONE; else - cupsdLogMessage(CUPSD_LOG_WARN, "Unknown AccessLogLevel %s on line %d.", - value, linenum); + cupsdLogMessage(CUPSD_LOG_WARN, "Unknown AccessLogLevel %s on line %d of %s.", + value, linenum, ConfigurationFile); } else if (!_cups_strcasecmp(line, "LogLevel") && value) { @@ -2957,8 +3276,8 @@ read_configuration(cups_file_t *fp) /* I - File to read from */ else if (!_cups_strcasecmp(value, "none")) LogLevel = CUPSD_LOG_NONE; else - cupsdLogMessage(CUPSD_LOG_WARN, "Unknown LogLevel %s on line %d.", - value, linenum); + cupsdLogMessage(CUPSD_LOG_WARN, "Unknown LogLevel %s on line %d of %s.", + value, linenum, ConfigurationFile); } else if (!_cups_strcasecmp(line, "LogTimeFormat") && value) { @@ -2971,24 +3290,8 @@ read_configuration(cups_file_t *fp) /* I - File to read from */ else if (!_cups_strcasecmp(value, "usecs")) LogTimeFormat = CUPSD_TIME_USECS; else - cupsdLogMessage(CUPSD_LOG_WARN, "Unknown LogTimeFormat %s on line %d.", - value, linenum); - } - else if (!_cups_strcasecmp(line, "PrintcapFormat") && value) - { - /* - * Format of printcap file? - */ - - if (!_cups_strcasecmp(value, "bsd")) - PrintcapFormat = PRINTCAP_BSD; - else if (!_cups_strcasecmp(value, "plist")) - PrintcapFormat = PRINTCAP_PLIST; - else if (!_cups_strcasecmp(value, "solaris")) - PrintcapFormat = PRINTCAP_SOLARIS; - else - cupsdLogMessage(CUPSD_LOG_WARN, "Unknown PrintcapFormat %s on line %d.", - value, linenum); + cupsdLogMessage(CUPSD_LOG_WARN, "Unknown LogTimeFormat %s on line %d of %s.", + value, linenum, ConfigurationFile); } else if (!_cups_strcasecmp(line, "ServerTokens") && value) { @@ -3002,24 +3305,25 @@ read_configuration(cups_file_t *fp) /* I - File to read from */ uname(&plat); if (!_cups_strcasecmp(value, "ProductOnly")) - cupsdSetString(&ServerHeader, "CUPS"); + cupsdSetString(&ServerHeader, "CUPS IPP"); else if (!_cups_strcasecmp(value, "Major")) - cupsdSetStringf(&ServerHeader, "CUPS/%d", CUPS_VERSION_MAJOR); + cupsdSetStringf(&ServerHeader, "CUPS/%d IPP/2", CUPS_VERSION_MAJOR); else if (!_cups_strcasecmp(value, "Minor")) - cupsdSetStringf(&ServerHeader, "CUPS/%d.%d", CUPS_VERSION_MAJOR, + cupsdSetStringf(&ServerHeader, "CUPS/%d.%d IPP/2.1", CUPS_VERSION_MAJOR, CUPS_VERSION_MINOR); else if (!_cups_strcasecmp(value, "Minimal")) - cupsdSetString(&ServerHeader, CUPS_MINIMAL); + cupsdSetString(&ServerHeader, CUPS_MINIMAL " IPP/2.1"); else if (!_cups_strcasecmp(value, "OS")) - cupsdSetStringf(&ServerHeader, CUPS_MINIMAL " (%s)", plat.sysname); + cupsdSetStringf(&ServerHeader, CUPS_MINIMAL " (%s %s) IPP/2.1", + plat.sysname, plat.release); else if (!_cups_strcasecmp(value, "Full")) - cupsdSetStringf(&ServerHeader, CUPS_MINIMAL " (%s) IPP/2.1", - plat.sysname); + cupsdSetStringf(&ServerHeader, CUPS_MINIMAL " (%s %s; %s) IPP/2.1", + plat.sysname, plat.release, plat.machine); else if (!_cups_strcasecmp(value, "None")) cupsdClearString(&ServerHeader); else - cupsdLogMessage(CUPSD_LOG_WARN, "Unknown ServerTokens %s on line %d.", - value, linenum); + cupsdLogMessage(CUPSD_LOG_WARN, "Unknown ServerTokens %s on line %d of %s.", + value, linenum, ConfigurationFile); } else if (!_cups_strcasecmp(line, "PassEnv") && value) { @@ -3095,202 +3399,230 @@ read_configuration(cups_file_t *fp) /* I - File to read from */ } else cupsdLogMessage(CUPSD_LOG_ERROR, - "Missing value for SetEnv directive on line %d.", - linenum); + "Missing value for SetEnv directive on line %d of %s.", + linenum, ConfigurationFile); } -#ifdef HAVE_SSL - else if (!_cups_strcasecmp(line, "SSLOptions")) + else if (!_cups_strcasecmp(line, "AccessLog") || + !_cups_strcasecmp(line, "CacheDir") || + !_cups_strcasecmp(line, "ConfigFilePerm") || + !_cups_strcasecmp(line, "DataDir") || + !_cups_strcasecmp(line, "DocumentRoot") || + !_cups_strcasecmp(line, "ErrorLog") || + !_cups_strcasecmp(line, "FatalErrors") || + !_cups_strcasecmp(line, "FileDevice") || + !_cups_strcasecmp(line, "FontPath") || + !_cups_strcasecmp(line, "Group") || + !_cups_strcasecmp(line, "LogFilePerm") || + !_cups_strcasecmp(line, "LPDConfigFile") || + !_cups_strcasecmp(line, "PageLog") || + !_cups_strcasecmp(line, "Printcap") || + !_cups_strcasecmp(line, "PrintcapFormat") || + !_cups_strcasecmp(line, "RemoteRoot") || + !_cups_strcasecmp(line, "RequestRoot") || + !_cups_strcasecmp(line, "ServerBin") || + !_cups_strcasecmp(line, "ServerCertificate") || + !_cups_strcasecmp(line, "ServerKey") || + !_cups_strcasecmp(line, "ServerKeychain") || + !_cups_strcasecmp(line, "ServerRoot") || + !_cups_strcasecmp(line, "SMBConfigFile") || + !_cups_strcasecmp(line, "StateDir") || + !_cups_strcasecmp(line, "SystemGroup") || + !_cups_strcasecmp(line, "SystemGroupAuthKey") || + !_cups_strcasecmp(line, "TempDir") || + !_cups_strcasecmp(line, "User")) { - /* - * SSLOptions options - */ - - if (!value || !_cups_strcasecmp(value, "none")) - SSLOptions = CUPSD_SSL_NONE; - else if (!_cups_strcasecmp(value, "noemptyfragments")) - SSLOptions = CUPSD_SSL_NOEMPTY; - else - cupsdLogMessage(CUPSD_LOG_ERROR, - "Unknown value \"%s\" for SSLOptions directive on " - "line %d.", value, linenum); + cupsdLogMessage(CUPSD_LOG_INFO, + "Please move \"%s%s%s\" on line %d of %s to the %s file; " + "this will become an error in a future release.", + line, value ? " " : "", value ? value : "", linenum, + ConfigurationFile, CupsFilesFile); } -#endif /* HAVE_SSL */ else + parse_variable(ConfigurationFile, linenum, line, value, + sizeof(cupsd_vars) / sizeof(cupsd_vars[0]), cupsd_vars); + } + + return (1); +} + + +/* + * 'read_cups_files_conf()' - Read the cups-files.conf configuration file. + */ + +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 */ + char line[HTTP_MAX_BUFFER], /* Line from file */ + *value; /* Value from line */ + struct group *group; /* Group */ + + + /* + * Loop through each line in the file... + */ + + linenum = 0; + + while (cupsFileGetConf(fp, line, sizeof(line), &value, &linenum)) + { + if (!_cups_strcasecmp(line, "FatalErrors")) + FatalErrors = parse_fatal_errors(value); + else if (!_cups_strcasecmp(line, "Group") && value) { /* - * Find a simple variable in the list... + * Group ID to run as... */ - for (i = NUM_VARS, var = variables; i > 0; i --, var ++) - if (!_cups_strcasecmp(line, var->name)) - break; - - if (i == 0) + if (isdigit(value[0])) + Group = (gid_t)atoi(value); + else { - /* - * Unknown directive! Output an error message and continue... - */ + endgrent(); + group = getgrnam(value); - if (!value) - cupsdLogMessage(CUPSD_LOG_ERROR, "Missing value for %s on line %d.", - line, linenum); + if (group != NULL) + Group = group->gr_gid; else - cupsdLogMessage(CUPSD_LOG_ERROR, "Unknown directive %s on line %d.", - line, linenum); - continue; + { + cupsdLogMessage(CUPSD_LOG_ERROR, + "Unknown Group \"%s\" on line %d of %s.", value, + linenum, CupsFilesFile); + if (FatalErrors & CUPSD_FATAL_CONFIG) + return (0); + } } + } + else if (!_cups_strcasecmp(line, "PrintcapFormat") && value) + { + /* + * Format of printcap file? + */ - switch (var->type) + if (!_cups_strcasecmp(value, "bsd")) + PrintcapFormat = PRINTCAP_BSD; + else if (!_cups_strcasecmp(value, "plist")) + PrintcapFormat = PRINTCAP_PLIST; + else if (!_cups_strcasecmp(value, "solaris")) + PrintcapFormat = PRINTCAP_SOLARIS; + else { - case CUPSD_VARTYPE_INTEGER : - if (!value) - cupsdLogMessage(CUPSD_LOG_ERROR, - "Missing integer value for %s on line %d.", - line, linenum); - else if (!isdigit(*value & 255)) - cupsdLogMessage(CUPSD_LOG_ERROR, - "Bad integer value for %s on line %d.", - line, linenum); - else - { - int n; /* Number */ - char *units; /* Units */ - - n = strtol(value, &units, 0); - - if (units && *units) - { - if (tolower(units[0] & 255) == 'g') - n *= 1024 * 1024 * 1024; - else if (tolower(units[0] & 255) == 'm') - n *= 1024 * 1024; - else if (tolower(units[0] & 255) == 'k') - n *= 1024; - else if (tolower(units[0] & 255) == 't') - n *= 262144; - else - { - cupsdLogMessage(CUPSD_LOG_ERROR, - "Unknown integer value for %s on line %d.", - line, linenum); - break; - } - } - - if (n < 0) - cupsdLogMessage(CUPSD_LOG_ERROR, - "Bad negative integer value for %s on line %d.", - line, linenum); - else - *((int *)var->ptr) = n; - } - break; + cupsdLogMessage(CUPSD_LOG_ERROR, + "Unknown PrintcapFormat \"%s\" on line %d of %s.", + value, linenum, CupsFilesFile); + if (FatalErrors & CUPSD_FATAL_CONFIG) + return (0); + } + } + else if (!_cups_strcasecmp(line, "Sandboxing") && value) + { + /* + * Level of sandboxing? + */ - case CUPSD_VARTYPE_TIME : - if (!value) - cupsdLogMessage(CUPSD_LOG_ERROR, - "Missing time interval value for %s on line %d.", - line, linenum); - else if (!_cups_strncasecmp(line, "PreserveJob", 11) && - (!_cups_strcasecmp(value, "true") || - !_cups_strcasecmp(value, "on") || - !_cups_strcasecmp(value, "enabled") || - !_cups_strcasecmp(value, "yes"))) - *((int *)var->ptr) = INT_MAX; - else if (!_cups_strcasecmp(value, "false") || - !_cups_strcasecmp(value, "off") || - !_cups_strcasecmp(value, "disabled") || - !_cups_strcasecmp(value, "no")) - *((int *)var->ptr) = 0; - else if (!isdigit(*value & 255)) - cupsdLogMessage(CUPSD_LOG_ERROR, - "Unknown time interval value for %s on line %d.", - line, linenum); - else - { - double n; /* Number */ - char *units; /* Units */ - - n = strtod(value, &units); - - if (units && *units) - { - if (tolower(units[0] & 255) == 'w') - n *= 7 * 24 * 60 * 60; - else if (tolower(units[0] & 255) == 'd') - n *= 24 * 60 * 60; - else if (tolower(units[0] & 255) == 'h') - n *= 60 * 60; - else if (tolower(units[0] & 255) == 'm') - n *= 60; - else - { - cupsdLogMessage(CUPSD_LOG_ERROR, - "Unknown time interval value for %s on line " - "%d.", line, linenum); - break; - } - } - - if (n < 0.0 || n > INT_MAX) - cupsdLogMessage(CUPSD_LOG_ERROR, - "Bad time value for %s on line %d.", - line, linenum); - else - *((int *)var->ptr) = (int)n; - } - break; + if (!_cups_strcasecmp(value, "off") && getuid()) + { + Sandboxing = CUPSD_SANDBOXING_OFF; + cupsdLogMessage(CUPSD_LOG_WARN, "Disabling sandboxing is not recommended (line %d of %s)", linenum, CupsFilesFile); + } + else if (!_cups_strcasecmp(value, "relaxed")) + Sandboxing = CUPSD_SANDBOXING_RELAXED; + else if (!_cups_strcasecmp(value, "strict")) + Sandboxing = CUPSD_SANDBOXING_STRICT; + else + { + cupsdLogMessage(CUPSD_LOG_ERROR, + "Unknown Sandboxing \"%s\" on line %d of %s.", + value, linenum, CupsFilesFile); + if (FatalErrors & CUPSD_FATAL_CONFIG) + return (0); + } + } + else if (!_cups_strcasecmp(line, "SystemGroup") && value) + { + /* + * SystemGroup (admin) group(s)... + */ - case CUPSD_VARTYPE_BOOLEAN : - if (!value) - cupsdLogMessage(CUPSD_LOG_ERROR, - "Missing boolean value for %s on line %d.", - line, linenum); - else if (!_cups_strcasecmp(value, "true") || - !_cups_strcasecmp(value, "on") || - !_cups_strcasecmp(value, "enabled") || - !_cups_strcasecmp(value, "yes") || - atoi(value) != 0) - *((int *)var->ptr) = TRUE; - else if (!_cups_strcasecmp(value, "false") || - !_cups_strcasecmp(value, "off") || - !_cups_strcasecmp(value, "disabled") || - !_cups_strcasecmp(value, "no") || - !_cups_strcasecmp(value, "0")) - *((int *)var->ptr) = FALSE; - else - cupsdLogMessage(CUPSD_LOG_ERROR, - "Unknown boolean value %s on line %d.", - value, linenum); - break; + if (!parse_groups(value)) + { + cupsdLogMessage(CUPSD_LOG_ERROR, + "Unknown SystemGroup \"%s\" on line %d of %s.", value, + linenum, CupsFilesFile); + if (FatalErrors & CUPSD_FATAL_CONFIG) + return (0); + } + } + else if (!_cups_strcasecmp(line, "User") && value) + { + /* + * User ID to run as... + */ - case CUPSD_VARTYPE_PATHNAME : - if (!value) - { - cupsdLogMessage(CUPSD_LOG_ERROR, - "Missing pathname value for %s on line %d.", - line, linenum); - break; - } + if (isdigit(value[0] & 255)) + { + int uid = atoi(value); - if (value[0] == '/') - strlcpy(temp, value, sizeof(temp)); - else - snprintf(temp, sizeof(temp), "%s/%s", ServerRoot, value); + if (!uid) + { + cupsdLogMessage(CUPSD_LOG_ERROR, + "Will not use User 0 as specified on line %d of %s " + "for security reasons. You must use a non-" + "privileged account instead.", + linenum, CupsFilesFile); + if (FatalErrors & CUPSD_FATAL_CONFIG) + return (0); + } + else + User = (uid_t)atoi(value); + } + else + { + struct passwd *p; /* Password information */ - if (access(temp, 0)) - { - cupsdLogMessage(CUPSD_LOG_ERROR, - "File or directory for \"%s %s\" on line %d " - "does not exist.", line, value, linenum); - break; - } + endpwent(); + p = getpwnam(value); - case CUPSD_VARTYPE_STRING : - cupsdSetString((char **)var->ptr, value); - break; + if (p) + { + if (!p->pw_uid) + { + cupsdLogMessage(CUPSD_LOG_ERROR, + "Will not use User %s (UID=0) as specified on line " + "%d of %s for security reasons. You must use a " + "non-privileged account instead.", + value, linenum, CupsFilesFile); + if (FatalErrors & CUPSD_FATAL_CONFIG) + return (0); + } + else + User = p->pw_uid; + } + else + { + cupsdLogMessage(CUPSD_LOG_ERROR, + "Unknown User \"%s\" on line %d of %s.", + value, linenum, CupsFilesFile); + if (FatalErrors & CUPSD_FATAL_CONFIG) + return (0); + } } } + else if (!_cups_strcasecmp(line, "ServerCertificate") || + !_cups_strcasecmp(line, "ServerKey")) + { + cupsdLogMessage(CUPSD_LOG_INFO, + "The \"%s\" directive on line %d of %s is no longer " + "supported; this will become an error in a future " + "release.", + line, linenum, CupsFilesFile); + } + else if (!parse_variable(CupsFilesFile, linenum, line, value, + sizeof(cupsfiles_vars) / sizeof(cupsfiles_vars[0]), + cupsfiles_vars) && + (FatalErrors & CUPSD_FATAL_CONFIG)) + return (0); } return (1); @@ -3315,8 +3647,8 @@ read_location(cups_file_t *fp, /* I - Configuration file */ if ((parent = cupsdFindLocation(location)) != NULL) - cupsdLogMessage(CUPSD_LOG_WARN, "Duplicate on line %d.", - location, linenum); + cupsdLogMessage(CUPSD_LOG_WARN, "Duplicate on line %d of %s.", + location, linenum, ConfigurationFile); else if ((parent = cupsdNewLocation(location)) == NULL) return (0); else @@ -3341,7 +3673,7 @@ read_location(cups_file_t *fp, /* I - Configuration file */ { if (!value) { - cupsdLogMessage(CUPSD_LOG_ERROR, "Syntax error on line %d.", linenum); + cupsdLogMessage(CUPSD_LOG_ERROR, "Syntax error on line %d of %s.", linenum, ConfigurationFile); if (FatalErrors & CUPSD_FATAL_CONFIG) return (0); else @@ -3376,8 +3708,8 @@ read_location(cups_file_t *fp, /* I - Configuration file */ else if (!strcmp(value, "TRACE")) loc->limit |= CUPSD_AUTH_LIMIT_TRACE; else - cupsdLogMessage(CUPSD_LOG_WARN, "Unknown request type %s on line %d.", - value, linenum); + cupsdLogMessage(CUPSD_LOG_WARN, "Unknown request type %s on line %d of %s.", + value, linenum, ConfigurationFile); for (value = valptr; isspace(*value & 255); value ++); } @@ -3392,15 +3724,15 @@ read_location(cups_file_t *fp, /* I - Configuration file */ loc = parent; else if (!value) { - cupsdLogMessage(CUPSD_LOG_ERROR, "Missing value on line %d.", linenum); + cupsdLogMessage(CUPSD_LOG_ERROR, "Missing value on line %d of %s.", linenum, ConfigurationFile); if (FatalErrors & CUPSD_FATAL_CONFIG) return (0); } else if (!parse_aaa(loc, line, value, linenum)) { cupsdLogMessage(CUPSD_LOG_ERROR, - "Unknown Location directive %s on line %d.", - line, linenum); + "Unknown Location directive %s on line %d of %s.", + line, linenum, ConfigurationFile); if (FatalErrors & CUPSD_FATAL_CONFIG) return (0); } @@ -3439,8 +3771,8 @@ read_policy(cups_file_t *fp, /* I - Configuration file */ */ if ((pol = cupsdFindPolicy(policy)) != NULL) - cupsdLogMessage(CUPSD_LOG_WARN, "Duplicate on line %d.", - policy, linenum); + cupsdLogMessage(CUPSD_LOG_WARN, "Duplicate on line %d of %s.", + policy, linenum, ConfigurationFile); else if ((pol = cupsdAddPolicy(policy)) == NULL) return (0); @@ -3461,8 +3793,8 @@ read_policy(cups_file_t *fp, /* I - Configuration file */ { if (op) cupsdLogMessage(CUPSD_LOG_WARN, - "Missing before on line %d.", - linenum); + "Missing before on line %d of %s.", + linenum, ConfigurationFile); set_policy_defaults(pol); @@ -3472,7 +3804,7 @@ read_policy(cups_file_t *fp, /* I - Configuration file */ { if (!value) { - cupsdLogMessage(CUPSD_LOG_ERROR, "Syntax error on line %d.", linenum); + cupsdLogMessage(CUPSD_LOG_ERROR, "Syntax error on line %d of %s.", linenum, ConfigurationFile); if (FatalErrors & CUPSD_FATAL_CONFIG) return (0); else @@ -3498,15 +3830,15 @@ read_policy(cups_file_t *fp, /* I - Configuration file */ 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.", - value, linenum); + "Bad IPP operation name \"%s\" on line %d of %s.", + value, linenum, ConfigurationFile); else num_ops ++; } else cupsdLogMessage(CUPSD_LOG_ERROR, - "Too many operations listed on line %d.", - linenum); + "Too many operations listed on line %d of %s.", + linenum, ConfigurationFile); for (value = valptr; isspace(*value & 255); value ++); } @@ -3547,7 +3879,7 @@ read_policy(cups_file_t *fp, /* I - Configuration file */ } else if (!value) { - cupsdLogMessage(CUPSD_LOG_ERROR, "Missing value on line %d.", linenum); + cupsdLogMessage(CUPSD_LOG_ERROR, "Missing value on line %d of %s.", linenum, ConfigurationFile); if (FatalErrors & CUPSD_FATAL_CONFIG) return (0); } @@ -3560,7 +3892,7 @@ read_policy(cups_file_t *fp, /* I - Configuration file */ { cupsdLogMessage(CUPSD_LOG_ERROR, "%s directive must appear outside ... " - "on line %d.", line, linenum); + "on line %d of %s.", line, linenum, ConfigurationFile); if (FatalErrors & CUPSD_FATAL_CONFIG) return (0); } @@ -3658,16 +3990,16 @@ read_policy(cups_file_t *fp, /* I - Configuration file */ else if (!op) { cupsdLogMessage(CUPSD_LOG_ERROR, - "Missing directive before %s on line %d.", - line, linenum); + "Missing directive before %s on line %d of %s.", + line, linenum, ConfigurationFile); if (FatalErrors & CUPSD_FATAL_CONFIG) return (0); } else if (!parse_aaa(op, line, value, linenum)) { cupsdLogMessage(CUPSD_LOG_ERROR, - "Unknown Policy Limit directive %s on line %d.", - line, linenum); + "Unknown Policy Limit directive %s on line %d of %s.", + line, linenum, ConfigurationFile); if (FatalErrors & CUPSD_FATAL_CONFIG) return (0); @@ -3696,121 +4028,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 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); } /* @@ -3820,18 +4137,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"); @@ -3840,18 +4153,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"); @@ -3859,8 +4168,3 @@ set_policy_defaults(cupsd_policy_t *pol)/* I - Policy */ cupsdAddString(&(pol->sub_attrs), "notify-user-data"); } } - - -/* - * End of "$Id: conf.c 9352 2010-11-06 04:55:26Z mike $". - */