2
* "$Id: conf.c 11201 2013-07-26 21:27:27Z msweet $"
4
* Configuration routines for the CUPS scheduler.
6
* Copyright 2007-2013 by Apple Inc.
7
* Copyright 1997-2007 by Easy Software Products, all rights reserved.
9
* These coded instructions, statements, and computer programs are the
10
* property of Apple Inc. and are protected by Federal copyright
11
* law. Distribution and use rights are outlined in the file "LICENSE.txt"
12
* which should have been included with this file. If this file is
13
* file is missing or damaged, see the license at "http://www.cups.org/".
17
* cupsdAddAlias() - Add a host alias.
18
* cupsdCheckPermissions() - Fix the mode and ownership of a file or
20
* cupsdDefaultAuthType() - Get the default AuthType.
21
* cupsdFreeAliases() - Free all of the alias entries.
22
* cupsdReadConfiguration() - Read the cupsd.conf file.
23
* get_address() - Get an address + port number from a line.
24
* get_addr_and_mask() - Get an IP address and netmask.
25
* mime_error_cb() - Log a MIME error.
26
* parse_aaa() - Parse authentication, authorization, and access
28
* parse_fatal_errors() - Parse FatalErrors values in a string.
29
* parse_groups() - Parse system group names in a string.
30
* parse_protocols() - Parse browse protocols in a string.
31
* parse_variable() - Parse a variable line.
32
* read_cupsd_conf() - Read the cupsd.conf configuration file.
33
* read_cups_files_conf() - Read the cups-files.conf configuration file.
34
* read_location() - Read a <Location path> definition.
35
* read_policy() - Read a <Policy name> definition.
36
* set_policy_defaults() - Set default policy values as needed.
40
* Include necessary headers...
46
#include <sys/utsname.h>
51
#endif /* HAVE_LIBPAPER */
55
* Possibly missing network definitions...
59
# define INADDR_NONE 0xffffffff
60
#endif /* !INADDR_NONE */
64
* Configuration variable structure...
69
CUPSD_VARTYPE_INTEGER, /* Integer option */
70
CUPSD_VARTYPE_TIME, /* Time interval option */
71
CUPSD_VARTYPE_STRING, /* String option */
72
CUPSD_VARTYPE_BOOLEAN, /* Boolean option */
73
CUPSD_VARTYPE_PATHNAME /* File/directory name option */
78
const char *name; /* Name of variable */
79
void *ptr; /* Pointer to variable */
80
cupsd_vartype_t type; /* Type (int, string, address) */
88
static const cupsd_var_t cupsd_vars[] =
90
{ "AutoPurgeJobs", &JobAutoPurge, CUPSD_VARTYPE_BOOLEAN },
91
#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
92
{ "BrowseDNSSDSubTypes", &DNSSDSubTypes, CUPSD_VARTYPE_STRING },
93
#endif /* HAVE_DNSSD || HAVE_AVAHI */
94
{ "BrowseWebIF", &BrowseWebIF, CUPSD_VARTYPE_BOOLEAN },
95
{ "Browsing", &Browsing, CUPSD_VARTYPE_BOOLEAN },
96
{ "Classification", &Classification, CUPSD_VARTYPE_STRING },
97
{ "ClassifyOverride", &ClassifyOverride, CUPSD_VARTYPE_BOOLEAN },
98
{ "DefaultLanguage", &DefaultLanguage, CUPSD_VARTYPE_STRING },
99
{ "DefaultLeaseDuration", &DefaultLeaseDuration, CUPSD_VARTYPE_TIME },
100
{ "DefaultPaperSize", &DefaultPaperSize, CUPSD_VARTYPE_STRING },
101
{ "DefaultPolicy", &DefaultPolicy, CUPSD_VARTYPE_STRING },
102
{ "DefaultShared", &DefaultShared, CUPSD_VARTYPE_BOOLEAN },
103
{ "DirtyCleanInterval", &DirtyCleanInterval, CUPSD_VARTYPE_TIME },
104
{ "ErrorPolicy", &ErrorPolicy, CUPSD_VARTYPE_STRING },
105
{ "FilterLimit", &FilterLimit, CUPSD_VARTYPE_INTEGER },
106
{ "FilterNice", &FilterNice, CUPSD_VARTYPE_INTEGER },
108
{ "GSSServiceName", &GSSServiceName, CUPSD_VARTYPE_STRING },
109
#endif /* HAVE_GSSAPI */
110
{ "JobKillDelay", &JobKillDelay, CUPSD_VARTYPE_TIME },
111
{ "JobRetryLimit", &JobRetryLimit, CUPSD_VARTYPE_INTEGER },
112
{ "JobRetryInterval", &JobRetryInterval, CUPSD_VARTYPE_TIME },
113
{ "KeepAliveTimeout", &KeepAliveTimeout, CUPSD_VARTYPE_TIME },
114
{ "KeepAlive", &KeepAlive, CUPSD_VARTYPE_BOOLEAN },
116
{ "LaunchdTimeout", &LaunchdTimeout, CUPSD_VARTYPE_TIME },
117
#endif /* HAVE_LAUNCHD */
118
{ "LimitRequestBody", &MaxRequestSize, CUPSD_VARTYPE_INTEGER },
119
{ "ListenBackLog", &ListenBackLog, CUPSD_VARTYPE_INTEGER },
120
{ "LogDebugHistory", &LogDebugHistory, CUPSD_VARTYPE_INTEGER },
121
{ "MaxActiveJobs", &MaxActiveJobs, CUPSD_VARTYPE_INTEGER },
122
{ "MaxClients", &MaxClients, CUPSD_VARTYPE_INTEGER },
123
{ "MaxClientsPerHost", &MaxClientsPerHost, CUPSD_VARTYPE_INTEGER },
124
{ "MaxCopies", &MaxCopies, CUPSD_VARTYPE_INTEGER },
125
{ "MaxEvents", &MaxEvents, CUPSD_VARTYPE_INTEGER },
126
{ "MaxHoldTime", &MaxHoldTime, CUPSD_VARTYPE_TIME },
127
{ "MaxJobs", &MaxJobs, CUPSD_VARTYPE_INTEGER },
128
{ "MaxJobsPerPrinter", &MaxJobsPerPrinter, CUPSD_VARTYPE_INTEGER },
129
{ "MaxJobsPerUser", &MaxJobsPerUser, CUPSD_VARTYPE_INTEGER },
130
{ "MaxJobTime", &MaxJobTime, CUPSD_VARTYPE_INTEGER },
131
{ "MaxLeaseDuration", &MaxLeaseDuration, CUPSD_VARTYPE_TIME },
132
{ "MaxLogSize", &MaxLogSize, CUPSD_VARTYPE_INTEGER },
133
{ "MaxRequestSize", &MaxRequestSize, CUPSD_VARTYPE_INTEGER },
134
{ "MaxSubscriptions", &MaxSubscriptions, CUPSD_VARTYPE_INTEGER },
135
{ "MaxSubscriptionsPerJob", &MaxSubscriptionsPerJob, CUPSD_VARTYPE_INTEGER },
136
{ "MaxSubscriptionsPerPrinter",&MaxSubscriptionsPerPrinter, CUPSD_VARTYPE_INTEGER },
137
{ "MaxSubscriptionsPerUser", &MaxSubscriptionsPerUser, CUPSD_VARTYPE_INTEGER },
138
{ "MultipleOperationTimeout", &MultipleOperationTimeout, CUPSD_VARTYPE_TIME },
139
{ "PageLogFormat", &PageLogFormat, CUPSD_VARTYPE_STRING },
140
{ "PreserveJobFiles", &JobFiles, CUPSD_VARTYPE_TIME },
141
{ "PreserveJobHistory", &JobHistory, CUPSD_VARTYPE_TIME },
142
{ "ReloadTimeout", &ReloadTimeout, CUPSD_VARTYPE_TIME },
143
{ "RIPCache", &RIPCache, CUPSD_VARTYPE_STRING },
144
{ "RootCertDuration", &RootCertDuration, CUPSD_VARTYPE_TIME },
145
{ "ServerAdmin", &ServerAdmin, CUPSD_VARTYPE_STRING },
146
{ "ServerName", &ServerName, CUPSD_VARTYPE_STRING },
147
{ "StrictConformance", &StrictConformance, CUPSD_VARTYPE_BOOLEAN },
148
{ "Timeout", &Timeout, CUPSD_VARTYPE_TIME },
149
{ "WebInterface", &WebInterface, CUPSD_VARTYPE_BOOLEAN }
151
static const cupsd_var_t cupsfiles_vars[] =
153
{ "AccessLog", &AccessLog, CUPSD_VARTYPE_STRING },
154
{ "CacheDir", &CacheDir, CUPSD_VARTYPE_STRING },
155
{ "ConfigFilePerm", &ConfigFilePerm, CUPSD_VARTYPE_INTEGER },
156
{ "DataDir", &DataDir, CUPSD_VARTYPE_STRING },
157
{ "DocumentRoot", &DocumentRoot, CUPSD_VARTYPE_STRING },
158
{ "ErrorLog", &ErrorLog, CUPSD_VARTYPE_STRING },
159
{ "FileDevice", &FileDevice, CUPSD_VARTYPE_BOOLEAN },
160
{ "FontPath", &FontPath, CUPSD_VARTYPE_STRING },
161
{ "LogFilePerm", &LogFilePerm, CUPSD_VARTYPE_INTEGER },
162
{ "LPDConfigFile", &LPDConfigFile, CUPSD_VARTYPE_STRING },
163
{ "PageLog", &PageLog, CUPSD_VARTYPE_STRING },
164
{ "Printcap", &Printcap, CUPSD_VARTYPE_STRING },
165
{ "RemoteRoot", &RemoteRoot, CUPSD_VARTYPE_STRING },
166
{ "RequestRoot", &RequestRoot, CUPSD_VARTYPE_STRING },
167
{ "ServerBin", &ServerBin, CUPSD_VARTYPE_PATHNAME },
169
{ "ServerCertificate", &ServerCertificate, CUPSD_VARTYPE_PATHNAME },
170
# if defined(HAVE_LIBSSL) || defined(HAVE_GNUTLS)
171
{ "ServerKey", &ServerKey, CUPSD_VARTYPE_PATHNAME },
172
# endif /* HAVE_LIBSSL || HAVE_GNUTLS */
173
#endif /* HAVE_SSL */
174
{ "ServerRoot", &ServerRoot, CUPSD_VARTYPE_PATHNAME },
175
{ "SMBConfigFile", &SMBConfigFile, CUPSD_VARTYPE_STRING },
176
{ "StateDir", &StateDir, CUPSD_VARTYPE_STRING },
177
{ "SyncOnClose", &SyncOnClose, CUPSD_VARTYPE_BOOLEAN },
178
#ifdef HAVE_AUTHORIZATION_H
179
{ "SystemGroupAuthKey", &SystemGroupAuthKey, CUPSD_VARTYPE_STRING },
180
#endif /* HAVE_AUTHORIZATION_H */
181
{ "TempDir", &TempDir, CUPSD_VARTYPE_PATHNAME },
182
{ "PidFile", &PidFile, CUPSD_VARTYPE_STRING }
185
static int default_auth_type = CUPSD_AUTH_AUTO;
186
/* Default AuthType, if not specified */
188
static const unsigned ones[4] =
190
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff
192
static const unsigned zeros[4] =
194
0x00000000, 0x00000000, 0x00000000, 0x00000000
202
static http_addrlist_t *get_address(const char *value, int defport);
203
static int get_addr_and_mask(const char *value, unsigned *ip,
205
static void mime_error_cb(void *ctx, const char *message);
206
static int parse_aaa(cupsd_location_t *loc, char *line,
207
char *value, int linenum);
208
static int parse_fatal_errors(const char *s);
209
static int parse_groups(const char *s);
210
static int parse_protocols(const char *s);
211
static int parse_variable(const char *filename, int linenum,
212
const char *line, const char *value,
214
const cupsd_var_t *vars);
215
static int read_cupsd_conf(cups_file_t *fp);
216
static int read_cups_files_conf(cups_file_t *fp);
217
static int read_location(cups_file_t *fp, char *name, int linenum);
218
static int read_policy(cups_file_t *fp, char *name, int linenum);
219
static void set_policy_defaults(cupsd_policy_t *pol);
223
* 'cupsdAddAlias()' - Add a host alias.
227
cupsdAddAlias(cups_array_t *aliases, /* I - Array of aliases */
228
const char *name) /* I - Name to add */
230
cupsd_alias_t *a; /* New alias */
231
size_t namelen; /* Length of name */
234
namelen = strlen(name);
236
if ((a = (cupsd_alias_t *)malloc(sizeof(cupsd_alias_t) + namelen)) == NULL)
239
a->namelen = namelen;
240
memcpy(a->name, name, namelen + 1); /* OK since a->name is allocated */
242
cupsArrayAdd(aliases, a);
247
* 'cupsdCheckPermissions()' - Fix the mode and ownership of a file or directory.
250
int /* O - 0 on success, -1 on error, 1 on warning */
251
cupsdCheckPermissions(
252
const char *filename, /* I - File/directory name */
253
const char *suffix, /* I - Additional file/directory name */
254
int mode, /* I - Permissions */
255
int user, /* I - Owner */
256
int group, /* I - Group */
257
int is_dir, /* I - 1 = directory, 0 = file */
258
int create_dir) /* I - 1 = create directory, -1 = create w/o logging, 0 = not */
260
int dir_created = 0; /* Did we create a directory? */
261
char pathname[1024]; /* File name with prefix */
262
struct stat fileinfo; /* Stat buffer */
263
int is_symlink; /* Is "filename" a symlink? */
267
* Prepend the given root to the filename before testing it...
272
snprintf(pathname, sizeof(pathname), "%s/%s", filename, suffix);
277
* See if we can stat the file/directory...
280
if (lstat(filename, &fileinfo))
282
if (errno == ENOENT && create_dir)
285
cupsdLogMessage(CUPSD_LOG_DEBUG, "Creating missing directory \"%s\"",
288
if (mkdir(filename, mode))
291
cupsdLogMessage(CUPSD_LOG_ERROR,
292
"Unable to create directory \"%s\" - %s", filename,
295
syslog(LOG_ERR, "Unable to create directory \"%s\" - %s", filename,
302
fileinfo.st_mode = mode | S_IFDIR;
305
return (create_dir ? -1 : 1);
308
if ((is_symlink = S_ISLNK(fileinfo.st_mode)) != 0)
310
if (stat(filename, &fileinfo))
312
cupsdLogMessage(CUPSD_LOG_ERROR, "\"%s\" is a bad symlink - %s",
313
filename, strerror(errno));
319
* Make sure it's a regular file or a directory as needed...
322
if (!dir_created && !is_dir && !S_ISREG(fileinfo.st_mode))
324
cupsdLogMessage(CUPSD_LOG_ERROR, "\"%s\" is not a regular file.", filename);
328
if (!dir_created && is_dir && !S_ISDIR(fileinfo.st_mode))
331
cupsdLogMessage(CUPSD_LOG_ERROR, "\"%s\" is not a directory.", filename);
333
syslog(LOG_ERR, "\"%s\" is not a directory.", filename);
339
* If the filename is a symlink, do not change permissions (STR #2937)...
346
* Fix owner, group, and mode as needed...
349
if (dir_created || fileinfo.st_uid != user || fileinfo.st_gid != group)
352
cupsdLogMessage(CUPSD_LOG_DEBUG, "Repairing ownership of \"%s\"",
355
if (chown(filename, user, group) && !getuid())
358
cupsdLogMessage(CUPSD_LOG_ERROR,
359
"Unable to change ownership of \"%s\" - %s", filename,
362
syslog(LOG_ERR, "Unable to change ownership of \"%s\" - %s", filename,
369
if (dir_created || (fileinfo.st_mode & 07777) != mode)
372
cupsdLogMessage(CUPSD_LOG_DEBUG, "Repairing access permissions of \"%s\"",
375
if (chmod(filename, mode))
378
cupsdLogMessage(CUPSD_LOG_ERROR,
379
"Unable to change permissions of \"%s\" - %s", filename,
382
syslog(LOG_ERR, "Unable to change permissions of \"%s\" - %s", filename,
390
* Everything is OK...
398
* 'cupsdDefaultAuthType()' - Get the default AuthType.
400
* When the default_auth_type is "auto", this function tries to get the GSS
401
* credentials for the server. If that succeeds we use Kerberos authentication,
402
* otherwise we do a fallback to Basic authentication against the local user
406
int /* O - Default AuthType value */
407
cupsdDefaultAuthType(void)
410
OM_uint32 major_status, /* Major status code */
411
minor_status; /* Minor status code */
412
gss_name_t server_name; /* Server name */
413
gss_buffer_desc token = GSS_C_EMPTY_BUFFER;
414
/* Service name token */
415
char buf[1024]; /* Service name buffer */
416
#endif /* HAVE_GSSAPI */
420
* If we have already determined the correct default AuthType, use it...
423
if (default_auth_type != CUPSD_AUTH_AUTO)
424
return (default_auth_type);
429
* If the weak-linked GSSAPI/Kerberos library is not present, don't try
433
if (gss_init_sec_context == NULL)
434
return (default_auth_type = CUPSD_AUTH_BASIC);
435
# endif /* __APPLE__ */
438
* Try to obtain the server's GSS credentials (GSSServiceName@servername). If
439
* that fails we must use Basic...
442
snprintf(buf, sizeof(buf), "%s@%s", GSSServiceName, ServerName);
445
token.length = strlen(buf);
446
server_name = GSS_C_NO_NAME;
447
major_status = gss_import_name(&minor_status, &token,
448
GSS_C_NT_HOSTBASED_SERVICE,
451
memset(&token, 0, sizeof(token));
453
if (GSS_ERROR(major_status))
455
cupsdLogGSSMessage(CUPSD_LOG_DEBUG, major_status, minor_status,
456
"cupsdDefaultAuthType: gss_import_name(%s) failed", buf);
457
return (default_auth_type = CUPSD_AUTH_BASIC);
460
major_status = gss_display_name(&minor_status, server_name, &token, NULL);
462
if (GSS_ERROR(major_status))
464
cupsdLogGSSMessage(CUPSD_LOG_DEBUG, major_status, minor_status,
465
"cupsdDefaultAuthType: gss_display_name(%s) failed",
467
return (default_auth_type = CUPSD_AUTH_BASIC);
470
cupsdLogMessage(CUPSD_LOG_DEBUG,
471
"cupsdDefaultAuthType: Attempting to acquire Kerberos "
472
"credentials for %s...", (char *)token.value);
474
ServerCreds = GSS_C_NO_CREDENTIAL;
475
major_status = gss_acquire_cred(&minor_status, server_name, GSS_C_INDEFINITE,
476
GSS_C_NO_OID_SET, GSS_C_ACCEPT,
477
&ServerCreds, NULL, NULL);
478
if (GSS_ERROR(major_status))
480
cupsdLogGSSMessage(CUPSD_LOG_DEBUG, major_status, minor_status,
481
"cupsdDefaultAuthType: gss_acquire_cred(%s) failed",
482
(char *)token.value);
483
gss_release_name(&minor_status, &server_name);
484
gss_release_buffer(&minor_status, &token);
485
return (default_auth_type = CUPSD_AUTH_BASIC);
488
cupsdLogMessage(CUPSD_LOG_DEBUG,
489
"cupsdDefaultAuthType: Kerberos credentials acquired "
490
"successfully for %s.", (char *)token.value);
492
gss_release_name(&minor_status, &server_name);
493
gss_release_buffer(&minor_status, &token);
497
return (default_auth_type = CUPSD_AUTH_NEGOTIATE);
501
* No Kerberos support compiled in so just use Basic all the time...
504
return (default_auth_type = CUPSD_AUTH_BASIC);
505
#endif /* HAVE_GSSAPI */
510
* 'cupsdFreeAliases()' - Free all of the alias entries.
514
cupsdFreeAliases(cups_array_t *aliases) /* I - Array of aliases */
516
cupsd_alias_t *a; /* Current alias */
519
for (a = (cupsd_alias_t *)cupsArrayFirst(aliases);
521
a = (cupsd_alias_t *)cupsArrayNext(aliases))
524
cupsArrayDelete(aliases);
529
* 'cupsdReadConfiguration()' - Read the cupsd.conf file.
532
int /* O - 1 on success, 0 otherwise */
533
cupsdReadConfiguration(void)
535
int i; /* Looping var */
536
cups_file_t *fp; /* Configuration file */
537
int status; /* Return status */
538
char temp[1024], /* Temporary buffer */
539
mimedir[1024], /* MIME directory */
540
*slash; /* Directory separator */
541
cups_lang_t *language; /* Language */
542
struct passwd *user; /* Default user */
543
struct group *group; /* Default group */
544
char *old_serverroot, /* Old ServerRoot */
545
*old_requestroot; /* Old RequestRoot */
546
int old_remote_port; /* Old RemotePort */
547
const char *tmpdir; /* TMPDIR environment variable */
548
struct stat tmpinfo; /* Temporary directory info */
549
cupsd_policy_t *p; /* Policy */
553
* Save the old root paths...
556
old_serverroot = NULL;
557
cupsdSetString(&old_serverroot, ServerRoot);
558
old_requestroot = NULL;
559
cupsdSetString(&old_requestroot, RequestRoot);
562
* Reset the server configuration data...
565
cupsdDeleteAllLocations();
567
cupsdDeleteAllListeners();
569
old_remote_port = RemotePort;
576
cupsdFreeAliases(ServerAlias);
579
cupsdClearString(&ServerName);
580
cupsdClearString(&ServerAdmin);
581
cupsdSetString(&ServerBin, CUPS_SERVERBIN);
582
cupsdSetString(&RequestRoot, CUPS_REQUESTS);
583
cupsdSetString(&CacheDir, CUPS_CACHEDIR);
584
cupsdSetString(&DataDir, CUPS_DATADIR);
585
cupsdSetString(&DocumentRoot, CUPS_DOCROOT);
586
cupsdSetString(&AccessLog, CUPS_LOGDIR "/access_log");
587
cupsdClearString(&ErrorLog);
588
cupsdSetString(&PageLog, CUPS_LOGDIR "/page_log");
589
cupsdSetString(&PageLogFormat,
590
"%p %u %j %T %P %C %{job-billing} "
591
"%{job-originating-host-name} %{job-name} %{media} %{sides}");
592
cupsdSetString(&Printcap, CUPS_DEFAULT_PRINTCAP);
593
cupsdSetString(&FontPath, CUPS_FONTPATH);
594
cupsdSetString(&RemoteRoot, "remroot");
595
cupsdSetStringf(&ServerHeader, "CUPS/%d.%d IPP/2.1", CUPS_VERSION_MAJOR,
597
cupsdSetString(&StateDir, CUPS_STATEDIR);
598
cupsdSetString(&PidFile, "/var/run/cups/cupsd.pid");
600
if (!strcmp(CUPS_DEFAULT_PRINTCAP, "/etc/printers.conf"))
601
PrintcapFormat = PRINTCAP_SOLARIS;
602
else if (!strcmp(CUPS_DEFAULT_PRINTCAP,
603
"/Library/Preferences/org.cups.printers.plist"))
604
PrintcapFormat = PRINTCAP_PLIST;
606
PrintcapFormat = PRINTCAP_BSD;
608
strlcpy(temp, ConfigurationFile, sizeof(temp));
609
if ((slash = strrchr(temp, '/')) != NULL)
612
cupsdSetString(&ServerRoot, temp);
614
cupsdClearString(&Classification);
615
ClassifyOverride = 0;
619
cupsdSetString(&ServerCertificate, "/Library/Keychains/System.keychain");
621
cupsdSetString(&ServerCertificate, "ssl/server.crt");
622
cupsdSetString(&ServerKey, "ssl/server.key");
623
# endif /* HAVE_CDSASSL */
624
#endif /* HAVE_SSL */
626
language = cupsLangDefault();
628
if (!strcmp(language->language, "C") || !strcmp(language->language, "POSIX"))
629
cupsdSetString(&DefaultLanguage, "en");
631
cupsdSetString(&DefaultLanguage, language->language);
633
cupsdClearString(&DefaultPaperSize);
635
cupsdSetString(&RIPCache, "128m");
637
cupsdSetString(&TempDir, NULL);
640
cupsdSetString(&GSSServiceName, CUPS_DEFAULT_GSSSERVICENAME);
644
OM_uint32 minor_status; /* Minor status code */
646
gss_release_cred(&minor_status, &ServerCreds);
651
ServerCreds = GSS_C_NO_CREDENTIAL;
652
#endif /* HAVE_GSSAPI */
655
* Find the default user...
658
if ((user = getpwnam(CUPS_DEFAULT_USER)) != NULL)
663
* Use the (historical) NFS nobody user ID (-2 as a 16-bit twos-
664
* complement number...)
673
* Find the default group...
676
group = getgrnam(CUPS_DEFAULT_GROUP);
680
Group = group->gr_gid;
684
* Fallback to group "nobody"...
687
group = getgrnam("nobody");
691
Group = group->gr_gid;
695
* Use the (historical) NFS nobody group ID (-2 as a 16-bit twos-
696
* complement number...)
707
AccessLogLevel = CUPSD_ACCESSLOG_ACTIONS;
708
ConfigFilePerm = CUPS_DEFAULT_CONFIG_FILE_PERM;
709
FatalErrors = parse_fatal_errors(CUPS_DEFAULT_FATAL_ERRORS);
710
default_auth_type = CUPSD_AUTH_BASIC;
712
DefaultEncryption = HTTP_ENCRYPT_REQUIRED;
713
SSLOptions = CUPSD_SSL_NONE;
714
#endif /* HAVE_SSL */
715
DirtyCleanInterval = DEFAULT_KEEPALIVE;
716
JobKillDelay = DEFAULT_TIMEOUT;
718
JobRetryInterval = 300;
723
HostNameLookups = FALSE;
725
KeepAliveTimeout = DEFAULT_KEEPALIVE;
726
ListenBackLog = SOMAXCONN;
727
LogDebugHistory = 99999;
728
LogFilePerm = CUPS_DEFAULT_LOG_FILE_PERM;
729
LogLevel = CUPSD_LOG_WARN;
730
LogTimeFormat = CUPSD_TIME_STANDARD;
732
MaxClientsPerHost = 0;
733
MaxLogSize = 1024 * 1024;
735
MultipleOperationTimeout = DEFAULT_TIMEOUT;
737
ReloadTimeout = DEFAULT_KEEPALIVE;
738
RootCertDuration = 300;
739
StrictConformance = FALSE;
741
Timeout = DEFAULT_TIMEOUT;
742
WebInterface = CUPS_DEFAULT_WEBIF;
744
BrowseLocalProtocols = parse_protocols(CUPS_DEFAULT_BROWSE_LOCAL_PROTOCOLS);
746
Browsing = CUPS_DEFAULT_BROWSING;
747
DefaultShared = CUPS_DEFAULT_DEFAULT_SHARED;
749
#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
750
cupsdSetString(&DNSSDSubTypes, "_cups,_print,_universal");
751
#endif /* HAVE_DNSSD || HAVE_AVAHI */
753
cupsdSetString(&LPDConfigFile, CUPS_DEFAULT_LPD_CONFIG_FILE);
754
cupsdSetString(&SMBConfigFile, CUPS_DEFAULT_SMB_CONFIG_FILE);
756
cupsdSetString(&ErrorPolicy, "stop-printer");
758
JobHistory = DEFAULT_HISTORY;
759
JobFiles = DEFAULT_FILES;
765
MaxJobsPerPrinter = 0;
766
MaxJobTime = 3 * 60 * 60; /* 3 hours */
767
MaxCopies = CUPS_DEFAULT_MAX_COPIES;
769
cupsdDeleteAllPolicies();
770
cupsdClearString(&DefaultPolicy);
772
#ifdef HAVE_AUTHORIZATION_H
773
cupsdSetString(&SystemGroupAuthKey, CUPS_DEFAULT_SYSTEM_AUTHKEY);
774
#endif /* HAVE_AUTHORIZATION_H */
776
MaxSubscriptions = 100;
777
MaxSubscriptionsPerJob = 0;
778
MaxSubscriptionsPerPrinter = 0;
779
MaxSubscriptionsPerUser = 0;
780
DefaultLeaseDuration = 86400;
781
MaxLeaseDuration = 0;
785
#endif /* HAVE_LAUNCHD */
788
* Setup environment variables...
794
* Read the cups-files.conf file...
797
if ((fp = cupsFileOpen(CupsFilesFile, "r")) != NULL)
799
status = read_cups_files_conf(fp);
806
printf("\"%s\" contains errors.\n", CupsFilesFile);
808
syslog(LOG_LPR, "Unable to read \"%s\" due to errors.",
814
else if (errno == ENOENT)
815
cupsdLogMessage(CUPSD_LOG_INFO, "No %s, using defaults.", CupsFilesFile);
818
syslog(LOG_LPR, "Unable to open \"%s\": %s", CupsFilesFile,
824
cupsdSetString(&ErrorLog, CUPS_LOGDIR "/error_log");
827
* Read the cupsd.conf file...
830
if ((fp = cupsFileOpen(ConfigurationFile, "r")) == NULL)
832
syslog(LOG_LPR, "Unable to open \"%s\": %s", ConfigurationFile,
837
status = read_cupsd_conf(fp);
844
printf("\"%s\" contains errors.\n", ConfigurationFile);
846
syslog(LOG_LPR, "Unable to read \"%s\" due to errors.",
854
cupsdLogMessage(CUPSD_LOG_INFO, "Remote access is %s.",
855
RemotePort ? "enabled" : "disabled");
858
BrowseLocalProtocols = 0; /* Disable sharing - no remote access */
861
* See if the ServerName is an IP address...
867
ServerAlias = cupsArrayNew(NULL, NULL);
869
cupsdLogMessage(CUPSD_LOG_DEBUG, "Added auto ServerAlias %s", ServerName);
873
if (gethostname(temp, sizeof(temp)))
875
cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to get hostname: %s",
877
strlcpy(temp, "localhost", sizeof(temp));
880
cupsdSetString(&ServerName, temp);
883
ServerAlias = cupsArrayNew(NULL, NULL);
885
cupsdAddAlias(ServerAlias, temp);
886
cupsdLogMessage(CUPSD_LOG_DEBUG, "Added auto ServerAlias %s", temp);
890
struct hostent *host; /* Host entry to get FQDN */
892
if ((host = gethostbyname(temp)) != NULL)
894
if (_cups_strcasecmp(temp, host->h_name))
896
cupsdSetString(&ServerName, host->h_name);
897
cupsdAddAlias(ServerAlias, host->h_name);
898
cupsdLogMessage(CUPSD_LOG_DEBUG, "Added auto ServerAlias %s",
904
for (i = 0; host->h_aliases[i]; i ++)
905
if (_cups_strcasecmp(temp, host->h_aliases[i]))
907
cupsdAddAlias(ServerAlias, host->h_aliases[i]);
908
cupsdLogMessage(CUPSD_LOG_DEBUG, "Added auto ServerAlias %s",
916
* Make sure we have the base hostname added as an alias, too!
919
if ((slash = strchr(temp, '.')) != NULL)
922
cupsdAddAlias(ServerAlias, temp);
923
cupsdLogMessage(CUPSD_LOG_DEBUG, "Added auto ServerAlias %s", temp);
927
for (slash = ServerName; isdigit(*slash & 255) || *slash == '.'; slash ++);
929
ServerNameIsIP = !*slash;
932
* Make sure ServerAdmin is initialized...
936
cupsdSetStringf(&ServerAdmin, "root@%s", ServerName);
939
* Use the default system group if none was supplied in cupsd.conf...
942
if (NumSystemGroups == 0)
944
if (!parse_groups(CUPS_DEFAULT_SYSTEM_GROUPS))
947
* Find the group associated with GID 0...
954
cupsdSetString(&SystemGroups[0], group->gr_name);
956
cupsdSetString(&SystemGroups[0], "unknown");
958
SystemGroupIDs[0] = 0;
964
* Make sure ConfigFilePerm and LogFilePerm have sane values...
967
ConfigFilePerm &= 0664;
971
* Open the system log for cupsd if necessary...
975
if (!strcmp(AccessLog, "syslog") ||
976
!strcmp(ErrorLog, "syslog") ||
977
!strcmp(PageLog, "syslog"))
978
openlog("cupsd", LOG_PID | LOG_NOWAIT | LOG_NDELAY, LOG_LPR);
979
#endif /* HAVE_VSYSLOG */
982
* Make sure each of the log files exists and gets rotated as necessary...
985
if (strcmp(AccessLog, "syslog"))
986
cupsdCheckLogFile(&AccessFile, AccessLog);
988
if (strcmp(ErrorLog, "syslog"))
989
cupsdCheckLogFile(&ErrorFile, ErrorLog);
991
if (strcmp(PageLog, "syslog"))
992
cupsdCheckLogFile(&PageFile, PageLog);
995
* Log the configuration file that was used...
998
cupsdLogMessage(CUPSD_LOG_INFO, "Loaded configuration file \"%s\"",
1002
* Validate the Group and SystemGroup settings - they cannot be the same,
1003
* otherwise the CGI programs will be able to authenticate as root without
1009
for (i = 0; i < NumSystemGroups; i ++)
1010
if (Group == SystemGroupIDs[i])
1013
if (i < NumSystemGroups)
1016
* Log the error and reset the group to a safe value...
1019
cupsdLogMessage(CUPSD_LOG_NOTICE,
1020
"Group and SystemGroup cannot use the same groups.");
1021
cupsdLogMessage(CUPSD_LOG_INFO, "Resetting Group to \"nobody\"...");
1023
group = getgrnam("nobody");
1027
Group = group->gr_gid;
1031
* Use the (historical) NFS nobody group ID (-2 as a 16-bit twos-
1032
* complement number...)
1041
* Check that we have at least one listen/port line; if not, report this
1042
* as an error and exit!
1045
if (cupsArrayCount(Listeners) == 0)
1051
cupsdLogMessage(CUPSD_LOG_EMERG,
1052
"No valid Listen or Port lines were found in the "
1053
"configuration file.");
1059
cupsdEndProcess(getpid(), 0);
1063
* Set the default locale using the language and charset...
1066
cupsdSetStringf(&DefaultLocale, "%s.UTF-8", DefaultLanguage);
1069
* Update all relative filenames to include the full path from ServerRoot...
1072
if (DocumentRoot[0] != '/')
1073
cupsdSetStringf(&DocumentRoot, "%s/%s", ServerRoot, DocumentRoot);
1075
if (RequestRoot[0] != '/')
1076
cupsdSetStringf(&RequestRoot, "%s/%s", ServerRoot, RequestRoot);
1078
if (ServerBin[0] != '/')
1079
cupsdSetStringf(&ServerBin, "%s/%s", ServerRoot, ServerBin);
1081
if (StateDir[0] != '/')
1082
cupsdSetStringf(&StateDir, "%s/%s", ServerRoot, StateDir);
1084
if (CacheDir[0] != '/')
1085
cupsdSetStringf(&CacheDir, "%s/%s", ServerRoot, CacheDir);
1088
if (ServerCertificate[0] != '/')
1089
cupsdSetStringf(&ServerCertificate, "%s/%s", ServerRoot, ServerCertificate);
1091
if (!strncmp(ServerRoot, ServerCertificate, strlen(ServerRoot)) &&
1092
cupsdCheckPermissions(ServerCertificate, NULL, 0600, RunUser, Group,
1094
(FatalErrors & CUPSD_FATAL_PERMISSIONS))
1097
# if defined(HAVE_LIBSSL) || defined(HAVE_GNUTLS)
1098
if (ServerKey[0] != '/')
1099
cupsdSetStringf(&ServerKey, "%s/%s", ServerRoot, ServerKey);
1101
if (!strncmp(ServerRoot, ServerKey, strlen(ServerRoot)) &&
1102
cupsdCheckPermissions(ServerKey, NULL, 0600, RunUser, Group, 0, 0) < 0 &&
1103
(FatalErrors & CUPSD_FATAL_PERMISSIONS))
1105
# endif /* HAVE_LIBSSL || HAVE_GNUTLS */
1106
#endif /* HAVE_SSL */
1109
* Make sure that directories and config files are owned and
1110
* writable by the user and group in the cupsd.conf file...
1113
snprintf(temp, sizeof(temp), "%s/rss", CacheDir);
1115
if ((cupsdCheckPermissions(RequestRoot, NULL, 0710, RunUser,
1117
cupsdCheckPermissions(CacheDir, NULL, 0775, RunUser,
1119
cupsdCheckPermissions(temp, NULL, 0775, RunUser,
1121
cupsdCheckPermissions(StateDir, NULL, 0755, RunUser,
1123
cupsdCheckPermissions(StateDir, "certs", RunUser ? 0711 : 0511, User,
1124
SystemGroupIDs[0], 1, 1) < 0 ||
1125
cupsdCheckPermissions(ServerRoot, NULL, 0755, RunUser,
1127
cupsdCheckPermissions(ServerRoot, "ppd", 0755, RunUser,
1129
cupsdCheckPermissions(ServerRoot, "ssl", 0700, RunUser,
1131
/* Never alter permissions of central conffile
1132
cupsdCheckPermissions(ConfigurationFile, NULL, ConfigFilePerm, RunUser,
1134
cupsdCheckPermissions(CupsFilesFile, NULL, ConfigFilePerm, RunUser,
1137
cupsdCheckPermissions(ServerRoot, "classes.conf", 0600, RunUser,
1139
cupsdCheckPermissions(ServerRoot, "printers.conf", 0600, RunUser,
1141
cupsdCheckPermissions(ServerRoot, "passwd.md5", 0600, User,
1142
Group, 0, 0) < 0) &&
1143
(FatalErrors & CUPSD_FATAL_PERMISSIONS))
1147
* Update TempDir to the default if it hasn't been set already...
1151
if (TempDir && !RunUser &&
1152
(!strncmp(TempDir, "/private/tmp", 12) || !strncmp(TempDir, "/tmp", 4)))
1154
cupsdLogMessage(CUPSD_LOG_ERROR, "Cannot use %s for TempDir.", TempDir);
1155
cupsdClearString(&TempDir);
1157
#endif /* __APPLE__ */
1162
if ((tmpdir = getenv("TMPDIR")) != NULL &&
1163
strncmp(tmpdir, "/private/tmp", 12) && strncmp(tmpdir, "/tmp", 4))
1165
if ((tmpdir = getenv("TMPDIR")) != NULL)
1166
#endif /* __APPLE__ */
1169
* TMPDIR is defined, see if it is OK for us to use...
1172
if (stat(tmpdir, &tmpinfo))
1173
cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to access TMPDIR (%s): %s",
1174
tmpdir, strerror(errno));
1175
else if (!S_ISDIR(tmpinfo.st_mode))
1176
cupsdLogMessage(CUPSD_LOG_ERROR, "TMPDIR (%s) is not a directory.",
1178
else if ((tmpinfo.st_uid != User || !(tmpinfo.st_mode & S_IWUSR)) &&
1179
(tmpinfo.st_gid != Group || !(tmpinfo.st_mode & S_IWGRP)) &&
1180
!(tmpinfo.st_mode & S_IWOTH))
1181
cupsdLogMessage(CUPSD_LOG_ERROR,
1182
"TMPDIR (%s) has the wrong permissions.", tmpdir);
1184
cupsdSetString(&TempDir, tmpdir);
1190
cupsdLogMessage(CUPSD_LOG_INFO, "Using default TempDir of %s/tmp...",
1192
cupsdSetStringf(&TempDir, "%s/tmp", RequestRoot);
1196
* Make sure the temporary directory has the right permissions...
1199
if (!strncmp(TempDir, RequestRoot, strlen(RequestRoot)) ||
1203
* Update ownership and permissions if the CUPS temp directory
1204
* is under the spool directory or does not exist...
1207
if (cupsdCheckPermissions(TempDir, NULL, 01770, RunUser, Group, 1, 1) < 0 &&
1208
(FatalErrors & CUPSD_FATAL_PERMISSIONS))
1213
* Update environment variables...
1219
* Update default paper size setting as needed...
1222
if (!DefaultPaperSize)
1224
#ifdef HAVE_LIBPAPER
1225
char *paper_result; /* Paper size name from libpaper */
1227
if ((paper_result = systempapername()) != NULL)
1228
cupsdSetString(&DefaultPaperSize, paper_result);
1230
#endif /* HAVE_LIBPAPER */
1231
if (!DefaultLanguage ||
1232
!_cups_strcasecmp(DefaultLanguage, "C") ||
1233
!_cups_strcasecmp(DefaultLanguage, "POSIX") ||
1234
!_cups_strcasecmp(DefaultLanguage, "en") ||
1235
!_cups_strncasecmp(DefaultLanguage, "en.", 3) ||
1236
!_cups_strncasecmp(DefaultLanguage, "en_US", 5) ||
1237
!_cups_strncasecmp(DefaultLanguage, "en_CA", 5) ||
1238
!_cups_strncasecmp(DefaultLanguage, "fr_CA", 5))
1241
* These are the only locales that will default to "letter" size...
1244
cupsdSetString(&DefaultPaperSize, "Letter");
1247
cupsdSetString(&DefaultPaperSize, "A4");
1251
* Update classification setting as needed...
1254
if (Classification && !_cups_strcasecmp(Classification, "none"))
1255
cupsdClearString(&Classification);
1258
cupsdLogMessage(CUPSD_LOG_INFO, "Security set to \"%s\"", Classification);
1261
* Check the MaxClients setting, and then allocate memory for it...
1264
if (MaxClients > (MaxFDs / 3) || MaxClients <= 0)
1267
cupsdLogMessage(CUPSD_LOG_INFO,
1268
"MaxClients limited to 1/3 (%d) of the file descriptor "
1270
MaxFDs / 3, MaxFDs);
1272
MaxClients = MaxFDs / 3;
1275
cupsdLogMessage(CUPSD_LOG_INFO, "Configured for up to %d clients.",
1279
* Check the MaxActiveJobs setting; limit to 1/3 the available
1280
* file descriptors, since we need a pipe for each job...
1283
if (MaxActiveJobs > (MaxFDs / 3))
1284
MaxActiveJobs = MaxFDs / 3;
1287
* Update the MaxClientsPerHost value, as needed...
1290
if (MaxClientsPerHost <= 0)
1291
MaxClientsPerHost = MaxClients;
1293
if (MaxClientsPerHost > MaxClients)
1294
MaxClientsPerHost = MaxClients;
1296
cupsdLogMessage(CUPSD_LOG_INFO,
1297
"Allowing up to %d client connections per host.",
1301
* Update the default policy, as needed...
1305
DefaultPolicyPtr = cupsdFindPolicy(DefaultPolicy);
1307
DefaultPolicyPtr = NULL;
1309
if (!DefaultPolicyPtr)
1311
cupsd_location_t *po; /* New policy operation */
1315
cupsdLogMessage(CUPSD_LOG_ERROR, "Default policy \"%s\" not found.",
1318
cupsdSetString(&DefaultPolicy, "default");
1320
if ((DefaultPolicyPtr = cupsdFindPolicy("default")) != NULL)
1321
cupsdLogMessage(CUPSD_LOG_INFO,
1322
"Using policy \"default\" as the default.");
1325
cupsdLogMessage(CUPSD_LOG_INFO,
1326
"Creating CUPS default administrative policy:");
1328
DefaultPolicyPtr = p = cupsdAddPolicy("default");
1330
cupsdLogMessage(CUPSD_LOG_INFO, "<Policy default>");
1332
cupsdLogMessage(CUPSD_LOG_INFO, "JobPrivateAccess default");
1333
cupsdAddString(&(p->job_access), "@OWNER");
1334
cupsdAddString(&(p->job_access), "@SYSTEM");
1336
cupsdLogMessage(CUPSD_LOG_INFO, "JobPrivateValues default");
1337
cupsdAddString(&(p->job_attrs), "job-name");
1338
cupsdAddString(&(p->job_attrs), "job-originating-host-name");
1339
cupsdAddString(&(p->job_attrs), "job-originating-user-name");
1341
cupsdLogMessage(CUPSD_LOG_INFO, "SubscriptionPrivateAccess default");
1342
cupsdAddString(&(p->sub_access), "@OWNER");
1343
cupsdAddString(&(p->sub_access), "@SYSTEM");
1345
cupsdLogMessage(CUPSD_LOG_INFO, "SubscriptionPrivateValues default");
1346
cupsdAddString(&(p->job_attrs), "notify-events");
1347
cupsdAddString(&(p->job_attrs), "notify-pull-method");
1348
cupsdAddString(&(p->job_attrs), "notify-recipient-uri");
1349
cupsdAddString(&(p->job_attrs), "notify-subscriber-user-name");
1350
cupsdAddString(&(p->job_attrs), "notify-user-data");
1352
cupsdLogMessage(CUPSD_LOG_INFO,
1353
"<Limit Create-Job Print-Job Print-URI Validate-Job>");
1354
cupsdLogMessage(CUPSD_LOG_INFO, "Order Deny,Allow");
1356
po = cupsdAddPolicyOp(p, NULL, IPP_CREATE_JOB);
1357
po->order_type = CUPSD_AUTH_ALLOW;
1359
cupsdAddPolicyOp(p, po, IPP_PRINT_JOB);
1360
cupsdAddPolicyOp(p, po, IPP_PRINT_URI);
1361
cupsdAddPolicyOp(p, po, IPP_VALIDATE_JOB);
1363
cupsdLogMessage(CUPSD_LOG_INFO, "</Limit>");
1365
cupsdLogMessage(CUPSD_LOG_INFO,
1366
"<Limit Send-Document Send-URI Cancel-Job Hold-Job "
1367
"Release-Job Restart-Job Purge-Jobs "
1368
"Set-Job-Attributes Create-Job-Subscription "
1369
"Renew-Subscription Cancel-Subscription "
1370
"Get-Notifications Reprocess-Job Cancel-Current-Job "
1371
"Suspend-Current-Job Resume-Job "
1372
"Cancel-My-Jobs Close-Job CUPS-Move-Job "
1373
"CUPS-Authenticate-Job CUPS-Get-Document>");
1374
cupsdLogMessage(CUPSD_LOG_INFO, "Order Deny,Allow");
1376
po = cupsdAddPolicyOp(p, NULL, IPP_SEND_DOCUMENT);
1377
po->order_type = CUPSD_AUTH_ALLOW;
1378
po->level = CUPSD_AUTH_USER;
1380
cupsdAddName(po, "@OWNER");
1381
cupsdAddName(po, "@SYSTEM");
1382
cupsdLogMessage(CUPSD_LOG_INFO, "Require user @OWNER @SYSTEM");
1384
cupsdAddPolicyOp(p, po, IPP_SEND_URI);
1385
cupsdAddPolicyOp(p, po, IPP_CANCEL_JOB);
1386
cupsdAddPolicyOp(p, po, IPP_HOLD_JOB);
1387
cupsdAddPolicyOp(p, po, IPP_RELEASE_JOB);
1388
cupsdAddPolicyOp(p, po, IPP_RESTART_JOB);
1389
cupsdAddPolicyOp(p, po, IPP_PURGE_JOBS);
1390
cupsdAddPolicyOp(p, po, IPP_SET_JOB_ATTRIBUTES);
1391
cupsdAddPolicyOp(p, po, IPP_CREATE_JOB_SUBSCRIPTION);
1392
cupsdAddPolicyOp(p, po, IPP_RENEW_SUBSCRIPTION);
1393
cupsdAddPolicyOp(p, po, IPP_CANCEL_SUBSCRIPTION);
1394
cupsdAddPolicyOp(p, po, IPP_GET_NOTIFICATIONS);
1395
cupsdAddPolicyOp(p, po, IPP_REPROCESS_JOB);
1396
cupsdAddPolicyOp(p, po, IPP_CANCEL_CURRENT_JOB);
1397
cupsdAddPolicyOp(p, po, IPP_SUSPEND_CURRENT_JOB);
1398
cupsdAddPolicyOp(p, po, IPP_RESUME_JOB);
1399
cupsdAddPolicyOp(p, po, IPP_CANCEL_MY_JOBS);
1400
cupsdAddPolicyOp(p, po, IPP_CLOSE_JOB);
1401
cupsdAddPolicyOp(p, po, CUPS_MOVE_JOB);
1402
cupsdAddPolicyOp(p, po, CUPS_AUTHENTICATE_JOB);
1403
cupsdAddPolicyOp(p, po, CUPS_GET_DOCUMENT);
1405
cupsdLogMessage(CUPSD_LOG_INFO, "</Limit>");
1407
cupsdLogMessage(CUPSD_LOG_INFO,
1408
"<Limit Pause-Printer Resume-Printer "
1409
"Set-Printer-Attributes Enable-Printer "
1410
"Disable-Printer Pause-Printer-After-Current-Job "
1411
"Hold-New-Jobs Release-Held-New-Jobs "
1412
"Deactivate-Printer Activate-Printer Restart-Printer "
1413
"Shutdown-Printer Startup-Printer Promote-Job "
1414
"Schedule-Job-After Cancel-Jobs CUPS-Add-Printer "
1415
"CUPS-Delete-Printer CUPS-Add-Class CUPS-Delete-Class "
1416
"CUPS-Accept-Jobs CUPS-Reject-Jobs CUPS-Set-Default>");
1417
cupsdLogMessage(CUPSD_LOG_INFO, "Order Deny,Allow");
1418
cupsdLogMessage(CUPSD_LOG_INFO, "AuthType Default");
1420
po = cupsdAddPolicyOp(p, NULL, IPP_PAUSE_PRINTER);
1421
po->order_type = CUPSD_AUTH_ALLOW;
1422
po->type = CUPSD_AUTH_DEFAULT;
1423
po->level = CUPSD_AUTH_USER;
1425
cupsdAddName(po, "@SYSTEM");
1426
cupsdLogMessage(CUPSD_LOG_INFO, "Require user @SYSTEM");
1428
cupsdAddPolicyOp(p, po, IPP_RESUME_PRINTER);
1429
cupsdAddPolicyOp(p, po, IPP_SET_PRINTER_ATTRIBUTES);
1430
cupsdAddPolicyOp(p, po, IPP_ENABLE_PRINTER);
1431
cupsdAddPolicyOp(p, po, IPP_DISABLE_PRINTER);
1432
cupsdAddPolicyOp(p, po, IPP_PAUSE_PRINTER_AFTER_CURRENT_JOB);
1433
cupsdAddPolicyOp(p, po, IPP_HOLD_NEW_JOBS);
1434
cupsdAddPolicyOp(p, po, IPP_RELEASE_HELD_NEW_JOBS);
1435
cupsdAddPolicyOp(p, po, IPP_DEACTIVATE_PRINTER);
1436
cupsdAddPolicyOp(p, po, IPP_ACTIVATE_PRINTER);
1437
cupsdAddPolicyOp(p, po, IPP_RESTART_PRINTER);
1438
cupsdAddPolicyOp(p, po, IPP_SHUTDOWN_PRINTER);
1439
cupsdAddPolicyOp(p, po, IPP_STARTUP_PRINTER);
1440
cupsdAddPolicyOp(p, po, IPP_PROMOTE_JOB);
1441
cupsdAddPolicyOp(p, po, IPP_SCHEDULE_JOB_AFTER);
1442
cupsdAddPolicyOp(p, po, IPP_CANCEL_JOBS);
1443
cupsdAddPolicyOp(p, po, CUPS_ADD_PRINTER);
1444
cupsdAddPolicyOp(p, po, CUPS_DELETE_PRINTER);
1445
cupsdAddPolicyOp(p, po, CUPS_ADD_CLASS);
1446
cupsdAddPolicyOp(p, po, CUPS_DELETE_CLASS);
1447
cupsdAddPolicyOp(p, po, CUPS_ACCEPT_JOBS);
1448
cupsdAddPolicyOp(p, po, CUPS_REJECT_JOBS);
1449
cupsdAddPolicyOp(p, po, CUPS_SET_DEFAULT);
1451
cupsdLogMessage(CUPSD_LOG_INFO, "</Limit>");
1453
cupsdLogMessage(CUPSD_LOG_INFO, "<Limit All>");
1454
cupsdLogMessage(CUPSD_LOG_INFO, "Order Deny,Allow");
1456
po = cupsdAddPolicyOp(p, NULL, IPP_ANY_OPERATION);
1457
po->order_type = CUPSD_AUTH_ALLOW;
1459
cupsdLogMessage(CUPSD_LOG_INFO, "</Limit>");
1460
cupsdLogMessage(CUPSD_LOG_INFO, "</Policy>");
1464
cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdReadConfiguration: NumPolicies=%d",
1465
cupsArrayCount(Policies));
1466
for (i = 0, p = (cupsd_policy_t *)cupsArrayFirst(Policies);
1468
i ++, p = (cupsd_policy_t *)cupsArrayNext(Policies))
1469
cupsdLogMessage(CUPSD_LOG_DEBUG2,
1470
"cupsdReadConfiguration: Policies[%d]=\"%s\"", i, p->name);
1473
* If we are doing a full reload or the server root has changed, flush
1474
* the jobs, printers, etc. and start from scratch...
1477
if (NeedReload == RELOAD_ALL ||
1478
old_remote_port != RemotePort ||
1479
!old_serverroot || !ServerRoot || strcmp(old_serverroot, ServerRoot) ||
1480
!old_requestroot || !RequestRoot || strcmp(old_requestroot, RequestRoot))
1482
mime_type_t *type; /* Current type */
1483
char mimetype[MIME_MAX_SUPER + MIME_MAX_TYPE];
1484
/* MIME type name */
1487
cupsdLogMessage(CUPSD_LOG_INFO, "Full reload is required.");
1490
* Free all memory...
1493
cupsdDeleteAllSubscriptions();
1495
cupsdDeleteAllPrinters();
1497
DefaultPrinter = NULL;
1499
if (MimeDatabase != NULL)
1500
mimeDelete(MimeDatabase);
1504
for (i = 0; i < NumMimeTypes; i ++)
1505
_cupsStrFree(MimeTypes[i]);
1511
* Read the MIME type and conversion database...
1514
snprintf(temp, sizeof(temp), "%s/filter", ServerBin);
1515
snprintf(mimedir, sizeof(mimedir), "%s/mime", DataDir);
1517
MimeDatabase = mimeNew();
1518
mimeSetErrorCallback(MimeDatabase, mime_error_cb, NULL);
1520
MimeDatabase = mimeLoadTypes(MimeDatabase, mimedir);
1521
MimeDatabase = mimeLoadTypes(MimeDatabase, ServerRoot);
1522
MimeDatabase = mimeLoadFilters(MimeDatabase, mimedir, temp);
1523
MimeDatabase = mimeLoadFilters(MimeDatabase, ServerRoot, temp);
1527
cupsdLogMessage(CUPSD_LOG_EMERG,
1528
"Unable to load MIME database from \"%s\" or \"%s\".",
1529
mimedir, ServerRoot);
1530
if (FatalErrors & CUPSD_FATAL_CONFIG)
1534
cupsdLogMessage(CUPSD_LOG_INFO,
1535
"Loaded MIME database from \"%s\" and \"%s\": %d types, "
1536
"%d filters...", mimedir, ServerRoot,
1537
mimeNumTypes(MimeDatabase), mimeNumFilters(MimeDatabase));
1540
* Create a list of MIME types for the document-format-supported
1544
NumMimeTypes = mimeNumTypes(MimeDatabase);
1545
if (!mimeType(MimeDatabase, "application", "octet-stream"))
1548
if ((MimeTypes = calloc(NumMimeTypes, sizeof(const char *))) == NULL)
1550
cupsdLogMessage(CUPSD_LOG_ERROR,
1551
"Unable to allocate memory for %d MIME types.",
1557
for (i = 0, type = mimeFirstType(MimeDatabase);
1559
i ++, type = mimeNextType(MimeDatabase))
1561
snprintf(mimetype, sizeof(mimetype), "%s/%s", type->super, type->type);
1563
MimeTypes[i] = _cupsStrAlloc(mimetype);
1566
if (i < NumMimeTypes)
1567
MimeTypes[i] = _cupsStrAlloc("application/octet-stream");
1570
if (LogLevel == CUPSD_LOG_DEBUG2)
1572
mime_filter_t *filter; /* Current filter */
1575
for (type = mimeFirstType(MimeDatabase);
1577
type = mimeNextType(MimeDatabase))
1578
cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdReadConfiguration: type %s/%s",
1579
type->super, type->type);
1581
for (filter = mimeFirstFilter(MimeDatabase);
1583
filter = mimeNextFilter(MimeDatabase))
1584
cupsdLogMessage(CUPSD_LOG_DEBUG2,
1585
"cupsdReadConfiguration: filter %s/%s to %s/%s %d %s",
1586
filter->src->super, filter->src->type,
1587
filter->dst->super, filter->dst->type,
1588
filter->cost, filter->filter);
1595
snprintf(temp, sizeof(temp), "%s/banners", DataDir);
1596
cupsdLoadBanners(temp);
1599
* Load printers and classes...
1602
cupsdLoadAllPrinters();
1603
cupsdLoadAllClasses();
1605
cupsdCreateCommonData();
1608
* Update the printcap file as needed...
1611
if (Printcap && *Printcap && access(Printcap, 0))
1612
cupsdWritePrintcap();
1615
* Load queued jobs...
1621
* Load subscriptions...
1624
cupsdLoadAllSubscriptions();
1626
cupsdLogMessage(CUPSD_LOG_INFO, "Full reload complete.");
1631
* Not a full reload, so recreate the common printer attributes...
1634
cupsdCreateCommonData();
1637
* Update all jobs as needed...
1643
* Update all printers as needed...
1646
cupsdUpdatePrinters();
1647
cupsdMarkDirty(CUPSD_DIRTY_PRINTCAP);
1649
cupsdLogMessage(CUPSD_LOG_INFO, "Partial reload complete.");
1653
* Reset the reload state...
1656
NeedReload = RELOAD_NONE;
1658
cupsdClearString(&old_serverroot);
1659
cupsdClearString(&old_requestroot);
1666
* 'get_address()' - Get an address + port number from a line.
1669
static http_addrlist_t * /* O - Pointer to list if address good, NULL if bad */
1670
get_address(const char *value, /* I - Value string */
1671
int defport) /* I - Default port */
1673
char buffer[1024], /* Hostname + port number buffer */
1674
defpname[255], /* Default port name */
1675
*hostname, /* Hostname or IP */
1676
*portname; /* Port number or name */
1677
http_addrlist_t *addrlist; /* Address list */
1681
* Check for an empty value...
1686
cupsdLogMessage(CUPSD_LOG_ERROR, "Bad (empty) address.");
1691
* Grab a hostname and port number; if there is no colon and the port name
1692
* is only digits, then we have a port number by itself...
1695
strlcpy(buffer, value, sizeof(buffer));
1697
if ((portname = strrchr(buffer, ':')) != NULL && !strchr(portname, ']'))
1704
for (portname = buffer; isdigit(*portname & 255); portname ++);
1709
* Use the default port...
1712
sprintf(defpname, "%d", defport);
1713
portname = defpname;
1719
* The buffer contains just a port number...
1727
if (hostname && !strcmp(hostname, "*"))
1731
* Now lookup the address using httpAddrGetList()...
1734
if ((addrlist = httpAddrGetList(hostname, AF_UNSPEC, portname)) == NULL)
1735
cupsdLogMessage(CUPSD_LOG_ERROR, "Hostname lookup for \"%s\" failed.",
1736
hostname ? hostname : "(nil)");
1743
* 'get_addr_and_mask()' - Get an IP address and netmask.
1746
static int /* O - 1 on success, 0 on failure */
1747
get_addr_and_mask(const char *value, /* I - String from config file */
1748
unsigned *ip, /* O - Address value */
1749
unsigned *mask) /* O - Mask value */
1751
int i, j, /* Looping vars */
1752
family, /* Address family */
1753
ipcount; /* Count of fields in address */
1754
unsigned ipval; /* Value */
1755
const char *maskval, /* Pointer to start of mask value */
1756
*ptr, /* Pointer into value */
1761
* Get the address...
1764
ip[0] = ip[1] = ip[2] = ip[3] = 0x00000000;
1765
mask[0] = mask[1] = mask[2] = mask[3] = 0xffffffff;
1767
if ((maskval = strchr(value, '/')) != NULL)
1770
maskval = value + strlen(value);
1774
* Check for an IPv6 address...
1780
* Parse hexadecimal IPv6/IPv4 address...
1785
for (i = 0, ptr = value + 1; *ptr && i < 8; i ++)
1789
else if (!strncmp(ptr, "::", 2))
1791
for (ptr2 = strchr(ptr + 2, ':'), j = 0;
1793
ptr2 = strchr(ptr2 + 1, ':'), j ++);
1798
else if (isdigit(*ptr & 255) && strchr(ptr + 1, '.') && i >= 6)
1801
* Read IPv4 dotted quad...
1804
unsigned val[4] = { 0, 0, 0, 0 };
1805
/* IPv4 address values */
1807
ipcount = sscanf(ptr, "%u.%u.%u.%u", val + 0, val + 1, val + 2,
1811
* Range check the IP numbers...
1814
for (i = 0; i < ipcount; i ++)
1819
* Merge everything into a 32-bit IPv4 address in ip[3]...
1822
ip[3] = (((((val[0] << 8) | val[1]) << 8) | val[2]) << 8) | val[3];
1825
mask[3] = (0xffffffff << (32 - 8 * ipcount)) & 0xffffffff;
1828
* If the leading words are all 0's then this is an IPv4 address...
1831
if (!val[0] && !val[1] && !val[2])
1834
while (isdigit(*ptr & 255) || *ptr == '.')
1838
else if (isxdigit(*ptr & 255))
1840
ipval = strtoul(ptr, (char **)&ptr, 16);
1842
if (*ptr == ':' && ptr[1] != ':')
1851
ip[i / 2] |= ipval << 16;
1862
if (*ptr && *ptr != '/')
1866
#endif /* AF_INET6 */
1869
* Parse dotted-decimal IPv4 address...
1872
unsigned val[4] = { 0, 0, 0, 0 }; /* IPv4 address values */
1876
ipcount = sscanf(value, "%u.%u.%u.%u", val + 0, val + 1, val + 2, val + 3);
1879
* Range check the IP numbers...
1882
for (i = 0; i < ipcount; i ++)
1887
* Merge everything into a 32-bit IPv4 address in ip[3]...
1890
ip[3] = (((((val[0] << 8) | val[1]) << 8) | val[2]) << 8) | val[3];
1893
mask[3] = (0xffffffff << (32 - 8 * ipcount)) & 0xffffffff;
1899
* Get the netmask value(s)...
1902
memset(mask, 0, sizeof(unsigned) * 4);
1904
if (strchr(maskval, '.'))
1907
* Get dotted-decimal mask...
1910
if (family != AF_INET)
1913
if (sscanf(maskval, "%u.%u.%u.%u", mask + 0, mask + 1, mask + 2,
1917
mask[3] |= ((((mask[0] << 8) | mask[1]) << 8) | mask[2]) << 8;
1918
mask[0] = mask[1] = mask[2] = 0;
1923
* Get address/bits format...
1929
if (family == AF_INET6)
1937
mask[0] = 0xffffffff;
1939
mask[0] = (0xffffffff << (i - 96)) & 0xffffffff;
1942
mask[1] = 0xffffffff;
1946
mask[1] = (0xffffffff << (i - 64)) & 0xffffffff;
1949
mask[2] = 0xffffffff;
1953
mask[2] = (0xffffffff << (i - 32)) & 0xffffffff;
1956
mask[3] = 0xffffffff;
1960
mask[3] = (0xffffffff << i) & 0xffffffff;
1963
#endif /* AF_INET6 */
1968
mask[0] = 0xffffffff;
1969
mask[1] = 0xffffffff;
1970
mask[2] = 0xffffffff;
1973
mask[3] = (0xffffffff << (32 - i)) & 0xffffffff;
1975
mask[3] = 0xffffffff;
1980
cupsdLogMessage(CUPSD_LOG_DEBUG2,
1981
"get_addr_and_mask(value=\"%s\", "
1982
"ip=[%08x:%08x:%08x:%08x], mask=[%08x:%08x:%08x:%08x])",
1983
value, ip[0], ip[1], ip[2], ip[3], mask[0], mask[1], mask[2],
1987
* Check for a valid netmask; no fallback like in CUPS 1.1.x!
1990
if ((ip[0] & ~mask[0]) != 0 ||
1991
(ip[1] & ~mask[1]) != 0 ||
1992
(ip[2] & ~mask[2]) != 0 ||
1993
(ip[3] & ~mask[3]) != 0)
2001
* 'mime_error_cb()' - Log a MIME error.
2005
mime_error_cb(void *ctx, /* I - Context pointer (unused) */
2006
const char *message) /* I - Message */
2010
cupsdLogMessage(CUPSD_LOG_ERROR, "%s", message);
2015
* 'parse_aaa()' - Parse authentication, authorization, and access control lines.
2018
static int /* O - 1 on success, 0 on failure */
2019
parse_aaa(cupsd_location_t *loc, /* I - Location */
2020
char *line, /* I - Line from file */
2021
char *value, /* I - Start of value data */
2022
int linenum) /* I - Current line number */
2024
char *valptr; /* Pointer into value */
2025
unsigned ip[4], /* IP address components */
2026
mask[4]; /* IP netmask components */
2029
if (!_cups_strcasecmp(line, "Encryption"))
2032
* "Encryption xxx" - set required encryption level...
2035
if (!_cups_strcasecmp(value, "never"))
2036
loc->encryption = HTTP_ENCRYPT_NEVER;
2037
else if (!_cups_strcasecmp(value, "always"))
2039
cupsdLogMessage(CUPSD_LOG_ERROR,
2040
"Encryption value \"%s\" on line %d is invalid in this "
2041
"context. Using \"required\" instead.", value, linenum);
2043
loc->encryption = HTTP_ENCRYPT_REQUIRED;
2045
else if (!_cups_strcasecmp(value, "required"))
2046
loc->encryption = HTTP_ENCRYPT_REQUIRED;
2047
else if (!_cups_strcasecmp(value, "ifrequested"))
2048
loc->encryption = HTTP_ENCRYPT_IF_REQUESTED;
2051
cupsdLogMessage(CUPSD_LOG_ERROR,
2052
"Unknown Encryption value %s on line %d.", value, linenum);
2056
else if (!_cups_strcasecmp(line, "Order"))
2059
* "Order Deny,Allow" or "Order Allow,Deny"...
2062
if (!_cups_strncasecmp(value, "deny", 4))
2063
loc->order_type = CUPSD_AUTH_ALLOW;
2064
else if (!_cups_strncasecmp(value, "allow", 5))
2065
loc->order_type = CUPSD_AUTH_DENY;
2068
cupsdLogMessage(CUPSD_LOG_ERROR, "Unknown Order value %s on line %d.",
2073
else if (!_cups_strcasecmp(line, "Allow") || !_cups_strcasecmp(line, "Deny"))
2076
* Allow [From] host/ip...
2077
* Deny [From] host/ip...
2082
if (!_cups_strncasecmp(value, "from", 4))
2085
* Strip leading "from"...
2090
while (_cups_isspace(*value))
2098
* Find the end of the value...
2101
for (valptr = value; *valptr && !_cups_isspace(*valptr); valptr ++);
2103
while (_cups_isspace(*valptr))
2107
* Figure out what form the allow/deny address takes:
2118
* nnn.nnn.nnn.nnn/mm
2119
* nnn.nnn.nnn.nnn/mmm.mmm.mmm.mmm
2122
if (!_cups_strcasecmp(value, "all"))
2128
if (!_cups_strcasecmp(line, "Allow"))
2129
cupsdAddIPMask(&(loc->allow), zeros, zeros);
2131
cupsdAddIPMask(&(loc->deny), zeros, zeros);
2133
else if (!_cups_strcasecmp(value, "none"))
2139
if (!_cups_strcasecmp(line, "Allow"))
2140
cupsdAddIPMask(&(loc->allow), ones, zeros);
2142
cupsdAddIPMask(&(loc->deny), ones, zeros);
2145
else if (value[0] == '*' || value[0] == '.' ||
2146
(!isdigit(value[0] & 255) && value[0] != '['))
2148
else if (value[0] == '*' || value[0] == '.' || !isdigit(value[0] & 255))
2149
#endif /* AF_INET6 */
2152
* Host or domain name...
2155
if (value[0] == '*')
2158
if (!_cups_strcasecmp(line, "Allow"))
2159
cupsdAddNameMask(&(loc->allow), value);
2161
cupsdAddNameMask(&(loc->deny), value);
2166
* One of many IP address forms...
2169
if (!get_addr_and_mask(value, ip, mask))
2171
cupsdLogMessage(CUPSD_LOG_ERROR, "Bad netmask value %s on line %d.",
2176
if (!_cups_strcasecmp(line, "Allow"))
2177
cupsdAddIPMask(&(loc->allow), ip, mask);
2179
cupsdAddIPMask(&(loc->deny), ip, mask);
2183
* Advance to next value...
2189
else if (!_cups_strcasecmp(line, "AuthType"))
2192
* AuthType {none,basic,digest,basicdigest,negotiate,default}
2195
if (!_cups_strcasecmp(value, "none"))
2197
loc->type = CUPSD_AUTH_NONE;
2198
loc->level = CUPSD_AUTH_ANON;
2200
else if (!_cups_strcasecmp(value, "basic"))
2202
loc->type = CUPSD_AUTH_BASIC;
2204
if (loc->level == CUPSD_AUTH_ANON)
2205
loc->level = CUPSD_AUTH_USER;
2207
else if (!_cups_strcasecmp(value, "digest"))
2209
loc->type = CUPSD_AUTH_DIGEST;
2211
if (loc->level == CUPSD_AUTH_ANON)
2212
loc->level = CUPSD_AUTH_USER;
2214
else if (!_cups_strcasecmp(value, "basicdigest"))
2216
loc->type = CUPSD_AUTH_BASICDIGEST;
2218
if (loc->level == CUPSD_AUTH_ANON)
2219
loc->level = CUPSD_AUTH_USER;
2221
else if (!_cups_strcasecmp(value, "default"))
2223
loc->type = CUPSD_AUTH_DEFAULT;
2225
if (loc->level == CUPSD_AUTH_ANON)
2226
loc->level = CUPSD_AUTH_USER;
2229
else if (!_cups_strcasecmp(value, "negotiate"))
2231
loc->type = CUPSD_AUTH_NEGOTIATE;
2233
if (loc->level == CUPSD_AUTH_ANON)
2234
loc->level = CUPSD_AUTH_USER;
2236
#endif /* HAVE_GSSAPI */
2239
cupsdLogMessage(CUPSD_LOG_WARN,
2240
"Unknown authorization type %s on line %d.",
2245
else if (!_cups_strcasecmp(line, "AuthClass"))
2248
* AuthClass anonymous, user, system, group
2251
if (!_cups_strcasecmp(value, "anonymous"))
2253
loc->type = CUPSD_AUTH_NONE;
2254
loc->level = CUPSD_AUTH_ANON;
2256
cupsdLogMessage(CUPSD_LOG_WARN,
2257
"\"AuthClass %s\" is deprecated; consider removing "
2261
else if (!_cups_strcasecmp(value, "user"))
2263
loc->level = CUPSD_AUTH_USER;
2265
cupsdLogMessage(CUPSD_LOG_WARN,
2266
"\"AuthClass %s\" is deprecated; consider using "
2267
"\"Require valid-user\" on line %d.",
2270
else if (!_cups_strcasecmp(value, "group"))
2272
loc->level = CUPSD_AUTH_GROUP;
2274
cupsdLogMessage(CUPSD_LOG_WARN,
2275
"\"AuthClass %s\" is deprecated; consider using "
2276
"\"Require user @groupname\" on line %d.",
2279
else if (!_cups_strcasecmp(value, "system"))
2281
loc->level = CUPSD_AUTH_GROUP;
2283
cupsdAddName(loc, "@SYSTEM");
2285
cupsdLogMessage(CUPSD_LOG_WARN,
2286
"\"AuthClass %s\" is deprecated; consider using "
2287
"\"Require user @SYSTEM\" on line %d.",
2292
cupsdLogMessage(CUPSD_LOG_WARN,
2293
"Unknown authorization class %s on line %d.",
2298
else if (!_cups_strcasecmp(line, "AuthGroupName"))
2300
cupsdAddName(loc, value);
2302
cupsdLogMessage(CUPSD_LOG_WARN,
2303
"\"AuthGroupName %s\" directive is deprecated; consider "
2304
"using \"Require user @%s\" on line %d.",
2305
value, value, linenum);
2307
else if (!_cups_strcasecmp(line, "Require"))
2310
* Apache synonym for AuthClass and AuthGroupName...
2314
* Require valid-user
2315
* Require group names
2316
* Require user names
2319
for (valptr = value; !_cups_isspace(*valptr) && *valptr; valptr ++);
2324
if (!_cups_strcasecmp(value, "valid-user") ||
2325
!_cups_strcasecmp(value, "user"))
2326
loc->level = CUPSD_AUTH_USER;
2327
else if (!_cups_strcasecmp(value, "group"))
2328
loc->level = CUPSD_AUTH_GROUP;
2331
cupsdLogMessage(CUPSD_LOG_WARN, "Unknown Require type %s on line %d.",
2337
* Get the list of names from the line...
2340
for (value = valptr; *value;)
2342
while (_cups_isspace(*value))
2345
#ifdef HAVE_AUTHORIZATION_H
2346
if (!strncmp(value, "@AUTHKEY(", 9))
2349
* Grab "@AUTHKEY(name)" value...
2352
for (valptr = value + 9; *valptr != ')' && *valptr; valptr ++);
2358
#endif /* HAVE_AUTHORIZATION_H */
2359
if (*value == '\"' || *value == '\'')
2362
* Grab quoted name...
2365
for (valptr = value + 1; *valptr != *value && *valptr; valptr ++);
2372
* Grab literal name.
2375
for (valptr = value; !_cups_isspace(*valptr) && *valptr; valptr ++);
2381
cupsdAddName(loc, value);
2383
for (value = valptr; _cups_isspace(*value); value ++);
2386
else if (!_cups_strcasecmp(line, "Satisfy"))
2388
if (!_cups_strcasecmp(value, "all"))
2389
loc->satisfy = CUPSD_AUTH_SATISFY_ALL;
2390
else if (!_cups_strcasecmp(value, "any"))
2391
loc->satisfy = CUPSD_AUTH_SATISFY_ANY;
2394
cupsdLogMessage(CUPSD_LOG_WARN, "Unknown Satisfy value %s on line %d.",
2407
* 'parse_fatal_errors()' - Parse FatalErrors values in a string.
2410
static int /* O - FatalErrors bits */
2411
parse_fatal_errors(const char *s) /* I - FatalErrors string */
2413
int fatal; /* FatalErrors bits */
2414
char value[1024], /* Value string */
2415
*valstart, /* Pointer into value */
2416
*valend; /* End of value */
2420
* Empty FatalErrors line yields NULL pointer...
2424
return (CUPSD_FATAL_NONE);
2427
* Loop through the value string,...
2430
strlcpy(value, s, sizeof(value));
2432
fatal = CUPSD_FATAL_NONE;
2434
for (valstart = value; *valstart;)
2437
* Get the current space/comma-delimited kind name...
2440
for (valend = valstart; *valend; valend ++)
2441
if (_cups_isspace(*valend) || *valend == ',')
2448
* Add the error to the bitmask...
2451
if (!_cups_strcasecmp(valstart, "all"))
2452
fatal = CUPSD_FATAL_ALL;
2453
else if (!_cups_strcasecmp(valstart, "browse"))
2454
fatal |= CUPSD_FATAL_BROWSE;
2455
else if (!_cups_strcasecmp(valstart, "-browse"))
2456
fatal &= ~CUPSD_FATAL_BROWSE;
2457
else if (!_cups_strcasecmp(valstart, "config"))
2458
fatal |= CUPSD_FATAL_CONFIG;
2459
else if (!_cups_strcasecmp(valstart, "-config"))
2460
fatal &= ~CUPSD_FATAL_CONFIG;
2461
else if (!_cups_strcasecmp(valstart, "listen"))
2462
fatal |= CUPSD_FATAL_LISTEN;
2463
else if (!_cups_strcasecmp(valstart, "-listen"))
2464
fatal &= ~CUPSD_FATAL_LISTEN;
2465
else if (!_cups_strcasecmp(valstart, "log"))
2466
fatal |= CUPSD_FATAL_LOG;
2467
else if (!_cups_strcasecmp(valstart, "-log"))
2468
fatal &= ~CUPSD_FATAL_LOG;
2469
else if (!_cups_strcasecmp(valstart, "permissions"))
2470
fatal |= CUPSD_FATAL_PERMISSIONS;
2471
else if (!_cups_strcasecmp(valstart, "-permissions"))
2472
fatal &= ~CUPSD_FATAL_PERMISSIONS;
2473
else if (_cups_strcasecmp(valstart, "none"))
2474
cupsdLogMessage(CUPSD_LOG_ERROR,
2475
"Unknown FatalErrors kind \"%s\" ignored.", valstart);
2477
for (valstart = valend; *valstart; valstart ++)
2478
if (!_cups_isspace(*valstart) || *valstart != ',')
2487
* 'parse_groups()' - Parse system group names in a string.
2490
static int /* O - 1 on success, 0 on failure */
2491
parse_groups(const char *s) /* I - Space-delimited groups */
2493
int status; /* Return status */
2494
char value[1024], /* Value string */
2495
*valstart, /* Pointer into value */
2496
*valend, /* End of value */
2497
quote; /* Quote character */
2498
struct group *group; /* Group */
2502
* Make a copy of the string and parse out the groups...
2505
strlcpy(value, s, sizeof(value));
2510
while (*valstart && NumSystemGroups < MAX_SYSTEM_GROUPS)
2512
if (*valstart == '\'' || *valstart == '\"')
2515
* Scan quoted name...
2518
quote = *valstart++;
2520
for (valend = valstart; *valend; valend ++)
2521
if (*valend == quote)
2527
* Scan space or comma-delimited name...
2530
for (valend = valstart; *valend; valend ++)
2531
if (_cups_isspace(*valend) || *valend == ',')
2538
group = getgrnam(valstart);
2541
cupsdSetString(SystemGroups + NumSystemGroups, valstart);
2542
SystemGroupIDs[NumSystemGroups] = group->gr_gid;
2553
while (*valstart == ',' || _cups_isspace(*valstart))
2562
* 'parse_protocols()' - Parse browse protocols in a string.
2565
static int /* O - Browse protocol bits */
2566
parse_protocols(const char *s) /* I - Space-delimited protocols */
2568
int protocols; /* Browse protocol bits */
2569
char value[1024], /* Value string */
2570
*valstart, /* Pointer into value */
2571
*valend; /* End of value */
2575
* Empty protocol line yields NULL pointer...
2582
* Loop through the value string,...
2585
strlcpy(value, s, sizeof(value));
2589
for (valstart = value; *valstart;)
2592
* Get the current space/comma-delimited protocol name...
2595
for (valend = valstart; *valend; valend ++)
2596
if (_cups_isspace(*valend) || *valend == ',')
2603
* Add the protocol to the bitmask...
2606
if (!_cups_strcasecmp(valstart, "dnssd") ||
2607
!_cups_strcasecmp(valstart, "dns-sd") ||
2608
!_cups_strcasecmp(valstart, "bonjour"))
2609
protocols |= BROWSE_DNSSD;
2610
else if (!_cups_strcasecmp(valstart, "all"))
2611
protocols |= BROWSE_ALL;
2612
else if (_cups_strcasecmp(valstart, "none"))
2613
cupsdLogMessage(CUPSD_LOG_ERROR,
2614
"Unknown browse protocol \"%s\" ignored.", valstart);
2616
for (valstart = valend; *valstart; valstart ++)
2617
if (!_cups_isspace(*valstart) || *valstart != ',')
2626
* 'parse_variable()' - Parse a variable line.
2629
static int /* O - 1 on success, 0 on failure */
2631
const char *filename, /* I - Name of configuration file */
2632
int linenum, /* I - Line in configuration file */
2633
const char *line, /* I - Line from configuration file */
2634
const char *value, /* I - Value from configuration file */
2635
size_t num_vars, /* I - Number of variables */
2636
const cupsd_var_t *vars) /* I - Variables */
2638
size_t i; /* Looping var */
2639
const cupsd_var_t *var; /* Variables */
2640
char temp[1024]; /* Temporary string */
2643
for (i = num_vars, var = vars; i > 0; i --, var ++)
2644
if (!_cups_strcasecmp(line, var->name))
2650
* Unknown directive! Output an error message and continue...
2654
cupsdLogMessage(CUPSD_LOG_ERROR, "Missing value for %s on line %d of %s.",
2655
line, linenum, filename);
2657
cupsdLogMessage(CUPSD_LOG_ERROR, "Unknown directive %s on line %d of %s.",
2658
line, linenum, filename);
2665
case CUPSD_VARTYPE_INTEGER :
2668
cupsdLogMessage(CUPSD_LOG_ERROR,
2669
"Missing integer value for %s on line %d of %s.",
2670
line, linenum, filename);
2673
else if (!isdigit(*value & 255))
2675
cupsdLogMessage(CUPSD_LOG_ERROR,
2676
"Bad integer value for %s on line %d of %s.",
2677
line, linenum, filename);
2683
char *units; /* Units */
2685
n = strtol(value, &units, 0);
2687
if (units && *units)
2689
if (tolower(units[0] & 255) == 'g')
2690
n *= 1024 * 1024 * 1024;
2691
else if (tolower(units[0] & 255) == 'm')
2693
else if (tolower(units[0] & 255) == 'k')
2695
else if (tolower(units[0] & 255) == 't')
2699
cupsdLogMessage(CUPSD_LOG_ERROR,
2700
"Unknown integer value for %s on line %d of %s.",
2701
line, linenum, filename);
2708
cupsdLogMessage(CUPSD_LOG_ERROR,
2709
"Bad negative integer value for %s on line %d of "
2710
"%s.", line, linenum, filename);
2715
*((int *)var->ptr) = n;
2720
case CUPSD_VARTYPE_TIME :
2723
cupsdLogMessage(CUPSD_LOG_ERROR,
2724
"Missing time interval value for %s on line %d of "
2725
"%s.", line, linenum, filename);
2728
else if (!_cups_strncasecmp(line, "PreserveJob", 11) &&
2729
(!_cups_strcasecmp(value, "true") ||
2730
!_cups_strcasecmp(value, "on") ||
2731
!_cups_strcasecmp(value, "enabled") ||
2732
!_cups_strcasecmp(value, "yes")))
2734
*((int *)var->ptr) = INT_MAX;
2736
else if (!_cups_strcasecmp(value, "false") ||
2737
!_cups_strcasecmp(value, "off") ||
2738
!_cups_strcasecmp(value, "disabled") ||
2739
!_cups_strcasecmp(value, "no"))
2741
*((int *)var->ptr) = 0;
2743
else if (!isdigit(*value & 255))
2745
cupsdLogMessage(CUPSD_LOG_ERROR,
2746
"Unknown time interval value for %s on line %d of "
2747
"%s.", line, linenum, filename);
2752
double n; /* Number */
2753
char *units; /* Units */
2755
n = strtod(value, &units);
2757
if (units && *units)
2759
if (tolower(units[0] & 255) == 'w')
2760
n *= 7 * 24 * 60 * 60;
2761
else if (tolower(units[0] & 255) == 'd')
2763
else if (tolower(units[0] & 255) == 'h')
2765
else if (tolower(units[0] & 255) == 'm')
2769
cupsdLogMessage(CUPSD_LOG_ERROR,
2770
"Unknown time interval value for %s on line "
2771
"%d of %s.", line, linenum, filename);
2776
if (n < 0.0 || n > INT_MAX)
2778
cupsdLogMessage(CUPSD_LOG_ERROR,
2779
"Bad time value for %s on line %d of %s.",
2780
line, linenum, filename);
2785
*((int *)var->ptr) = (int)n;
2790
case CUPSD_VARTYPE_BOOLEAN :
2793
cupsdLogMessage(CUPSD_LOG_ERROR,
2794
"Missing boolean value for %s on line %d of %s.",
2795
line, linenum, filename);
2798
else if (!_cups_strcasecmp(value, "true") ||
2799
!_cups_strcasecmp(value, "on") ||
2800
!_cups_strcasecmp(value, "enabled") ||
2801
!_cups_strcasecmp(value, "yes") ||
2804
*((int *)var->ptr) = TRUE;
2806
else if (!_cups_strcasecmp(value, "false") ||
2807
!_cups_strcasecmp(value, "off") ||
2808
!_cups_strcasecmp(value, "disabled") ||
2809
!_cups_strcasecmp(value, "no") ||
2810
!_cups_strcasecmp(value, "0"))
2812
*((int *)var->ptr) = FALSE;
2816
cupsdLogMessage(CUPSD_LOG_ERROR,
2817
"Unknown boolean value %s on line %d of %s.",
2818
value, linenum, filename);
2823
case CUPSD_VARTYPE_PATHNAME :
2826
cupsdLogMessage(CUPSD_LOG_ERROR,
2827
"Missing pathname value for %s on line %d of %s.",
2828
line, linenum, filename);
2832
if (value[0] == '/')
2833
strlcpy(temp, value, sizeof(temp));
2835
snprintf(temp, sizeof(temp), "%s/%s", ServerRoot, value);
2837
if (access(temp, 0))
2839
cupsdLogMessage(CUPSD_LOG_ERROR,
2840
"File or directory for \"%s %s\" on line %d of %s "
2841
"does not exist.", line, value, linenum, filename);
2845
cupsdSetString((char **)var->ptr, temp);
2848
case CUPSD_VARTYPE_STRING :
2849
cupsdSetString((char **)var->ptr, value);
2858
* 'read_cupsd_conf()' - Read the cupsd.conf configuration file.
2861
static int /* O - 1 on success, 0 on failure */
2862
read_cupsd_conf(cups_file_t *fp) /* I - File to read from */
2864
int linenum; /* Current line number */
2865
char line[HTTP_MAX_BUFFER],
2866
/* Line from file */
2867
temp[HTTP_MAX_BUFFER],
2868
/* Temporary buffer for value */
2869
*value, /* Pointer to value */
2870
*valueptr; /* Pointer into value */
2871
int valuelen; /* Length of value */
2872
http_addrlist_t *addrlist, /* Address list */
2873
*addr; /* Current address */
2874
cups_file_t *incfile; /* Include file */
2875
char incname[1024]; /* Include filename */
2879
* Loop through each line in the file...
2884
while (cupsFileGetConf(fp, line, sizeof(line), &value, &linenum))
2887
* Decode the directive...
2890
if (!_cups_strcasecmp(line, "Include") && value)
2896
if (value[0] == '/')
2897
strlcpy(incname, value, sizeof(incname));
2899
snprintf(incname, sizeof(incname), "%s/%s", ServerRoot, value);
2901
if ((incfile = cupsFileOpen(incname, "rb")) == NULL)
2902
cupsdLogMessage(CUPSD_LOG_ERROR,
2903
"Unable to include config file \"%s\" - %s",
2904
incname, strerror(errno));
2907
read_cupsd_conf(incfile);
2908
cupsFileClose(incfile);
2911
else if (!_cups_strcasecmp(line, "<Location") && value)
2917
linenum = read_location(fp, value, linenum);
2921
else if (!_cups_strcasecmp(line, "<Policy") && value)
2927
linenum = read_policy(fp, value, linenum);
2931
else if (!_cups_strcasecmp(line, "FaxRetryInterval") && value)
2933
JobRetryInterval = atoi(value);
2934
cupsdLogMessage(CUPSD_LOG_WARN,
2935
"FaxRetryInterval is deprecated; use "
2936
"JobRetryInterval on line %d.", linenum);
2938
else if (!_cups_strcasecmp(line, "FaxRetryLimit") && value)
2940
JobRetryLimit = atoi(value);
2941
cupsdLogMessage(CUPSD_LOG_WARN,
2942
"FaxRetryLimit is deprecated; use "
2943
"JobRetryLimit on line %d.", linenum);
2945
else if ((!_cups_strcasecmp(line, "Port") || !_cups_strcasecmp(line, "Listen")
2947
|| !_cups_strcasecmp(line, "SSLPort") || !_cups_strcasecmp(line, "SSLListen")
2948
#endif /* HAVE_SSL */
2952
* Add listening address(es) to the list...
2955
cupsd_listener_t *lis; /* New listeners array */
2959
* Get the address list...
2962
addrlist = get_address(value, IPP_PORT);
2966
cupsdLogMessage(CUPSD_LOG_ERROR, "Bad %s address %s at line %d.", line,
2972
* Add each address...
2975
for (addr = addrlist; addr; addr = addr->next)
2978
* See if this address is already present...
2981
for (lis = (cupsd_listener_t *)cupsArrayFirst(Listeners);
2983
lis = (cupsd_listener_t *)cupsArrayNext(Listeners))
2984
if (httpAddrEqual(&(addr->addr), &(lis->address)) &&
2985
httpAddrPort(&(addr->addr)) == httpAddrPort(&(lis->address)))
2990
httpAddrString(&lis->address, temp, sizeof(temp));
2991
cupsdLogMessage(CUPSD_LOG_WARN,
2992
"Duplicate listen address \"%s\" ignored.", temp);
2997
* Allocate another listener...
3001
Listeners = cupsArrayNew(NULL, NULL);
3005
cupsdLogMessage(CUPSD_LOG_ERROR,
3006
"Unable to allocate %s at line %d - %s.",
3007
line, linenum, strerror(errno));
3011
if ((lis = calloc(1, sizeof(cupsd_listener_t))) == NULL)
3013
cupsdLogMessage(CUPSD_LOG_ERROR,
3014
"Unable to allocate %s at line %d - %s.",
3015
line, linenum, strerror(errno));
3019
cupsArrayAdd(Listeners, lis);
3022
* Copy the current address and log it...
3025
memcpy(&(lis->address), &(addr->addr), sizeof(lis->address));
3029
if (!_cups_strcasecmp(line, "SSLPort") || !_cups_strcasecmp(line, "SSLListen"))
3030
lis->encryption = HTTP_ENCRYPT_ALWAYS;
3031
#endif /* HAVE_SSL */
3033
httpAddrString(&lis->address, temp, sizeof(temp));
3036
if (lis->address.addr.sa_family == AF_LOCAL)
3037
cupsdLogMessage(CUPSD_LOG_INFO, "Listening to %s (Domain)", temp);
3039
#endif /* AF_LOCAL */
3040
cupsdLogMessage(CUPSD_LOG_INFO, "Listening to %s:%d (IPv%d)", temp,
3041
httpAddrPort(&(lis->address)),
3042
_httpAddrFamily(&(lis->address)) == AF_INET ? 4 : 6);
3044
if (!httpAddrLocalhost(&(lis->address)))
3045
RemotePort = httpAddrPort(&(lis->address));
3052
httpAddrFreeList(addrlist);
3054
else if (!_cups_strcasecmp(line, "BrowseProtocols") ||
3055
!_cups_strcasecmp(line, "BrowseLocalProtocols"))
3058
* "BrowseProtocols name [... name]"
3059
* "BrowseLocalProtocols name [... name]"
3062
int protocols = parse_protocols(value);
3066
cupsdLogMessage(CUPSD_LOG_ERROR,
3067
"Unknown browse protocol \"%s\" on line %d.",
3072
BrowseLocalProtocols = protocols;
3074
else if (!_cups_strcasecmp(line, "DefaultAuthType") && value)
3077
* DefaultAuthType {basic,digest,basicdigest,negotiate}
3080
if (!_cups_strcasecmp(value, "none"))
3081
default_auth_type = CUPSD_AUTH_NONE;
3082
else if (!_cups_strcasecmp(value, "basic"))
3083
default_auth_type = CUPSD_AUTH_BASIC;
3084
else if (!_cups_strcasecmp(value, "digest"))
3085
default_auth_type = CUPSD_AUTH_DIGEST;
3086
else if (!_cups_strcasecmp(value, "basicdigest"))
3087
default_auth_type = CUPSD_AUTH_BASICDIGEST;
3089
else if (!_cups_strcasecmp(value, "negotiate"))
3090
default_auth_type = CUPSD_AUTH_NEGOTIATE;
3091
#endif /* HAVE_GSSAPI */
3092
else if (!_cups_strcasecmp(value, "auto"))
3093
default_auth_type = CUPSD_AUTH_AUTO;
3096
cupsdLogMessage(CUPSD_LOG_WARN,
3097
"Unknown default authorization type %s on line %d.",
3099
if (FatalErrors & CUPSD_FATAL_CONFIG)
3104
else if (!_cups_strcasecmp(line, "DefaultEncryption"))
3107
* DefaultEncryption {Never,IfRequested,Required}
3110
if (!value || !_cups_strcasecmp(value, "never"))
3111
DefaultEncryption = HTTP_ENCRYPT_NEVER;
3112
else if (!_cups_strcasecmp(value, "required"))
3113
DefaultEncryption = HTTP_ENCRYPT_REQUIRED;
3114
else if (!_cups_strcasecmp(value, "ifrequested"))
3115
DefaultEncryption = HTTP_ENCRYPT_IF_REQUESTED;
3118
cupsdLogMessage(CUPSD_LOG_WARN,
3119
"Unknown default encryption %s on line %d.",
3121
if (FatalErrors & CUPSD_FATAL_CONFIG)
3125
#endif /* HAVE_SSL */
3126
else if (!_cups_strcasecmp(line, "HostNameLookups") && value)
3129
* Do hostname lookups?
3132
if (!_cups_strcasecmp(value, "off") || !_cups_strcasecmp(value, "no") ||
3133
!_cups_strcasecmp(value, "false"))
3134
HostNameLookups = 0;
3135
else if (!_cups_strcasecmp(value, "on") || !_cups_strcasecmp(value, "yes") ||
3136
!_cups_strcasecmp(value, "true"))
3137
HostNameLookups = 1;
3138
else if (!_cups_strcasecmp(value, "double"))
3139
HostNameLookups = 2;
3141
cupsdLogMessage(CUPSD_LOG_WARN, "Unknown HostNameLookups %s on line %d.",
3144
else if (!_cups_strcasecmp(line, "AccessLogLevel") && value)
3147
* Amount of logging to do to access log...
3150
if (!_cups_strcasecmp(value, "all"))
3151
AccessLogLevel = CUPSD_ACCESSLOG_ALL;
3152
else if (!_cups_strcasecmp(value, "actions"))
3153
AccessLogLevel = CUPSD_ACCESSLOG_ACTIONS;
3154
else if (!_cups_strcasecmp(value, "config"))
3155
AccessLogLevel = CUPSD_ACCESSLOG_CONFIG;
3157
cupsdLogMessage(CUPSD_LOG_WARN, "Unknown AccessLogLevel %s on line %d.",
3160
else if (!_cups_strcasecmp(line, "LogLevel") && value)
3163
* Amount of logging to do to error log...
3166
if (!_cups_strcasecmp(value, "debug2"))
3167
LogLevel = CUPSD_LOG_DEBUG2;
3168
else if (!_cups_strcasecmp(value, "debug"))
3169
LogLevel = CUPSD_LOG_DEBUG;
3170
else if (!_cups_strcasecmp(value, "info"))
3171
LogLevel = CUPSD_LOG_INFO;
3172
else if (!_cups_strcasecmp(value, "notice"))
3173
LogLevel = CUPSD_LOG_NOTICE;
3174
else if (!_cups_strcasecmp(value, "warn"))
3175
LogLevel = CUPSD_LOG_WARN;
3176
else if (!_cups_strcasecmp(value, "error"))
3177
LogLevel = CUPSD_LOG_ERROR;
3178
else if (!_cups_strcasecmp(value, "crit"))
3179
LogLevel = CUPSD_LOG_CRIT;
3180
else if (!_cups_strcasecmp(value, "alert"))
3181
LogLevel = CUPSD_LOG_ALERT;
3182
else if (!_cups_strcasecmp(value, "emerg"))
3183
LogLevel = CUPSD_LOG_EMERG;
3184
else if (!_cups_strcasecmp(value, "none"))
3185
LogLevel = CUPSD_LOG_NONE;
3187
cupsdLogMessage(CUPSD_LOG_WARN, "Unknown LogLevel %s on line %d.",
3190
else if (!_cups_strcasecmp(line, "LogTimeFormat") && value)
3193
* Amount of logging to do to error log...
3196
if (!_cups_strcasecmp(value, "standard"))
3197
LogTimeFormat = CUPSD_TIME_STANDARD;
3198
else if (!_cups_strcasecmp(value, "usecs"))
3199
LogTimeFormat = CUPSD_TIME_USECS;
3201
cupsdLogMessage(CUPSD_LOG_WARN, "Unknown LogTimeFormat %s on line %d.",
3204
else if (!_cups_strcasecmp(line, "ServerTokens") && value)
3207
* Set the string used for the Server header...
3210
struct utsname plat; /* Platform info */
3215
if (!_cups_strcasecmp(value, "ProductOnly"))
3216
cupsdSetString(&ServerHeader, "CUPS IPP");
3217
else if (!_cups_strcasecmp(value, "Major"))
3218
cupsdSetStringf(&ServerHeader, "CUPS/%d IPP/2", CUPS_VERSION_MAJOR);
3219
else if (!_cups_strcasecmp(value, "Minor"))
3220
cupsdSetStringf(&ServerHeader, "CUPS/%d.%d IPP/2.1", CUPS_VERSION_MAJOR,
3221
CUPS_VERSION_MINOR);
3222
else if (!_cups_strcasecmp(value, "Minimal"))
3223
cupsdSetString(&ServerHeader, CUPS_MINIMAL " IPP/2.1");
3224
else if (!_cups_strcasecmp(value, "OS"))
3225
cupsdSetStringf(&ServerHeader, CUPS_MINIMAL " (%s %s) IPP/2.1",
3226
plat.sysname, plat.release);
3227
else if (!_cups_strcasecmp(value, "Full"))
3228
cupsdSetStringf(&ServerHeader, CUPS_MINIMAL " (%s %s; %s) IPP/2.1",
3229
plat.sysname, plat.release, plat.machine);
3230
else if (!_cups_strcasecmp(value, "None"))
3231
cupsdClearString(&ServerHeader);
3233
cupsdLogMessage(CUPSD_LOG_WARN, "Unknown ServerTokens %s on line %d.",
3236
else if (!_cups_strcasecmp(line, "PassEnv") && value)
3239
* PassEnv variable [... variable]
3244
for (valuelen = 0; value[valuelen]; valuelen ++)
3245
if (_cups_isspace(value[valuelen]) || value[valuelen] == ',')
3248
if (value[valuelen])
3250
value[valuelen] = '\0';
3254
cupsdSetEnv(value, NULL);
3256
for (value += valuelen; *value; value ++)
3257
if (!_cups_isspace(*value) || *value != ',')
3261
else if (!_cups_strcasecmp(line, "ServerAlias") && value)
3264
* ServerAlias name [... name]
3268
ServerAlias = cupsArrayNew(NULL, NULL);
3272
for (valuelen = 0; value[valuelen]; valuelen ++)
3273
if (_cups_isspace(value[valuelen]) || value[valuelen] == ',')
3276
if (value[valuelen])
3278
value[valuelen] = '\0';
3282
cupsdAddAlias(ServerAlias, value);
3284
for (value += valuelen; *value; value ++)
3285
if (!_cups_isspace(*value) || *value != ',')
3289
else if (!_cups_strcasecmp(line, "SetEnv") && value)
3292
* SetEnv variable value
3295
for (valueptr = value; *valueptr && !isspace(*valueptr & 255); valueptr ++);
3303
while (isspace(*valueptr & 255))
3306
cupsdSetEnv(value, valueptr);
3309
cupsdLogMessage(CUPSD_LOG_ERROR,
3310
"Missing value for SetEnv directive on line %d.",
3314
else if (!_cups_strcasecmp(line, "SSLOptions"))
3317
* SSLOptions options
3320
if (!value || !_cups_strcasecmp(value, "none"))
3321
SSLOptions = CUPSD_SSL_NONE;
3322
else if (!_cups_strcasecmp(value, "noemptyfragments"))
3323
SSLOptions = CUPSD_SSL_NOEMPTY;
3325
cupsdLogMessage(CUPSD_LOG_ERROR,
3326
"Unknown value \"%s\" for SSLOptions directive on "
3327
"line %d.", value, linenum);
3329
#endif /* HAVE_SSL */
3330
else if (!_cups_strcasecmp(line, "AccessLog") ||
3331
!_cups_strcasecmp(line, "CacheDir") ||
3332
!_cups_strcasecmp(line, "ConfigFilePerm") ||
3333
!_cups_strcasecmp(line, "DataDir") ||
3334
!_cups_strcasecmp(line, "DocumentRoot") ||
3335
!_cups_strcasecmp(line, "ErrorLog") ||
3336
!_cups_strcasecmp(line, "FatalErrors") ||
3337
!_cups_strcasecmp(line, "FileDevice") ||
3338
!_cups_strcasecmp(line, "FontPath") ||
3339
!_cups_strcasecmp(line, "Group") ||
3340
!_cups_strcasecmp(line, "LogFilePerm") ||
3341
!_cups_strcasecmp(line, "LPDConfigFile") ||
3342
!_cups_strcasecmp(line, "PageLog") ||
3343
!_cups_strcasecmp(line, "Printcap") ||
3344
!_cups_strcasecmp(line, "PrintcapFormat") ||
3345
!_cups_strcasecmp(line, "RemoteRoot") ||
3346
!_cups_strcasecmp(line, "RequestRoot") ||
3347
!_cups_strcasecmp(line, "ServerBin") ||
3348
!_cups_strcasecmp(line, "ServerCertificate") ||
3349
!_cups_strcasecmp(line, "ServerKey") ||
3350
!_cups_strcasecmp(line, "ServerRoot") ||
3351
!_cups_strcasecmp(line, "SMBConfigFile") ||
3352
!_cups_strcasecmp(line, "StateDir") ||
3353
!_cups_strcasecmp(line, "SystemGroup") ||
3354
!_cups_strcasecmp(line, "SystemGroupAuthKey") ||
3355
!_cups_strcasecmp(line, "TempDir") ||
3356
!_cups_strcasecmp(line, "PidFile") ||
3357
!_cups_strcasecmp(line, "User"))
3359
cupsdLogMessage(CUPSD_LOG_INFO,
3360
"Please move \"%s%s%s\" on line %d of %s to the %s file; "
3361
"this will become an error in a future release.",
3362
line, value ? " " : "", value ? value : "", linenum,
3363
ConfigurationFile, CupsFilesFile);
3366
parse_variable(ConfigurationFile, linenum, line, value,
3367
sizeof(cupsd_vars) / sizeof(cupsd_vars[0]), cupsd_vars);
3375
* 'read_cups_files_conf()' - Read the cups-files.conf configuration file.
3378
static int /* O - 1 on success, 0 on failure */
3379
read_cups_files_conf(cups_file_t *fp) /* I - File to read from */
3381
int linenum; /* Current line number */
3382
char line[HTTP_MAX_BUFFER], /* Line from file */
3383
*value; /* Value from line */
3384
struct group *group; /* Group */
3388
* Loop through each line in the file...
3393
while (cupsFileGetConf(fp, line, sizeof(line), &value, &linenum))
3395
if (!_cups_strcasecmp(line, "FatalErrors"))
3396
FatalErrors = parse_fatal_errors(value);
3397
else if (!_cups_strcasecmp(line, "Group") && value)
3400
* Group ID to run as...
3403
if (isdigit(value[0]))
3404
Group = atoi(value);
3408
group = getgrnam(value);
3411
Group = group->gr_gid;
3414
cupsdLogMessage(CUPSD_LOG_ERROR,
3415
"Unknown Group \"%s\" on line %d of %s.", value,
3416
linenum, CupsFilesFile);
3417
if (FatalErrors & CUPSD_FATAL_CONFIG)
3422
else if (!_cups_strcasecmp(line, "PrintcapFormat") && value)
3425
* Format of printcap file?
3428
if (!_cups_strcasecmp(value, "bsd"))
3429
PrintcapFormat = PRINTCAP_BSD;
3430
else if (!_cups_strcasecmp(value, "plist"))
3431
PrintcapFormat = PRINTCAP_PLIST;
3432
else if (!_cups_strcasecmp(value, "solaris"))
3433
PrintcapFormat = PRINTCAP_SOLARIS;
3436
cupsdLogMessage(CUPSD_LOG_ERROR,
3437
"Unknown PrintcapFormat \"%s\" on line %d of %s.",
3438
value, linenum, CupsFilesFile);
3439
if (FatalErrors & CUPSD_FATAL_CONFIG)
3443
else if (!_cups_strcasecmp(line, "SystemGroup") && value)
3446
* SystemGroup (admin) group(s)...
3449
if (!parse_groups(value))
3451
cupsdLogMessage(CUPSD_LOG_ERROR,
3452
"Unknown SystemGroup \"%s\" on line %d of %s.", value,
3453
linenum, CupsFilesFile);
3454
if (FatalErrors & CUPSD_FATAL_CONFIG)
3458
else if (!_cups_strcasecmp(line, "User") && value)
3461
* User ID to run as...
3464
if (isdigit(value[0] & 255))
3466
int uid = atoi(value);
3470
cupsdLogMessage(CUPSD_LOG_ERROR,
3471
"Will not use User 0 as specified on line %d of %s "
3472
"for security reasons. You must use a non-"
3473
"privileged account instead.",
3474
linenum, CupsFilesFile);
3475
if (FatalErrors & CUPSD_FATAL_CONFIG)
3483
struct passwd *p; /* Password information */
3486
p = getpwnam(value);
3492
cupsdLogMessage(CUPSD_LOG_ERROR,
3493
"Will not use User %s (UID=0) as specified on line "
3494
"%d of %s for security reasons. You must use a "
3495
"non-privileged account instead.",
3496
value, linenum, CupsFilesFile);
3497
if (FatalErrors & CUPSD_FATAL_CONFIG)
3505
cupsdLogMessage(CUPSD_LOG_ERROR,
3506
"Unknown User \"%s\" on line %d of %s.",
3507
value, linenum, CupsFilesFile);
3508
if (FatalErrors & CUPSD_FATAL_CONFIG)
3513
else if (!parse_variable(CupsFilesFile, linenum, line, value,
3514
sizeof(cupsfiles_vars) / sizeof(cupsfiles_vars[0]),
3516
(FatalErrors & CUPSD_FATAL_CONFIG))
3525
* 'read_location()' - Read a <Location path> definition.
3528
static int /* O - New line number or 0 on error */
3529
read_location(cups_file_t *fp, /* I - Configuration file */
3530
char *location, /* I - Location name/path */
3531
int linenum) /* I - Current line number */
3533
cupsd_location_t *loc, /* New location */
3534
*parent; /* Parent location */
3535
char line[HTTP_MAX_BUFFER],
3537
*value, /* Value for directive */
3538
*valptr; /* Pointer into value */
3541
if ((parent = cupsdFindLocation(location)) != NULL)
3542
cupsdLogMessage(CUPSD_LOG_WARN, "Duplicate <Location %s> on line %d.",
3544
else if ((parent = cupsdNewLocation(location)) == NULL)
3548
cupsdAddLocation(parent);
3550
parent->limit = CUPSD_AUTH_LIMIT_ALL;
3555
while (cupsFileGetConf(fp, line, sizeof(line), &value, &linenum))
3558
* Decode the directive...
3561
if (!_cups_strcasecmp(line, "</Location>"))
3563
else if (!_cups_strcasecmp(line, "<Limit") ||
3564
!_cups_strcasecmp(line, "<LimitExcept"))
3568
cupsdLogMessage(CUPSD_LOG_ERROR, "Syntax error on line %d.", linenum);
3569
if (FatalErrors & CUPSD_FATAL_CONFIG)
3575
if ((loc = cupsdCopyLocation(parent)) == NULL)
3578
cupsdAddLocation(loc);
3583
for (valptr = value; !isspace(*valptr & 255) && *valptr; valptr ++);
3588
if (!strcmp(value, "ALL"))
3589
loc->limit = CUPSD_AUTH_LIMIT_ALL;
3590
else if (!strcmp(value, "GET"))
3591
loc->limit |= CUPSD_AUTH_LIMIT_GET;
3592
else if (!strcmp(value, "HEAD"))
3593
loc->limit |= CUPSD_AUTH_LIMIT_HEAD;
3594
else if (!strcmp(value, "OPTIONS"))
3595
loc->limit |= CUPSD_AUTH_LIMIT_OPTIONS;
3596
else if (!strcmp(value, "POST"))
3597
loc->limit |= CUPSD_AUTH_LIMIT_POST;
3598
else if (!strcmp(value, "PUT"))
3599
loc->limit |= CUPSD_AUTH_LIMIT_PUT;
3600
else if (!strcmp(value, "TRACE"))
3601
loc->limit |= CUPSD_AUTH_LIMIT_TRACE;
3603
cupsdLogMessage(CUPSD_LOG_WARN, "Unknown request type %s on line %d.",
3606
for (value = valptr; isspace(*value & 255); value ++);
3609
if (!_cups_strcasecmp(line, "<LimitExcept"))
3610
loc->limit = CUPSD_AUTH_LIMIT_ALL ^ loc->limit;
3612
parent->limit &= ~loc->limit;
3614
else if (!_cups_strcasecmp(line, "</Limit>") ||
3615
!_cups_strcasecmp(line, "</LimitExcept>"))
3619
cupsdLogMessage(CUPSD_LOG_ERROR, "Missing value on line %d.", linenum);
3620
if (FatalErrors & CUPSD_FATAL_CONFIG)
3623
else if (!parse_aaa(loc, line, value, linenum))
3625
cupsdLogMessage(CUPSD_LOG_ERROR,
3626
"Unknown Location directive %s on line %d.",
3628
if (FatalErrors & CUPSD_FATAL_CONFIG)
3633
cupsdLogMessage(CUPSD_LOG_ERROR,
3634
"Unexpected end-of-file at line %d while reading location.",
3637
return ((FatalErrors & CUPSD_FATAL_CONFIG) ? 0 : linenum);
3642
* 'read_policy()' - Read a <Policy name> definition.
3645
static int /* O - New line number or 0 on error */
3646
read_policy(cups_file_t *fp, /* I - Configuration file */
3647
char *policy, /* I - Location name/path */
3648
int linenum) /* I - Current line number */
3650
int i; /* Looping var */
3651
cupsd_policy_t *pol; /* Policy */
3652
cupsd_location_t *op; /* Policy operation */
3653
int num_ops; /* Number of IPP operations */
3654
ipp_op_t ops[100]; /* Operations */
3655
char line[HTTP_MAX_BUFFER],
3657
*value, /* Value for directive */
3658
*valptr; /* Pointer into value */
3662
* Create the policy...
3665
if ((pol = cupsdFindPolicy(policy)) != NULL)
3666
cupsdLogMessage(CUPSD_LOG_WARN, "Duplicate <Policy %s> on line %d.",
3668
else if ((pol = cupsdAddPolicy(policy)) == NULL)
3672
* Read from the file...
3678
while (cupsFileGetConf(fp, line, sizeof(line), &value, &linenum))
3681
* Decode the directive...
3684
if (!_cups_strcasecmp(line, "</Policy>"))
3687
cupsdLogMessage(CUPSD_LOG_WARN,
3688
"Missing </Limit> before </Policy> on line %d.",
3691
set_policy_defaults(pol);
3695
else if (!_cups_strcasecmp(line, "<Limit") && !op)
3699
cupsdLogMessage(CUPSD_LOG_ERROR, "Syntax error on line %d.", linenum);
3700
if (FatalErrors & CUPSD_FATAL_CONFIG)
3707
* Scan for IPP operation names...
3714
for (valptr = value; !isspace(*valptr & 255) && *valptr; valptr ++);
3719
if (num_ops < (int)(sizeof(ops) / sizeof(ops[0])))
3721
if (!_cups_strcasecmp(value, "All"))
3722
ops[num_ops] = IPP_ANY_OPERATION;
3723
else if ((ops[num_ops] = ippOpValue(value)) == IPP_BAD_OPERATION)
3724
cupsdLogMessage(CUPSD_LOG_ERROR,
3725
"Bad IPP operation name \"%s\" on line %d.",
3731
cupsdLogMessage(CUPSD_LOG_ERROR,
3732
"Too many operations listed on line %d.",
3735
for (value = valptr; isspace(*value & 255); value ++);
3739
* If none are specified, apply the policy to all operations...
3744
ops[0] = IPP_ANY_OPERATION;
3749
* Add a new policy for the first operation...
3752
op = cupsdAddPolicyOp(pol, NULL, ops[0]);
3754
else if (!_cups_strcasecmp(line, "</Limit>") && op)
3757
* Finish the current operation limit...
3763
* Copy the policy to the other operations...
3766
for (i = 1; i < num_ops; i ++)
3767
cupsdAddPolicyOp(pol, op, ops[i]);
3774
cupsdLogMessage(CUPSD_LOG_ERROR, "Missing value on line %d.", linenum);
3775
if (FatalErrors & CUPSD_FATAL_CONFIG)
3778
else if (!_cups_strcasecmp(line, "JobPrivateAccess") ||
3779
!_cups_strcasecmp(line, "JobPrivateValues") ||
3780
!_cups_strcasecmp(line, "SubscriptionPrivateAccess") ||
3781
!_cups_strcasecmp(line, "SubscriptionPrivateValues"))
3785
cupsdLogMessage(CUPSD_LOG_ERROR,
3786
"%s directive must appear outside <Limit>...</Limit> "
3787
"on line %d.", line, linenum);
3788
if (FatalErrors & CUPSD_FATAL_CONFIG)
3794
* Pull out whitespace-delimited values...
3800
* Find the end of the current value...
3803
for (valptr = value; !isspace(*valptr & 255) && *valptr; valptr ++);
3809
* Save it appropriately...
3812
if (!_cups_strcasecmp(line, "JobPrivateAccess"))
3815
* JobPrivateAccess {all|default|user/group list|@@ACL}
3818
if (!_cups_strcasecmp(value, "default"))
3820
cupsdAddString(&(pol->job_access), "@OWNER");
3821
cupsdAddString(&(pol->job_access), "@SYSTEM");
3824
cupsdAddString(&(pol->job_access), value);
3826
else if (!_cups_strcasecmp(line, "JobPrivateValues"))
3829
* JobPrivateValues {all|none|default|attribute list}
3832
if (!_cups_strcasecmp(value, "default"))
3834
cupsdAddString(&(pol->job_attrs), "job-name");
3835
cupsdAddString(&(pol->job_attrs), "job-originating-host-name");
3836
cupsdAddString(&(pol->job_attrs), "job-originating-user-name");
3837
cupsdAddString(&(pol->job_attrs), "phone");
3840
cupsdAddString(&(pol->job_attrs), value);
3842
else if (!_cups_strcasecmp(line, "SubscriptionPrivateAccess"))
3845
* SubscriptionPrivateAccess {all|default|user/group list|@@ACL}
3848
if (!_cups_strcasecmp(value, "default"))
3850
cupsdAddString(&(pol->sub_access), "@OWNER");
3851
cupsdAddString(&(pol->sub_access), "@SYSTEM");
3854
cupsdAddString(&(pol->sub_access), value);
3856
else /* if (!_cups_strcasecmp(line, "SubscriptionPrivateValues")) */
3859
* SubscriptionPrivateValues {all|none|default|attribute list}
3862
if (!_cups_strcasecmp(value, "default"))
3864
cupsdAddString(&(pol->sub_attrs), "notify-events");
3865
cupsdAddString(&(pol->sub_attrs), "notify-pull-method");
3866
cupsdAddString(&(pol->sub_attrs), "notify-recipient-uri");
3867
cupsdAddString(&(pol->sub_attrs), "notify-subscriber-user-name");
3868
cupsdAddString(&(pol->sub_attrs), "notify-user-data");
3871
cupsdAddString(&(pol->sub_attrs), value);
3875
* Find the next string on the line...
3878
for (value = valptr; isspace(*value & 255); value ++);
3884
cupsdLogMessage(CUPSD_LOG_ERROR,
3885
"Missing <Limit ops> directive before %s on line %d.",
3887
if (FatalErrors & CUPSD_FATAL_CONFIG)
3890
else if (!parse_aaa(op, line, value, linenum))
3892
cupsdLogMessage(CUPSD_LOG_ERROR,
3893
"Unknown Policy Limit directive %s on line %d.",
3896
if (FatalErrors & CUPSD_FATAL_CONFIG)
3901
cupsdLogMessage(CUPSD_LOG_ERROR,
3902
"Unexpected end-of-file at line %d while reading policy "
3903
"\"%s\".", linenum, policy);
3905
return ((FatalErrors & CUPSD_FATAL_CONFIG) ? 0 : linenum);
3910
* 'set_policy_defaults()' - Set default policy values as needed.
3914
set_policy_defaults(cupsd_policy_t *pol)/* I - Policy */
3916
cupsd_location_t *op; /* Policy operation */
3920
* Verify that we have an explicit policy for Validate-Job, Cancel-Jobs,
3921
* Cancel-My-Jobs, Close-Job, and CUPS-Get-Document, which ensures that
3922
* upgrades do not introduce new security issues...
3925
if ((op = cupsdFindPolicyOp(pol, IPP_VALIDATE_JOB)) == NULL ||
3926
op->op == IPP_ANY_OPERATION)
3928
if ((op = cupsdFindPolicyOp(pol, IPP_PRINT_JOB)) != NULL &&
3929
op->op != IPP_ANY_OPERATION)
3932
* Add a new limit for Validate-Job using the Print-Job limit as a
3936
cupsdLogMessage(CUPSD_LOG_WARN,
3937
"No limit for Validate-Job defined in policy %s "
3938
"- using Print-Job's policy.", pol->name);
3940
cupsdAddPolicyOp(pol, op, IPP_VALIDATE_JOB);
3943
cupsdLogMessage(CUPSD_LOG_WARN,
3944
"No limit for Validate-Job defined in policy %s "
3945
"and no suitable template found.", pol->name);
3948
if ((op = cupsdFindPolicyOp(pol, IPP_CANCEL_JOBS)) == NULL ||
3949
op->op == IPP_ANY_OPERATION)
3951
if ((op = cupsdFindPolicyOp(pol, IPP_PAUSE_PRINTER)) != NULL &&
3952
op->op != IPP_ANY_OPERATION)
3955
* Add a new limit for Cancel-Jobs using the Pause-Printer limit as a
3959
cupsdLogMessage(CUPSD_LOG_WARN,
3960
"No limit for Cancel-Jobs defined in policy %s "
3961
"- using Pause-Printer's policy.", pol->name);
3963
cupsdAddPolicyOp(pol, op, IPP_CANCEL_JOBS);
3966
cupsdLogMessage(CUPSD_LOG_WARN,
3967
"No limit for Cancel-Jobs defined in policy %s "
3968
"and no suitable template found.", pol->name);
3971
if ((op = cupsdFindPolicyOp(pol, IPP_CANCEL_MY_JOBS)) == NULL ||
3972
op->op == IPP_ANY_OPERATION)
3974
if ((op = cupsdFindPolicyOp(pol, IPP_SEND_DOCUMENT)) != NULL &&
3975
op->op != IPP_ANY_OPERATION)
3978
* Add a new limit for Cancel-My-Jobs using the Send-Document limit as
3982
cupsdLogMessage(CUPSD_LOG_WARN,
3983
"No limit for Cancel-My-Jobs defined in policy %s "
3984
"- using Send-Document's policy.", pol->name);
3986
cupsdAddPolicyOp(pol, op, IPP_CANCEL_MY_JOBS);
3989
cupsdLogMessage(CUPSD_LOG_WARN,
3990
"No limit for Cancel-My-Jobs defined in policy %s "
3991
"and no suitable template found.", pol->name);
3994
if ((op = cupsdFindPolicyOp(pol, IPP_CLOSE_JOB)) == NULL ||
3995
op->op == IPP_ANY_OPERATION)
3997
if ((op = cupsdFindPolicyOp(pol, IPP_SEND_DOCUMENT)) != NULL &&
3998
op->op != IPP_ANY_OPERATION)
4001
* Add a new limit for Close-Job using the Send-Document limit as a
4005
cupsdLogMessage(CUPSD_LOG_WARN,
4006
"No limit for Close-Job defined in policy %s "
4007
"- using Send-Document's policy.", pol->name);
4009
cupsdAddPolicyOp(pol, op, IPP_CLOSE_JOB);
4012
cupsdLogMessage(CUPSD_LOG_WARN,
4013
"No limit for Close-Job defined in policy %s "
4014
"and no suitable template found.", pol->name);
4017
if ((op = cupsdFindPolicyOp(pol, CUPS_GET_DOCUMENT)) == NULL ||
4018
op->op == IPP_ANY_OPERATION)
4020
if ((op = cupsdFindPolicyOp(pol, IPP_SEND_DOCUMENT)) != NULL &&
4021
op->op != IPP_ANY_OPERATION)
4024
* Add a new limit for CUPS-Get-Document using the Send-Document
4025
* limit as a template...
4028
cupsdLogMessage(CUPSD_LOG_WARN,
4029
"No limit for CUPS-Get-Document defined in policy %s "
4030
"- using Send-Document's policy.", pol->name);
4032
cupsdAddPolicyOp(pol, op, CUPS_GET_DOCUMENT);
4035
cupsdLogMessage(CUPSD_LOG_WARN,
4036
"No limit for CUPS-Get-Document defined in policy %s "
4037
"and no suitable template found.", pol->name);
4041
* Verify we have JobPrivateAccess, JobPrivateValues,
4042
* SubscriptionPrivateAccess, and SubscriptionPrivateValues in the policy.
4045
if (!pol->job_access)
4047
cupsdLogMessage(CUPSD_LOG_WARN,
4048
"No JobPrivateAccess defined in policy %s "
4049
"- using defaults.", pol->name);
4050
cupsdAddString(&(pol->job_access), "@OWNER");
4051
cupsdAddString(&(pol->job_access), "@SYSTEM");
4054
if (!pol->job_attrs)
4056
cupsdLogMessage(CUPSD_LOG_WARN,
4057
"No JobPrivateValues defined in policy %s "
4058
"- using defaults.", pol->name);
4059
cupsdAddString(&(pol->job_attrs), "job-name");
4060
cupsdAddString(&(pol->job_attrs), "job-originating-host-name");
4061
cupsdAddString(&(pol->job_attrs), "job-originating-user-name");
4062
cupsdAddString(&(pol->job_attrs), "phone");
4065
if (!pol->sub_access)
4067
cupsdLogMessage(CUPSD_LOG_WARN,
4068
"No SubscriptionPrivateAccess defined in policy %s "
4069
"- using defaults.", pol->name);
4070
cupsdAddString(&(pol->sub_access), "@OWNER");
4071
cupsdAddString(&(pol->sub_access), "@SYSTEM");
4074
if (!pol->sub_attrs)
4076
cupsdLogMessage(CUPSD_LOG_WARN,
4077
"No SubscriptionPrivateValues defined in policy %s "
4078
"- using defaults.", pol->name);
4079
cupsdAddString(&(pol->sub_attrs), "notify-events");
4080
cupsdAddString(&(pol->sub_attrs), "notify-pull-method");
4081
cupsdAddString(&(pol->sub_attrs), "notify-recipient-uri");
4082
cupsdAddString(&(pol->sub_attrs), "notify-subscriber-user-name");
4083
cupsdAddString(&(pol->sub_attrs), "notify-user-data");
4089
* End of "$Id: conf.c 11201 2013-07-26 21:27:27Z msweet $".