]> git.ipfire.org Git - thirdparty/cups.git/blob - scheduler/conf.c
Merge changes from CUPS 1.5svn-r9717.
[thirdparty/cups.git] / scheduler / conf.c
1 /*
2 * "$Id: conf.c 9352 2010-11-06 04:55:26Z mike $"
3 *
4 * Configuration routines for the CUPS scheduler.
5 *
6 * Copyright 2007-2011 by Apple Inc.
7 * Copyright 1997-2007 by Easy Software Products, all rights reserved.
8 *
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/".
14 *
15 * Contents:
16 *
17 * cupsdAddAlias() - Add a host alias.
18 * cupsdCheckPermissions() - Fix the mode and ownership of a file or
19 * directory.
20 * cupsdFreeAliases() - Free all of the alias entries.
21 * cupsdReadConfiguration() - Read the cupsd.conf file.
22 * get_address() - Get an address + port number from a line.
23 * get_addr_and_mask() - Get an IP address and netmask.
24 * parse_aaa() - Parse authentication, authorization, and access
25 * control lines.
26 * parse_fatal_errors() - Parse FatalErrors values in a string.
27 * parse_groups() - Parse system group names in a string.
28 * parse_protocols() - Parse browse protocols in a string.
29 * read_configuration() - Read a configuration file.
30 * read_location() - Read a <Location path> definition.
31 * read_policy() - Read a <Policy name> definition.
32 * set_policy_defaults() - Set default policy values as needed.
33 */
34
35 /*
36 * Include necessary headers...
37 */
38
39 #include "cupsd.h"
40 #include <stdarg.h>
41 #include <grp.h>
42 #include <sys/utsname.h>
43 #include <syslog.h>
44
45 #ifdef HAVE_LIBPAPER
46 # include <paper.h>
47 #endif /* HAVE_LIBPAPER */
48
49
50 /*
51 * Possibly missing network definitions...
52 */
53
54 #ifndef INADDR_NONE
55 # define INADDR_NONE 0xffffffff
56 #endif /* !INADDR_NONE */
57
58
59 /*
60 * Configuration variable structure...
61 */
62
63 typedef enum
64 {
65 CUPSD_VARTYPE_INTEGER, /* Integer option */
66 CUPSD_VARTYPE_STRING, /* String option */
67 CUPSD_VARTYPE_BOOLEAN, /* Boolean option */
68 CUPSD_VARTYPE_PATHNAME /* File/directory name option */
69 } cupsd_vartype_t;
70
71 typedef struct
72 {
73 char *name; /* Name of variable */
74 void *ptr; /* Pointer to variable */
75 cupsd_vartype_t type; /* Type (int, string, address) */
76 } cupsd_var_t;
77
78
79 /*
80 * Local globals...
81 */
82
83 static const cupsd_var_t variables[] =
84 {
85 { "AccessLog", &AccessLog, CUPSD_VARTYPE_STRING },
86 { "AutoPurgeJobs", &JobAutoPurge, CUPSD_VARTYPE_BOOLEAN },
87 #ifdef HAVE_DNSSD
88 { "BrowseDNSSDRegType", &DNSSDRegType, CUPSD_VARTYPE_STRING },
89 #endif /* HAVE_DNSSD */
90 { "BrowseInterval", &BrowseInterval, CUPSD_VARTYPE_INTEGER },
91 #ifdef HAVE_LDAP
92 { "BrowseLDAPBindDN", &BrowseLDAPBindDN, CUPSD_VARTYPE_STRING },
93 # ifdef HAVE_LDAP_SSL
94 { "BrowseLDAPCACertFile", &BrowseLDAPCACertFile, CUPSD_VARTYPE_PATHNAME },
95 # endif /* HAVE_LDAP_SSL */
96 { "BrowseLDAPDN", &BrowseLDAPDN, CUPSD_VARTYPE_STRING },
97 { "BrowseLDAPPassword", &BrowseLDAPPassword, CUPSD_VARTYPE_STRING },
98 { "BrowseLDAPServer", &BrowseLDAPServer, CUPSD_VARTYPE_STRING },
99 #endif /* HAVE_LDAP */
100 { "BrowseLocalOptions", &BrowseLocalOptions, CUPSD_VARTYPE_STRING },
101 { "BrowsePort", &BrowsePort, CUPSD_VARTYPE_INTEGER },
102 { "BrowseRemoteOptions", &BrowseRemoteOptions, CUPSD_VARTYPE_STRING },
103 { "BrowseShortNames", &BrowseShortNames, CUPSD_VARTYPE_BOOLEAN },
104 { "BrowseTimeout", &BrowseTimeout, CUPSD_VARTYPE_INTEGER },
105 { "BrowseWebIF", &BrowseWebIF, CUPSD_VARTYPE_BOOLEAN },
106 { "Browsing", &Browsing, CUPSD_VARTYPE_BOOLEAN },
107 { "CacheDir", &CacheDir, CUPSD_VARTYPE_STRING },
108 { "Classification", &Classification, CUPSD_VARTYPE_STRING },
109 { "ClassifyOverride", &ClassifyOverride, CUPSD_VARTYPE_BOOLEAN },
110 { "ConfigFilePerm", &ConfigFilePerm, CUPSD_VARTYPE_INTEGER },
111 { "DataDir", &DataDir, CUPSD_VARTYPE_STRING },
112 { "DefaultLanguage", &DefaultLanguage, CUPSD_VARTYPE_STRING },
113 { "DefaultLeaseDuration", &DefaultLeaseDuration, CUPSD_VARTYPE_INTEGER },
114 { "DefaultPaperSize", &DefaultPaperSize, CUPSD_VARTYPE_STRING },
115 { "DefaultPolicy", &DefaultPolicy, CUPSD_VARTYPE_STRING },
116 { "DefaultShared", &DefaultShared, CUPSD_VARTYPE_BOOLEAN },
117 { "DirtyCleanInterval", &DirtyCleanInterval, CUPSD_VARTYPE_INTEGER },
118 { "DocumentRoot", &DocumentRoot, CUPSD_VARTYPE_STRING },
119 { "ErrorLog", &ErrorLog, CUPSD_VARTYPE_STRING },
120 { "ErrorPolicy", &ErrorPolicy, CUPSD_VARTYPE_STRING },
121 { "FileDevice", &FileDevice, CUPSD_VARTYPE_BOOLEAN },
122 { "FilterLimit", &FilterLimit, CUPSD_VARTYPE_INTEGER },
123 { "FilterNice", &FilterNice, CUPSD_VARTYPE_INTEGER },
124 { "FontPath", &FontPath, CUPSD_VARTYPE_STRING },
125 { "HideImplicitMembers", &HideImplicitMembers, CUPSD_VARTYPE_BOOLEAN },
126 { "ImplicitClasses", &ImplicitClasses, CUPSD_VARTYPE_BOOLEAN },
127 { "ImplicitAnyClasses", &ImplicitAnyClasses, CUPSD_VARTYPE_BOOLEAN },
128 { "JobKillDelay", &JobKillDelay, CUPSD_VARTYPE_INTEGER },
129 { "JobRetryLimit", &JobRetryLimit, CUPSD_VARTYPE_INTEGER },
130 { "JobRetryInterval", &JobRetryInterval, CUPSD_VARTYPE_INTEGER },
131 { "KeepAliveTimeout", &KeepAliveTimeout, CUPSD_VARTYPE_INTEGER },
132 { "KeepAlive", &KeepAlive, CUPSD_VARTYPE_BOOLEAN },
133 #ifdef HAVE_LAUNCHD
134 { "LaunchdTimeout", &LaunchdTimeout, CUPSD_VARTYPE_INTEGER },
135 #endif /* HAVE_LAUNCHD */
136 { "LimitRequestBody", &MaxRequestSize, CUPSD_VARTYPE_INTEGER },
137 { "ListenBackLog", &ListenBackLog, CUPSD_VARTYPE_INTEGER },
138 { "LogDebugHistory", &LogDebugHistory, CUPSD_VARTYPE_INTEGER },
139 { "LogFilePerm", &LogFilePerm, CUPSD_VARTYPE_INTEGER },
140 { "LPDConfigFile", &LPDConfigFile, CUPSD_VARTYPE_STRING },
141 { "MaxActiveJobs", &MaxActiveJobs, CUPSD_VARTYPE_INTEGER },
142 { "MaxClients", &MaxClients, CUPSD_VARTYPE_INTEGER },
143 { "MaxClientsPerHost", &MaxClientsPerHost, CUPSD_VARTYPE_INTEGER },
144 { "MaxCopies", &MaxCopies, CUPSD_VARTYPE_INTEGER },
145 { "MaxEvents", &MaxEvents, CUPSD_VARTYPE_INTEGER },
146 { "MaxJobs", &MaxJobs, CUPSD_VARTYPE_INTEGER },
147 { "MaxJobsPerPrinter", &MaxJobsPerPrinter, CUPSD_VARTYPE_INTEGER },
148 { "MaxJobsPerUser", &MaxJobsPerUser, CUPSD_VARTYPE_INTEGER },
149 { "MaxLeaseDuration", &MaxLeaseDuration, CUPSD_VARTYPE_INTEGER },
150 { "MaxLogSize", &MaxLogSize, CUPSD_VARTYPE_INTEGER },
151 { "MaxRequestSize", &MaxRequestSize, CUPSD_VARTYPE_INTEGER },
152 { "MaxSubscriptions", &MaxSubscriptions, CUPSD_VARTYPE_INTEGER },
153 { "MaxSubscriptionsPerJob", &MaxSubscriptionsPerJob, CUPSD_VARTYPE_INTEGER },
154 { "MaxSubscriptionsPerPrinter",&MaxSubscriptionsPerPrinter, CUPSD_VARTYPE_INTEGER },
155 { "MaxSubscriptionsPerUser", &MaxSubscriptionsPerUser, CUPSD_VARTYPE_INTEGER },
156 { "MultipleOperationTimeout", &MultipleOperationTimeout, CUPSD_VARTYPE_INTEGER },
157 { "PageLog", &PageLog, CUPSD_VARTYPE_STRING },
158 { "PageLogFormat", &PageLogFormat, CUPSD_VARTYPE_STRING },
159 { "PreserveJobFiles", &JobFiles, CUPSD_VARTYPE_BOOLEAN },
160 { "PreserveJobHistory", &JobHistory, CUPSD_VARTYPE_BOOLEAN },
161 { "Printcap", &Printcap, CUPSD_VARTYPE_STRING },
162 { "PrintcapGUI", &PrintcapGUI, CUPSD_VARTYPE_STRING },
163 { "ReloadTimeout", &ReloadTimeout, CUPSD_VARTYPE_INTEGER },
164 { "RemoteRoot", &RemoteRoot, CUPSD_VARTYPE_STRING },
165 { "RequestRoot", &RequestRoot, CUPSD_VARTYPE_STRING },
166 { "RIPCache", &RIPCache, CUPSD_VARTYPE_STRING },
167 { "RootCertDuration", &RootCertDuration, CUPSD_VARTYPE_INTEGER },
168 { "ServerAdmin", &ServerAdmin, CUPSD_VARTYPE_STRING },
169 { "ServerBin", &ServerBin, CUPSD_VARTYPE_PATHNAME },
170 #ifdef HAVE_SSL
171 { "ServerCertificate", &ServerCertificate, CUPSD_VARTYPE_PATHNAME },
172 # if defined(HAVE_LIBSSL) || defined(HAVE_GNUTLS)
173 { "ServerKey", &ServerKey, CUPSD_VARTYPE_PATHNAME },
174 # endif /* HAVE_LIBSSL || HAVE_GNUTLS */
175 #endif /* HAVE_SSL */
176 { "ServerName", &ServerName, CUPSD_VARTYPE_STRING },
177 { "ServerRoot", &ServerRoot, CUPSD_VARTYPE_PATHNAME },
178 { "SMBConfigFile", &SMBConfigFile, CUPSD_VARTYPE_STRING },
179 { "StateDir", &StateDir, CUPSD_VARTYPE_STRING },
180 #ifdef HAVE_AUTHORIZATION_H
181 { "SystemGroupAuthKey", &SystemGroupAuthKey, CUPSD_VARTYPE_STRING },
182 #endif /* HAVE_AUTHORIZATION_H */
183 { "TempDir", &TempDir, CUPSD_VARTYPE_PATHNAME },
184 { "Timeout", &Timeout, CUPSD_VARTYPE_INTEGER },
185 { "UseNetworkDefault", &UseNetworkDefault, CUPSD_VARTYPE_BOOLEAN },
186 { "WebInterface", &WebInterface, CUPSD_VARTYPE_BOOLEAN }
187 };
188 #define NUM_VARS (sizeof(variables) / sizeof(variables[0]))
189
190
191 static const unsigned ones[4] =
192 {
193 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff
194 };
195 static const unsigned zeros[4] =
196 {
197 0x00000000, 0x00000000, 0x00000000, 0x00000000
198 };
199
200
201 /*
202 * Local functions...
203 */
204
205 static http_addrlist_t *get_address(const char *value, int defport);
206 static int get_addr_and_mask(const char *value, unsigned *ip,
207 unsigned *mask);
208 static int parse_aaa(cupsd_location_t *loc, char *line,
209 char *value, int linenum);
210 static int parse_fatal_errors(const char *s);
211 static int parse_groups(const char *s);
212 static int parse_protocols(const char *s);
213 static int read_configuration(cups_file_t *fp);
214 static int read_location(cups_file_t *fp, char *name, int linenum);
215 static int read_policy(cups_file_t *fp, char *name, int linenum);
216 static void set_policy_defaults(cupsd_policy_t *pol);
217
218
219 /*
220 * 'cupsdAddAlias()' - Add a host alias.
221 */
222
223 void
224 cupsdAddAlias(cups_array_t *aliases, /* I - Array of aliases */
225 const char *name) /* I - Name to add */
226 {
227 cupsd_alias_t *a; /* New alias */
228 size_t namelen; /* Length of name */
229
230
231 namelen = strlen(name);
232
233 if ((a = (cupsd_alias_t *)malloc(sizeof(cupsd_alias_t) + namelen)) == NULL)
234 return;
235
236 a->namelen = namelen;
237 strcpy(a->name, name); /* OK since a->name is allocated */
238
239 cupsArrayAdd(aliases, a);
240 }
241
242
243 /*
244 * 'cupsdCheckPermissions()' - Fix the mode and ownership of a file or directory.
245 */
246
247 int /* O - 0 on success, -1 on error, 1 on warning */
248 cupsdCheckPermissions(
249 const char *filename, /* I - File/directory name */
250 const char *suffix, /* I - Additional file/directory name */
251 int mode, /* I - Permissions */
252 int user, /* I - Owner */
253 int group, /* I - Group */
254 int is_dir, /* I - 1 = directory, 0 = file */
255 int create_dir) /* I - 1 = create directory, -1 = create w/o logging, 0 = not */
256 {
257 int dir_created = 0; /* Did we create a directory? */
258 char pathname[1024]; /* File name with prefix */
259 struct stat fileinfo; /* Stat buffer */
260 int is_symlink; /* Is "filename" a symlink? */
261
262
263 /*
264 * Prepend the given root to the filename before testing it...
265 */
266
267 if (suffix)
268 {
269 snprintf(pathname, sizeof(pathname), "%s/%s", filename, suffix);
270 filename = pathname;
271 }
272
273 /*
274 * See if we can stat the file/directory...
275 */
276
277 if (lstat(filename, &fileinfo))
278 {
279 if (errno == ENOENT && create_dir)
280 {
281 if (create_dir > 0)
282 cupsdLogMessage(CUPSD_LOG_DEBUG, "Creating missing directory \"%s\"",
283 filename);
284
285 if (mkdir(filename, mode))
286 {
287 if (create_dir > 0)
288 cupsdLogMessage(CUPSD_LOG_ERROR,
289 "Unable to create directory \"%s\" - %s", filename,
290 strerror(errno));
291 else
292 syslog(LOG_ERR, "Unable to create directory \"%s\" - %s", filename,
293 strerror(errno));
294
295 return (-1);
296 }
297
298 dir_created = 1;
299 fileinfo.st_mode = mode | S_IFDIR;
300 }
301 else
302 return (create_dir ? -1 : 1);
303 }
304
305 if ((is_symlink = S_ISLNK(fileinfo.st_mode)) != 0)
306 {
307 if (stat(filename, &fileinfo))
308 {
309 cupsdLogMessage(CUPSD_LOG_ERROR, "\"%s\" is a bad symlink - %s",
310 filename, strerror(errno));
311 return (-1);
312 }
313 }
314
315 /*
316 * Make sure it's a regular file or a directory as needed...
317 */
318
319 if (!dir_created && !is_dir && !S_ISREG(fileinfo.st_mode))
320 {
321 cupsdLogMessage(CUPSD_LOG_ERROR, "\"%s\" is not a regular file.", filename);
322 return (-1);
323 }
324
325 if (!dir_created && is_dir && !S_ISDIR(fileinfo.st_mode))
326 {
327 if (create_dir >= 0)
328 cupsdLogMessage(CUPSD_LOG_ERROR, "\"%s\" is not a directory.", filename);
329 else
330 syslog(LOG_ERR, "\"%s\" is not a directory.", filename);
331
332 return (-1);
333 }
334
335 /*
336 * If the filename is a symlink, do not change permissions (STR #2937)...
337 */
338
339 if (is_symlink)
340 return (0);
341
342 /*
343 * Fix owner, group, and mode as needed...
344 */
345
346 if (dir_created || fileinfo.st_uid != user || fileinfo.st_gid != group)
347 {
348 if (create_dir >= 0)
349 cupsdLogMessage(CUPSD_LOG_DEBUG, "Repairing ownership of \"%s\"",
350 filename);
351
352 if (chown(filename, user, group) && !getuid())
353 {
354 if (create_dir >= 0)
355 cupsdLogMessage(CUPSD_LOG_ERROR,
356 "Unable to change ownership of \"%s\" - %s", filename,
357 strerror(errno));
358 else
359 syslog(LOG_ERR, "Unable to change ownership of \"%s\" - %s", filename,
360 strerror(errno));
361
362 return (1);
363 }
364 }
365
366 if (dir_created || (fileinfo.st_mode & 07777) != mode)
367 {
368 if (create_dir >= 0)
369 cupsdLogMessage(CUPSD_LOG_DEBUG, "Repairing access permissions of \"%s\"",
370 filename);
371
372 if (chmod(filename, mode))
373 {
374 if (create_dir >= 0)
375 cupsdLogMessage(CUPSD_LOG_ERROR,
376 "Unable to change permissions of \"%s\" - %s", filename,
377 strerror(errno));
378 else
379 syslog(LOG_ERR, "Unable to change permissions of \"%s\" - %s", filename,
380 strerror(errno));
381
382 return (1);
383 }
384 }
385
386 /*
387 * Everything is OK...
388 */
389
390 return (0);
391 }
392
393
394 /*
395 * 'cupsdFreeAliases()' - Free all of the alias entries.
396 */
397
398 void
399 cupsdFreeAliases(cups_array_t *aliases) /* I - Array of aliases */
400 {
401 cupsd_alias_t *a; /* Current alias */
402
403
404 for (a = (cupsd_alias_t *)cupsArrayFirst(aliases);
405 a;
406 a = (cupsd_alias_t *)cupsArrayNext(aliases))
407 free(a);
408
409 cupsArrayDelete(aliases);
410 }
411
412
413 /*
414 * 'cupsdReadConfiguration()' - Read the cupsd.conf file.
415 */
416
417 int /* O - 1 on success, 0 otherwise */
418 cupsdReadConfiguration(void)
419 {
420 int i; /* Looping var */
421 cups_file_t *fp; /* Configuration file */
422 int status; /* Return status */
423 char temp[1024], /* Temporary buffer */
424 mimedir[1024], /* MIME directory */
425 *slash; /* Directory separator */
426 cups_lang_t *language; /* Language */
427 struct passwd *user; /* Default user */
428 struct group *group; /* Default group */
429 char *old_serverroot, /* Old ServerRoot */
430 *old_requestroot; /* Old RequestRoot */
431 int old_remote_port; /* Old RemotePort */
432 const char *tmpdir; /* TMPDIR environment variable */
433 struct stat tmpinfo; /* Temporary directory info */
434 cupsd_policy_t *p; /* Policy */
435
436
437 /*
438 * Save the old root paths...
439 */
440
441 old_serverroot = NULL;
442 cupsdSetString(&old_serverroot, ServerRoot);
443 old_requestroot = NULL;
444 cupsdSetString(&old_requestroot, RequestRoot);
445
446 /*
447 * Reset the server configuration data...
448 */
449
450 cupsdDeleteAllLocations();
451
452 if (NumBrowsers > 0)
453 {
454 free(Browsers);
455 Browsers = NULL;
456
457 NumBrowsers = 0;
458 }
459
460 if (NumPolled > 0)
461 {
462 free(Polled);
463
464 NumPolled = 0;
465 }
466
467 if (NumRelays > 0)
468 {
469 for (i = 0; i < NumRelays; i ++)
470 cupsArrayDelete(Relays[i].from);
471
472 free(Relays);
473
474 NumRelays = 0;
475 }
476
477 cupsdDeleteAllListeners();
478
479 old_remote_port = RemotePort;
480 RemotePort = 0;
481
482 /*
483 * String options...
484 */
485
486 cupsdFreeAliases(ServerAlias);
487 ServerAlias = NULL;
488
489 cupsdClearString(&ServerName);
490 cupsdClearString(&ServerAdmin);
491 cupsdSetString(&ServerBin, CUPS_SERVERBIN);
492 cupsdSetString(&RequestRoot, CUPS_REQUESTS);
493 cupsdSetString(&CacheDir, CUPS_CACHEDIR);
494 cupsdSetString(&DataDir, CUPS_DATADIR);
495 cupsdSetString(&DocumentRoot, CUPS_DOCROOT);
496 cupsdSetString(&AccessLog, CUPS_LOGDIR "/access_log");
497 cupsdSetString(&ErrorLog, CUPS_LOGDIR "/error_log");
498 cupsdSetString(&PageLog, CUPS_LOGDIR "/page_log");
499 cupsdSetString(&PageLogFormat,
500 "%p %u %j %T %P %C %{job-billing} "
501 "%{job-originating-host-name} %{job-name} %{media} %{sides}");
502 cupsdSetString(&Printcap, CUPS_DEFAULT_PRINTCAP);
503 cupsdSetString(&PrintcapGUI, "/usr/bin/glpoptions");
504 cupsdSetString(&FontPath, CUPS_FONTPATH);
505 cupsdSetString(&RemoteRoot, "remroot");
506 cupsdSetString(&ServerHeader, "CUPS/1.4");
507 cupsdSetString(&StateDir, CUPS_STATEDIR);
508
509 if (!strcmp(CUPS_DEFAULT_PRINTCAP, "/etc/printers.conf"))
510 PrintcapFormat = PRINTCAP_SOLARIS;
511 else if (!strcmp(CUPS_DEFAULT_PRINTCAP,
512 "/Library/Preferences/org.cups.printers.plist"))
513 PrintcapFormat = PRINTCAP_PLIST;
514 else
515 PrintcapFormat = PRINTCAP_BSD;
516
517 strlcpy(temp, ConfigurationFile, sizeof(temp));
518 if ((slash = strrchr(temp, '/')) != NULL)
519 *slash = '\0';
520
521 cupsdSetString(&ServerRoot, temp);
522
523 cupsdClearString(&Classification);
524 ClassifyOverride = 0;
525
526 #ifdef HAVE_SSL
527 # ifdef HAVE_CDSASSL
528 cupsdSetString(&ServerCertificate, "/Library/Keychains/System.keychain");
529 # else
530 cupsdSetString(&ServerCertificate, "ssl/server.crt");
531 cupsdSetString(&ServerKey, "ssl/server.key");
532 # endif /* HAVE_CDSASSL */
533 #endif /* HAVE_SSL */
534
535 language = cupsLangDefault();
536
537 if (!strcmp(language->language, "C") || !strcmp(language->language, "POSIX"))
538 cupsdSetString(&DefaultLanguage, "en");
539 else
540 cupsdSetString(&DefaultLanguage, language->language);
541
542 cupsdClearString(&DefaultPaperSize);
543
544 cupsdSetString(&RIPCache, "8m");
545
546 cupsdSetString(&TempDir, NULL);
547
548 /*
549 * Find the default user...
550 */
551
552 if ((user = getpwnam(CUPS_DEFAULT_USER)) != NULL)
553 User = user->pw_uid;
554 else
555 {
556 /*
557 * Use the (historical) NFS nobody user ID (-2 as a 16-bit twos-
558 * complement number...)
559 */
560
561 User = 65534;
562 }
563
564 endpwent();
565
566 /*
567 * Find the default group...
568 */
569
570 group = getgrnam(CUPS_DEFAULT_GROUP);
571 endgrent();
572
573 if (group)
574 Group = group->gr_gid;
575 else
576 {
577 /*
578 * Fallback to group "nobody"...
579 */
580
581 group = getgrnam("nobody");
582 endgrent();
583
584 if (group)
585 Group = group->gr_gid;
586 else
587 {
588 /*
589 * Use the (historical) NFS nobody group ID (-2 as a 16-bit twos-
590 * complement number...)
591 */
592
593 Group = 65534;
594 }
595 }
596
597 /*
598 * Numeric options...
599 */
600
601 AccessLogLevel = CUPSD_ACCESSLOG_ACTIONS;
602 ConfigFilePerm = CUPS_DEFAULT_CONFIG_FILE_PERM;
603 FatalErrors = parse_fatal_errors(CUPS_DEFAULT_FATAL_ERRORS);
604 DefaultAuthType = CUPSD_AUTH_BASIC;
605 #ifdef HAVE_SSL
606 DefaultEncryption = HTTP_ENCRYPT_REQUIRED;
607 SSLOptions = CUPSD_SSL_NONE;
608 #endif /* HAVE_SSL */
609 DirtyCleanInterval = DEFAULT_KEEPALIVE;
610 JobKillDelay = DEFAULT_TIMEOUT;
611 JobRetryLimit = 5;
612 JobRetryInterval = 300;
613 FileDevice = FALSE;
614 FilterLevel = 0;
615 FilterLimit = 0;
616 FilterNice = 0;
617 HostNameLookups = FALSE;
618 ImplicitClasses = CUPS_DEFAULT_IMPLICIT_CLASSES;
619 ImplicitAnyClasses = FALSE;
620 HideImplicitMembers = TRUE;
621 KeepAlive = TRUE;
622 KeepAliveTimeout = DEFAULT_KEEPALIVE;
623 ListenBackLog = SOMAXCONN;
624 LogDebugHistory = 200;
625 LogFilePerm = CUPS_DEFAULT_LOG_FILE_PERM;
626 LogLevel = CUPSD_LOG_WARN;
627 LogTimeFormat = CUPSD_TIME_STANDARD;
628 MaxClients = 100;
629 MaxClientsPerHost = 0;
630 MaxLogSize = 1024 * 1024;
631 MaxRequestSize = 0;
632 MultipleOperationTimeout = DEFAULT_TIMEOUT;
633 ReloadTimeout = DEFAULT_KEEPALIVE;
634 RootCertDuration = 300;
635 Timeout = DEFAULT_TIMEOUT;
636 NumSystemGroups = 0;
637 WebInterface = CUPS_DEFAULT_WEBIF;
638
639 BrowseInterval = DEFAULT_INTERVAL;
640 BrowsePort = ippPort();
641 BrowseLocalProtocols = parse_protocols(CUPS_DEFAULT_BROWSE_LOCAL_PROTOCOLS);
642 BrowseRemoteProtocols = parse_protocols(CUPS_DEFAULT_BROWSE_REMOTE_PROTOCOLS);
643 BrowseShortNames = CUPS_DEFAULT_BROWSE_SHORT_NAMES;
644 BrowseTimeout = DEFAULT_TIMEOUT;
645 BrowseWebIF = FALSE;
646 Browsing = CUPS_DEFAULT_BROWSING;
647 DefaultShared = CUPS_DEFAULT_DEFAULT_SHARED;
648
649 #ifdef HAVE_DNSSD
650 cupsdSetString(&DNSSDRegType, "_ipp._tcp,_cups");
651 #endif /* HAVE_DNSSD */
652
653 cupsdSetString(&LPDConfigFile, CUPS_DEFAULT_LPD_CONFIG_FILE);
654 cupsdSetString(&SMBConfigFile, CUPS_DEFAULT_SMB_CONFIG_FILE);
655
656 cupsdClearString(&BrowseLocalOptions);
657 cupsdClearString(&BrowseRemoteOptions);
658
659 cupsdSetString(&ErrorPolicy, "stop-printer");
660
661 #ifdef HAVE_LDAP
662 cupsdClearString(&BrowseLDAPBindDN);
663 cupsdClearString(&BrowseLDAPDN);
664 cupsdClearString(&BrowseLDAPPassword);
665 cupsdClearString(&BrowseLDAPServer);
666 # ifdef HAVE_LDAP_SSL
667 cupsdClearString(&BrowseLDAPCACertFile);
668 # endif /* HAVE_LDAP_SSL */
669 #endif /* HAVE_LDAP */
670
671 JobHistory = DEFAULT_HISTORY;
672 JobFiles = DEFAULT_FILES;
673 JobAutoPurge = 0;
674 MaxJobs = 500;
675 MaxActiveJobs = 0;
676 MaxJobsPerUser = 0;
677 MaxJobsPerPrinter = 0;
678 MaxCopies = CUPS_DEFAULT_MAX_COPIES;
679
680 cupsdDeleteAllPolicies();
681 cupsdClearString(&DefaultPolicy);
682
683 #ifdef HAVE_AUTHORIZATION_H
684 cupsdClearString(&SystemGroupAuthKey);
685 #endif /* HAVE_AUTHORIZATION_H */
686
687 MaxSubscriptions = 100;
688 MaxSubscriptionsPerJob = 0;
689 MaxSubscriptionsPerPrinter = 0;
690 MaxSubscriptionsPerUser = 0;
691 DefaultLeaseDuration = 86400;
692 MaxLeaseDuration = 0;
693
694 #ifdef HAVE_LAUNCHD
695 LaunchdTimeout = DEFAULT_TIMEOUT + 10;
696 #endif /* HAVE_LAUNCHD */
697
698 /*
699 * Setup environment variables...
700 */
701
702 cupsdInitEnv();
703
704 /*
705 * Read the configuration file...
706 */
707
708 if ((fp = cupsFileOpen(ConfigurationFile, "r")) == NULL)
709 return (0);
710
711 status = read_configuration(fp);
712
713 cupsFileClose(fp);
714
715 if (!status)
716 return (0);
717
718 RunUser = getuid();
719
720 cupsdLogMessage(CUPSD_LOG_INFO, "Remote access is %s.",
721 RemotePort ? "enabled" : "disabled");
722
723 if (!RemotePort)
724 BrowseLocalProtocols = 0; /* Disable sharing - no remote access */
725
726 /*
727 * See if the ServerName is an IP address...
728 */
729
730 if (ServerName)
731 {
732 if (!ServerAlias)
733 ServerAlias = cupsArrayNew(NULL, NULL);
734
735 cupsdLogMessage(CUPSD_LOG_DEBUG, "Added auto ServerAlias %s", ServerName);
736 }
737 else
738 {
739 if (gethostname(temp, sizeof(temp)))
740 {
741 cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to get hostname: %s",
742 strerror(errno));
743 strlcpy(temp, "localhost", sizeof(temp));
744 }
745
746 cupsdSetString(&ServerName, temp);
747
748 if (!ServerAlias)
749 ServerAlias = cupsArrayNew(NULL, NULL);
750
751 cupsdAddAlias(ServerAlias, temp);
752 cupsdLogMessage(CUPSD_LOG_DEBUG, "Added auto ServerAlias %s", temp);
753
754 if (HostNameLookups || RemotePort)
755 {
756 struct hostent *host; /* Host entry to get FQDN */
757
758 if ((host = gethostbyname(temp)) != NULL)
759 {
760 if (strcasecmp(temp, host->h_name))
761 {
762 cupsdSetString(&ServerName, host->h_name);
763 cupsdAddAlias(ServerAlias, host->h_name);
764 cupsdLogMessage(CUPSD_LOG_DEBUG, "Added auto ServerAlias %s",
765 host->h_name);
766 }
767
768 if (host->h_aliases)
769 {
770 for (i = 0; host->h_aliases[i]; i ++)
771 if (strcasecmp(temp, host->h_aliases[i]))
772 {
773 cupsdAddAlias(ServerAlias, host->h_aliases[i]);
774 cupsdLogMessage(CUPSD_LOG_DEBUG, "Added auto ServerAlias %s",
775 host->h_aliases[i]);
776 }
777 }
778 }
779 }
780
781 /*
782 * Make sure we have the base hostname added as an alias, too!
783 */
784
785 if ((slash = strchr(temp, '.')) != NULL)
786 {
787 *slash = '\0';
788 cupsdAddAlias(ServerAlias, temp);
789 cupsdLogMessage(CUPSD_LOG_DEBUG, "Added auto ServerAlias %s", temp);
790 }
791 }
792
793 for (slash = ServerName; isdigit(*slash & 255) || *slash == '.'; slash ++);
794
795 ServerNameIsIP = !*slash;
796
797 /*
798 * Make sure ServerAdmin is initialized...
799 */
800
801 if (!ServerAdmin)
802 cupsdSetStringf(&ServerAdmin, "root@%s", ServerName);
803
804 /*
805 * Use the default system group if none was supplied in cupsd.conf...
806 */
807
808 if (NumSystemGroups == 0)
809 {
810 if (!parse_groups(CUPS_DEFAULT_SYSTEM_GROUPS))
811 {
812 /*
813 * Find the group associated with GID 0...
814 */
815
816 group = getgrgid(0);
817 endgrent();
818
819 if (group != NULL)
820 cupsdSetString(&SystemGroups[0], group->gr_name);
821 else
822 cupsdSetString(&SystemGroups[0], "unknown");
823
824 SystemGroupIDs[0] = 0;
825 NumSystemGroups = 1;
826 }
827 }
828
829 /*
830 * Get the access control list for browsing...
831 */
832
833 BrowseACL = cupsdFindLocation("CUPS_INTERNAL_BROWSE_ACL");
834
835 /*
836 * Open the system log for cupsd if necessary...
837 */
838
839 #ifdef HAVE_VSYSLOG
840 if (!strcmp(AccessLog, "syslog") ||
841 !strcmp(ErrorLog, "syslog") ||
842 !strcmp(PageLog, "syslog"))
843 openlog("cupsd", LOG_PID | LOG_NOWAIT | LOG_NDELAY, LOG_LPR);
844 #endif /* HAVE_VSYSLOG */
845
846 /*
847 * Make sure each of the log files exists and gets rotated as necessary...
848 */
849
850 if (!strcmp(AccessLog, "syslog"))
851 cupsdCheckLogFile(&AccessFile, AccessLog);
852
853 if (!strcmp(ErrorLog, "syslog"))
854 cupsdCheckLogFile(&ErrorFile, ErrorLog);
855
856 if (!strcmp(PageLog, "syslog"))
857 cupsdCheckLogFile(&PageFile, PageLog);
858
859 /*
860 * Log the configuration file that was used...
861 */
862
863 cupsdLogMessage(CUPSD_LOG_INFO, "Loaded configuration file \"%s\"",
864 ConfigurationFile);
865
866 /*
867 * Validate the Group and SystemGroup settings - they cannot be the same,
868 * otherwise the CGI programs will be able to authenticate as root without
869 * a password!
870 */
871
872 if (!RunUser)
873 {
874 for (i = 0; i < NumSystemGroups; i ++)
875 if (Group == SystemGroupIDs[i])
876 break;
877
878 if (i < NumSystemGroups)
879 {
880 /*
881 * Log the error and reset the group to a safe value...
882 */
883
884 cupsdLogMessage(CUPSD_LOG_NOTICE,
885 "Group and SystemGroup cannot use the same groups.");
886 cupsdLogMessage(CUPSD_LOG_INFO, "Resetting Group to \"nobody\"...");
887
888 group = getgrnam("nobody");
889 endgrent();
890
891 if (group != NULL)
892 Group = group->gr_gid;
893 else
894 {
895 /*
896 * Use the (historical) NFS nobody group ID (-2 as a 16-bit twos-
897 * complement number...)
898 */
899
900 Group = 65534;
901 }
902 }
903 }
904
905 /*
906 * Check that we have at least one listen/port line; if not, report this
907 * as an error and exit!
908 */
909
910 if (cupsArrayCount(Listeners) == 0)
911 {
912 /*
913 * No listeners!
914 */
915
916 cupsdLogMessage(CUPSD_LOG_EMERG,
917 "No valid Listen or Port lines were found in the "
918 "configuration file.");
919
920 /*
921 * Commit suicide...
922 */
923
924 cupsdEndProcess(getpid(), 0);
925 }
926
927 /*
928 * Set the default locale using the language and charset...
929 */
930
931 cupsdSetStringf(&DefaultLocale, "%s.UTF-8", DefaultLanguage);
932
933 /*
934 * Update all relative filenames to include the full path from ServerRoot...
935 */
936
937 if (DocumentRoot[0] != '/')
938 cupsdSetStringf(&DocumentRoot, "%s/%s", ServerRoot, DocumentRoot);
939
940 if (RequestRoot[0] != '/')
941 cupsdSetStringf(&RequestRoot, "%s/%s", ServerRoot, RequestRoot);
942
943 if (ServerBin[0] != '/')
944 cupsdSetStringf(&ServerBin, "%s/%s", ServerRoot, ServerBin);
945
946 if (StateDir[0] != '/')
947 cupsdSetStringf(&StateDir, "%s/%s", ServerRoot, StateDir);
948
949 if (CacheDir[0] != '/')
950 cupsdSetStringf(&CacheDir, "%s/%s", ServerRoot, CacheDir);
951
952 #ifdef HAVE_SSL
953 if (ServerCertificate[0] != '/')
954 cupsdSetStringf(&ServerCertificate, "%s/%s", ServerRoot, ServerCertificate);
955
956 if (!strncmp(ServerRoot, ServerCertificate, strlen(ServerRoot)) &&
957 cupsdCheckPermissions(ServerCertificate, NULL, 0600, RunUser, Group,
958 0, 0) < 0 &&
959 (FatalErrors & CUPSD_FATAL_PERMISSIONS))
960 return (0);
961
962 # if defined(HAVE_LIBSSL) || defined(HAVE_GNUTLS)
963 if (ServerKey[0] != '/')
964 cupsdSetStringf(&ServerKey, "%s/%s", ServerRoot, ServerKey);
965
966 if (!strncmp(ServerRoot, ServerKey, strlen(ServerRoot)) &&
967 cupsdCheckPermissions(ServerKey, NULL, 0600, RunUser, Group, 0, 0) < 0 &&
968 (FatalErrors & CUPSD_FATAL_PERMISSIONS))
969 return (0);
970 # endif /* HAVE_LIBSSL || HAVE_GNUTLS */
971 #endif /* HAVE_SSL */
972
973 /*
974 * Make sure that directories and config files are owned and
975 * writable by the user and group in the cupsd.conf file...
976 */
977
978 snprintf(temp, sizeof(temp), "%s/rss", CacheDir);
979
980 if ((cupsdCheckPermissions(RequestRoot, NULL, 0710, RunUser,
981 Group, 1, 1) < 0 ||
982 cupsdCheckPermissions(CacheDir, NULL, 0775, RunUser,
983 Group, 1, 1) < 0 ||
984 cupsdCheckPermissions(temp, NULL, 0775, RunUser,
985 Group, 1, 1) < 0 ||
986 cupsdCheckPermissions(StateDir, NULL, 0755, RunUser,
987 Group, 1, 1) < 0 ||
988 cupsdCheckPermissions(StateDir, "certs", RunUser ? 0711 : 0511, User,
989 SystemGroupIDs[0], 1, 1) < 0 ||
990 cupsdCheckPermissions(ServerRoot, NULL, 0755, RunUser,
991 Group, 1, 0) < 0 ||
992 cupsdCheckPermissions(ServerRoot, "ppd", 0755, RunUser,
993 Group, 1, 1) < 0 ||
994 cupsdCheckPermissions(ServerRoot, "ssl", 0700, RunUser,
995 Group, 1, 0) < 0 ||
996 cupsdCheckPermissions(ServerRoot, "cupsd.conf", ConfigFilePerm, RunUser,
997 Group, 0, 0) < 0 ||
998 cupsdCheckPermissions(ServerRoot, "classes.conf", 0600, RunUser,
999 Group, 0, 0) < 0 ||
1000 cupsdCheckPermissions(ServerRoot, "printers.conf", 0600, RunUser,
1001 Group, 0, 0) < 0 ||
1002 cupsdCheckPermissions(ServerRoot, "passwd.md5", 0600, User,
1003 Group, 0, 0) < 0) &&
1004 (FatalErrors & CUPSD_FATAL_PERMISSIONS))
1005 return (0);
1006
1007 /*
1008 * Update TempDir to the default if it hasn't been set already...
1009 */
1010
1011 if (!TempDir)
1012 {
1013 if ((tmpdir = getenv("TMPDIR")) != NULL)
1014 {
1015 /*
1016 * TMPDIR is defined, see if it is OK for us to use...
1017 */
1018
1019 if (stat(tmpdir, &tmpinfo))
1020 cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to access TMPDIR (%s): %s",
1021 tmpdir, strerror(errno));
1022 else if (!S_ISDIR(tmpinfo.st_mode))
1023 cupsdLogMessage(CUPSD_LOG_ERROR, "TMPDIR (%s) is not a directory.",
1024 tmpdir);
1025 else if ((tmpinfo.st_uid != User || !(tmpinfo.st_mode & S_IWUSR)) &&
1026 (tmpinfo.st_gid != Group || !(tmpinfo.st_mode & S_IWGRP)) &&
1027 !(tmpinfo.st_mode & S_IWOTH))
1028 cupsdLogMessage(CUPSD_LOG_ERROR,
1029 "TMPDIR (%s) has the wrong permissions.", tmpdir);
1030 else
1031 cupsdSetString(&TempDir, tmpdir);
1032 }
1033
1034 if (!TempDir)
1035 {
1036 cupsdLogMessage(CUPSD_LOG_INFO, "Using default TempDir of %s/tmp...",
1037 RequestRoot);
1038 cupsdSetStringf(&TempDir, "%s/tmp", RequestRoot);
1039 }
1040 }
1041
1042 /*
1043 * Make sure the temporary directory has the right permissions...
1044 */
1045
1046 if (!strncmp(TempDir, RequestRoot, strlen(RequestRoot)) ||
1047 access(TempDir, 0))
1048 {
1049 /*
1050 * Update ownership and permissions if the CUPS temp directory
1051 * is under the spool directory or does not exist...
1052 */
1053
1054 if (cupsdCheckPermissions(TempDir, NULL, 01770, RunUser, Group, 1, 1) < 0 &&
1055 (FatalErrors & CUPSD_FATAL_PERMISSIONS))
1056 return (0);
1057 }
1058
1059 /*
1060 * Update environment variables...
1061 */
1062
1063 cupsdUpdateEnv();
1064
1065 /*
1066 * Update default paper size setting as needed...
1067 */
1068
1069 if (!DefaultPaperSize)
1070 {
1071 #ifdef HAVE_LIBPAPER
1072 char *paper_result; /* Paper size name from libpaper */
1073
1074 if ((paper_result = systempapername()) != NULL)
1075 cupsdSetString(&DefaultPaperSize, paper_result);
1076 else
1077 #endif /* HAVE_LIBPAPER */
1078 if (!DefaultLanguage ||
1079 !strcasecmp(DefaultLanguage, "C") ||
1080 !strcasecmp(DefaultLanguage, "POSIX") ||
1081 !strcasecmp(DefaultLanguage, "en") ||
1082 !strncasecmp(DefaultLanguage, "en.", 3) ||
1083 !strncasecmp(DefaultLanguage, "en_US", 5) ||
1084 !strncasecmp(DefaultLanguage, "en_CA", 5) ||
1085 !strncasecmp(DefaultLanguage, "fr_CA", 5))
1086 {
1087 /*
1088 * These are the only locales that will default to "letter" size...
1089 */
1090
1091 cupsdSetString(&DefaultPaperSize, "Letter");
1092 }
1093 else
1094 cupsdSetString(&DefaultPaperSize, "A4");
1095 }
1096
1097 /*
1098 * Update classification setting as needed...
1099 */
1100
1101 if (Classification && !strcasecmp(Classification, "none"))
1102 cupsdClearString(&Classification);
1103
1104 if (Classification)
1105 cupsdLogMessage(CUPSD_LOG_INFO, "Security set to \"%s\"", Classification);
1106
1107 /*
1108 * Check the MaxClients setting, and then allocate memory for it...
1109 */
1110
1111 if (MaxClients > (MaxFDs / 3) || MaxClients <= 0)
1112 {
1113 if (MaxClients > 0)
1114 cupsdLogMessage(CUPSD_LOG_INFO,
1115 "MaxClients limited to 1/3 (%d) of the file descriptor "
1116 "limit (%d)...",
1117 MaxFDs / 3, MaxFDs);
1118
1119 MaxClients = MaxFDs / 3;
1120 }
1121
1122 cupsdLogMessage(CUPSD_LOG_INFO, "Configured for up to %d clients.",
1123 MaxClients);
1124
1125 /*
1126 * Check the MaxActiveJobs setting; limit to 1/3 the available
1127 * file descriptors, since we need a pipe for each job...
1128 */
1129
1130 if (MaxActiveJobs > (MaxFDs / 3))
1131 MaxActiveJobs = MaxFDs / 3;
1132
1133 /*
1134 * Update the MaxClientsPerHost value, as needed...
1135 */
1136
1137 if (MaxClientsPerHost <= 0)
1138 MaxClientsPerHost = MaxClients;
1139
1140 if (MaxClientsPerHost > MaxClients)
1141 MaxClientsPerHost = MaxClients;
1142
1143 cupsdLogMessage(CUPSD_LOG_INFO,
1144 "Allowing up to %d client connections per host.",
1145 MaxClientsPerHost);
1146
1147 /*
1148 * Make sure that BrowseTimeout is at least twice the interval...
1149 */
1150
1151 if (BrowseTimeout < (2 * BrowseInterval) || BrowseTimeout <= 0)
1152 {
1153 cupsdLogMessage(CUPSD_LOG_ALERT, "Invalid BrowseTimeout value %d.",
1154 BrowseTimeout);
1155
1156 if (BrowseInterval)
1157 BrowseTimeout = BrowseInterval * 2;
1158 else
1159 BrowseTimeout = DEFAULT_TIMEOUT;
1160
1161 cupsdLogMessage(CUPSD_LOG_ALERT, "Reset BrowseTimeout to %d.",
1162 BrowseTimeout);
1163 }
1164
1165 /*
1166 * Update the default policy, as needed...
1167 */
1168
1169 if (DefaultPolicy)
1170 DefaultPolicyPtr = cupsdFindPolicy(DefaultPolicy);
1171 else
1172 DefaultPolicyPtr = NULL;
1173
1174 if (!DefaultPolicyPtr)
1175 {
1176 cupsd_location_t *po; /* New policy operation */
1177
1178
1179 if (DefaultPolicy)
1180 cupsdLogMessage(CUPSD_LOG_ERROR, "Default policy \"%s\" not found.",
1181 DefaultPolicy);
1182
1183 cupsdSetString(&DefaultPolicy, "default");
1184
1185 if ((DefaultPolicyPtr = cupsdFindPolicy("default")) != NULL)
1186 cupsdLogMessage(CUPSD_LOG_INFO,
1187 "Using policy \"default\" as the default.");
1188 else
1189 {
1190 cupsdLogMessage(CUPSD_LOG_INFO,
1191 "Creating CUPS default administrative policy:");
1192
1193 DefaultPolicyPtr = p = cupsdAddPolicy("default");
1194
1195 cupsdLogMessage(CUPSD_LOG_INFO, "<Policy default>");
1196
1197 cupsdLogMessage(CUPSD_LOG_INFO, "JobPrivateAccess default");
1198 cupsdAddString(&(p->job_access), "@OWNER");
1199 cupsdAddString(&(p->job_access), "@SYSTEM");
1200
1201 cupsdLogMessage(CUPSD_LOG_INFO, "JobPrivateValues default");
1202 cupsdAddString(&(p->job_attrs), "job-name");
1203 cupsdAddString(&(p->job_attrs), "job-originating-host-name");
1204 cupsdAddString(&(p->job_attrs), "job-originating-user-name");
1205
1206 cupsdLogMessage(CUPSD_LOG_INFO, "SubscriptionPrivateAccess default");
1207 cupsdAddString(&(p->sub_access), "@OWNER");
1208 cupsdAddString(&(p->sub_access), "@SYSTEM");
1209
1210 cupsdLogMessage(CUPSD_LOG_INFO, "SubscriptionPrivateValues default");
1211 cupsdAddString(&(p->job_attrs), "notify-events");
1212 cupsdAddString(&(p->job_attrs), "notify-pull-method");
1213 cupsdAddString(&(p->job_attrs), "notify-recipient-uri");
1214 cupsdAddString(&(p->job_attrs), "notify-subscriber-user-name");
1215 cupsdAddString(&(p->job_attrs), "notify-user-data");
1216
1217 cupsdLogMessage(CUPSD_LOG_INFO,
1218 "<Limit Create-Job Print-Job Print-URI Validate-Job>");
1219 cupsdLogMessage(CUPSD_LOG_INFO, "Order Deny,Allow");
1220
1221 po = cupsdAddPolicyOp(p, NULL, IPP_CREATE_JOB);
1222 po->order_type = CUPSD_AUTH_ALLOW;
1223
1224 cupsdAddPolicyOp(p, po, IPP_PRINT_JOB);
1225 cupsdAddPolicyOp(p, po, IPP_PRINT_URI);
1226 cupsdAddPolicyOp(p, po, IPP_VALIDATE_JOB);
1227
1228 cupsdLogMessage(CUPSD_LOG_INFO, "</Limit>");
1229
1230 cupsdLogMessage(CUPSD_LOG_INFO,
1231 "<Limit Send-Document Send-URI Cancel-Job Hold-Job "
1232 "Release-Job Restart-Job Purge-Jobs "
1233 "Set-Job-Attributes Create-Job-Subscription "
1234 "Renew-Subscription Cancel-Subscription "
1235 "Get-Notifications Reprocess-Job Cancel-Current-Job "
1236 "Suspend-Current-Job Resume-Job "
1237 "Cancel-My-Jobs Close-Job CUPS-Move-Job "
1238 "CUPS-Authenticate-Job CUPS-Get-Document>");
1239 cupsdLogMessage(CUPSD_LOG_INFO, "Order Deny,Allow");
1240
1241 po = cupsdAddPolicyOp(p, NULL, IPP_SEND_DOCUMENT);
1242 po->order_type = CUPSD_AUTH_ALLOW;
1243 po->level = CUPSD_AUTH_USER;
1244
1245 cupsdAddName(po, "@OWNER");
1246 cupsdAddName(po, "@SYSTEM");
1247 cupsdLogMessage(CUPSD_LOG_INFO, "Require user @OWNER @SYSTEM");
1248
1249 cupsdAddPolicyOp(p, po, IPP_SEND_URI);
1250 cupsdAddPolicyOp(p, po, IPP_CANCEL_JOB);
1251 cupsdAddPolicyOp(p, po, IPP_HOLD_JOB);
1252 cupsdAddPolicyOp(p, po, IPP_RELEASE_JOB);
1253 cupsdAddPolicyOp(p, po, IPP_RESTART_JOB);
1254 cupsdAddPolicyOp(p, po, IPP_PURGE_JOBS);
1255 cupsdAddPolicyOp(p, po, IPP_SET_JOB_ATTRIBUTES);
1256 cupsdAddPolicyOp(p, po, IPP_CREATE_JOB_SUBSCRIPTION);
1257 cupsdAddPolicyOp(p, po, IPP_RENEW_SUBSCRIPTION);
1258 cupsdAddPolicyOp(p, po, IPP_CANCEL_SUBSCRIPTION);
1259 cupsdAddPolicyOp(p, po, IPP_GET_NOTIFICATIONS);
1260 cupsdAddPolicyOp(p, po, IPP_REPROCESS_JOB);
1261 cupsdAddPolicyOp(p, po, IPP_CANCEL_CURRENT_JOB);
1262 cupsdAddPolicyOp(p, po, IPP_SUSPEND_CURRENT_JOB);
1263 cupsdAddPolicyOp(p, po, IPP_RESUME_JOB);
1264 cupsdAddPolicyOp(p, po, IPP_CANCEL_MY_JOBS);
1265 cupsdAddPolicyOp(p, po, IPP_CLOSE_JOB);
1266 cupsdAddPolicyOp(p, po, CUPS_MOVE_JOB);
1267 cupsdAddPolicyOp(p, po, CUPS_AUTHENTICATE_JOB);
1268 cupsdAddPolicyOp(p, po, CUPS_GET_DOCUMENT);
1269
1270 cupsdLogMessage(CUPSD_LOG_INFO, "</Limit>");
1271
1272 cupsdLogMessage(CUPSD_LOG_INFO,
1273 "<Limit Pause-Printer Resume-Printer "
1274 "Set-Printer-Attributes Enable-Printer "
1275 "Disable-Printer Pause-Printer-After-Current-Job "
1276 "Hold-New-Jobs Release-Held-New-Jobs "
1277 "Deactivate-Printer Activate-Printer Restart-Printer "
1278 "Shutdown-Printer Startup-Printer Promote-Job "
1279 "Schedule-Job-After Cancel-Jobs CUPS-Add-Printer "
1280 "CUPS-Delete-Printer CUPS-Add-Class CUPS-Delete-Class "
1281 "CUPS-Accept-Jobs CUPS-Reject-Jobs CUPS-Set-Default>");
1282 cupsdLogMessage(CUPSD_LOG_INFO, "Order Deny,Allow");
1283 cupsdLogMessage(CUPSD_LOG_INFO, "AuthType Default");
1284
1285 po = cupsdAddPolicyOp(p, NULL, IPP_PAUSE_PRINTER);
1286 po->order_type = CUPSD_AUTH_ALLOW;
1287 po->type = CUPSD_AUTH_DEFAULT;
1288 po->level = CUPSD_AUTH_USER;
1289
1290 cupsdAddName(po, "@SYSTEM");
1291 cupsdLogMessage(CUPSD_LOG_INFO, "Require user @SYSTEM");
1292
1293 cupsdAddPolicyOp(p, po, IPP_RESUME_PRINTER);
1294 cupsdAddPolicyOp(p, po, IPP_SET_PRINTER_ATTRIBUTES);
1295 cupsdAddPolicyOp(p, po, IPP_ENABLE_PRINTER);
1296 cupsdAddPolicyOp(p, po, IPP_DISABLE_PRINTER);
1297 cupsdAddPolicyOp(p, po, IPP_PAUSE_PRINTER_AFTER_CURRENT_JOB);
1298 cupsdAddPolicyOp(p, po, IPP_HOLD_NEW_JOBS);
1299 cupsdAddPolicyOp(p, po, IPP_RELEASE_HELD_NEW_JOBS);
1300 cupsdAddPolicyOp(p, po, IPP_DEACTIVATE_PRINTER);
1301 cupsdAddPolicyOp(p, po, IPP_ACTIVATE_PRINTER);
1302 cupsdAddPolicyOp(p, po, IPP_RESTART_PRINTER);
1303 cupsdAddPolicyOp(p, po, IPP_SHUTDOWN_PRINTER);
1304 cupsdAddPolicyOp(p, po, IPP_STARTUP_PRINTER);
1305 cupsdAddPolicyOp(p, po, IPP_PROMOTE_JOB);
1306 cupsdAddPolicyOp(p, po, IPP_SCHEDULE_JOB_AFTER);
1307 cupsdAddPolicyOp(p, po, IPP_CANCEL_JOBS);
1308 cupsdAddPolicyOp(p, po, CUPS_ADD_PRINTER);
1309 cupsdAddPolicyOp(p, po, CUPS_DELETE_PRINTER);
1310 cupsdAddPolicyOp(p, po, CUPS_ADD_CLASS);
1311 cupsdAddPolicyOp(p, po, CUPS_DELETE_CLASS);
1312 cupsdAddPolicyOp(p, po, CUPS_ACCEPT_JOBS);
1313 cupsdAddPolicyOp(p, po, CUPS_REJECT_JOBS);
1314 cupsdAddPolicyOp(p, po, CUPS_SET_DEFAULT);
1315
1316 cupsdLogMessage(CUPSD_LOG_INFO, "</Limit>");
1317
1318 cupsdLogMessage(CUPSD_LOG_INFO, "<Limit All>");
1319 cupsdLogMessage(CUPSD_LOG_INFO, "Order Deny,Allow");
1320
1321 po = cupsdAddPolicyOp(p, NULL, IPP_ANY_OPERATION);
1322 po->order_type = CUPSD_AUTH_ALLOW;
1323
1324 cupsdLogMessage(CUPSD_LOG_INFO, "</Limit>");
1325 cupsdLogMessage(CUPSD_LOG_INFO, "</Policy>");
1326 }
1327 }
1328
1329 cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdReadConfiguration: NumPolicies=%d",
1330 cupsArrayCount(Policies));
1331 for (i = 0, p = (cupsd_policy_t *)cupsArrayFirst(Policies);
1332 p;
1333 i ++, p = (cupsd_policy_t *)cupsArrayNext(Policies))
1334 cupsdLogMessage(CUPSD_LOG_DEBUG2,
1335 "cupsdReadConfiguration: Policies[%d]=\"%s\"", i, p->name);
1336
1337 /*
1338 * If we are doing a full reload or the server root has changed, flush
1339 * the jobs, printers, etc. and start from scratch...
1340 */
1341
1342 if (NeedReload == RELOAD_ALL ||
1343 old_remote_port != RemotePort ||
1344 !old_serverroot || !ServerRoot || strcmp(old_serverroot, ServerRoot) ||
1345 !old_requestroot || !RequestRoot || strcmp(old_requestroot, RequestRoot))
1346 {
1347 mime_type_t *type; /* Current type */
1348 char mimetype[MIME_MAX_SUPER + MIME_MAX_TYPE];
1349 /* MIME type name */
1350
1351
1352 cupsdLogMessage(CUPSD_LOG_INFO, "Full reload is required.");
1353
1354 /*
1355 * Free all memory...
1356 */
1357
1358 cupsdDeleteAllSubscriptions();
1359 cupsdFreeAllJobs();
1360 cupsdDeleteAllPrinters();
1361
1362 DefaultPrinter = NULL;
1363
1364 if (MimeDatabase != NULL)
1365 mimeDelete(MimeDatabase);
1366
1367 if (NumMimeTypes)
1368 {
1369 for (i = 0; i < NumMimeTypes; i ++)
1370 _cupsStrFree(MimeTypes[i]);
1371
1372 free(MimeTypes);
1373 }
1374
1375 /*
1376 * Read the MIME type and conversion database...
1377 */
1378
1379 snprintf(temp, sizeof(temp), "%s/filter", ServerBin);
1380 snprintf(mimedir, sizeof(mimedir), "%s/mime", DataDir);
1381
1382 MimeDatabase = mimeLoadTypes(NULL, mimedir);
1383 MimeDatabase = mimeLoadTypes(MimeDatabase, ServerRoot);
1384 MimeDatabase = mimeLoadFilters(MimeDatabase, mimedir, temp);
1385 MimeDatabase = mimeLoadFilters(MimeDatabase, ServerRoot, temp);
1386
1387 if (!MimeDatabase)
1388 {
1389 cupsdLogMessage(CUPSD_LOG_EMERG,
1390 "Unable to load MIME database from \"%s\" or \"%s\".",
1391 mimedir, ServerRoot);
1392 if (FatalErrors & CUPSD_FATAL_CONFIG)
1393 return (0);
1394 }
1395
1396 cupsdLogMessage(CUPSD_LOG_INFO,
1397 "Loaded MIME database from \"%s\" and \"%s\": %d types, "
1398 "%d filters...", mimedir, ServerRoot,
1399 mimeNumTypes(MimeDatabase), mimeNumFilters(MimeDatabase));
1400
1401 /*
1402 * Create a list of MIME types for the document-format-supported
1403 * attribute...
1404 */
1405
1406 NumMimeTypes = mimeNumTypes(MimeDatabase);
1407 if (!mimeType(MimeDatabase, "application", "octet-stream"))
1408 NumMimeTypes ++;
1409
1410 if ((MimeTypes = calloc(NumMimeTypes, sizeof(const char *))) == NULL)
1411 {
1412 cupsdLogMessage(CUPSD_LOG_ERROR,
1413 "Unable to allocate memory for %d MIME types.",
1414 NumMimeTypes);
1415 NumMimeTypes = 0;
1416 }
1417 else
1418 {
1419 for (i = 0, type = mimeFirstType(MimeDatabase);
1420 type;
1421 i ++, type = mimeNextType(MimeDatabase))
1422 {
1423 snprintf(mimetype, sizeof(mimetype), "%s/%s", type->super, type->type);
1424
1425 MimeTypes[i] = _cupsStrAlloc(mimetype);
1426 }
1427
1428 if (i < NumMimeTypes)
1429 MimeTypes[i] = _cupsStrAlloc("application/octet-stream");
1430 }
1431
1432 if (LogLevel == CUPSD_LOG_DEBUG2)
1433 {
1434 mime_filter_t *filter; /* Current filter */
1435
1436
1437 for (type = mimeFirstType(MimeDatabase);
1438 type;
1439 type = mimeNextType(MimeDatabase))
1440 cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdReadConfiguration: type %s/%s",
1441 type->super, type->type);
1442
1443 for (filter = mimeFirstFilter(MimeDatabase);
1444 filter;
1445 filter = mimeNextFilter(MimeDatabase))
1446 cupsdLogMessage(CUPSD_LOG_DEBUG2,
1447 "cupsdReadConfiguration: filter %s/%s to %s/%s %d %s",
1448 filter->src->super, filter->src->type,
1449 filter->dst->super, filter->dst->type,
1450 filter->cost, filter->filter);
1451 }
1452
1453 /*
1454 * Load banners...
1455 */
1456
1457 snprintf(temp, sizeof(temp), "%s/banners", DataDir);
1458 cupsdLoadBanners(temp);
1459
1460 /*
1461 * Load printers and classes...
1462 */
1463
1464 cupsdLoadAllPrinters();
1465 cupsdLoadAllClasses();
1466 cupsdLoadRemoteCache();
1467
1468 cupsdCreateCommonData();
1469
1470 /*
1471 * Update the printcap file as needed...
1472 */
1473
1474 if (Printcap && *Printcap && access(Printcap, 0))
1475 cupsdWritePrintcap();
1476
1477 /*
1478 * Load queued jobs...
1479 */
1480
1481 cupsdLoadAllJobs();
1482
1483 /*
1484 * Load subscriptions...
1485 */
1486
1487 cupsdLoadAllSubscriptions();
1488
1489 cupsdLogMessage(CUPSD_LOG_INFO, "Full reload complete.");
1490 }
1491 else
1492 {
1493 /*
1494 * Not a full reload, so recreate the common printer attributes...
1495 */
1496
1497 cupsdCreateCommonData();
1498
1499 /*
1500 * Update all printers as needed...
1501 */
1502
1503 cupsdUpdatePrinters();
1504 cupsdMarkDirty(CUPSD_DIRTY_PRINTCAP);
1505
1506 cupsdLogMessage(CUPSD_LOG_INFO, "Partial reload complete.");
1507 }
1508
1509 /*
1510 * Reset the reload state...
1511 */
1512
1513 NeedReload = RELOAD_NONE;
1514
1515 cupsdClearString(&old_serverroot);
1516 cupsdClearString(&old_requestroot);
1517
1518 return (1);
1519 }
1520
1521
1522 /*
1523 * 'get_address()' - Get an address + port number from a line.
1524 */
1525
1526 static http_addrlist_t * /* O - Pointer to list if address good, NULL if bad */
1527 get_address(const char *value, /* I - Value string */
1528 int defport) /* I - Default port */
1529 {
1530 char buffer[1024], /* Hostname + port number buffer */
1531 defpname[255], /* Default port name */
1532 *hostname, /* Hostname or IP */
1533 *portname; /* Port number or name */
1534 http_addrlist_t *addrlist; /* Address list */
1535
1536
1537 /*
1538 * Check for an empty value...
1539 */
1540
1541 if (!*value)
1542 {
1543 cupsdLogMessage(CUPSD_LOG_ERROR, "Bad (empty) address.");
1544 return (NULL);
1545 }
1546
1547 /*
1548 * Grab a hostname and port number; if there is no colon and the port name
1549 * is only digits, then we have a port number by itself...
1550 */
1551
1552 strlcpy(buffer, value, sizeof(buffer));
1553
1554 if ((portname = strrchr(buffer, ':')) != NULL && !strchr(portname, ']'))
1555 {
1556 *portname++ = '\0';
1557 hostname = buffer;
1558 }
1559 else
1560 {
1561 for (portname = buffer; isdigit(*portname & 255); portname ++);
1562
1563 if (*portname)
1564 {
1565 /*
1566 * Use the default port...
1567 */
1568
1569 sprintf(defpname, "%d", defport);
1570 portname = defpname;
1571 hostname = buffer;
1572 }
1573 else
1574 {
1575 /*
1576 * The buffer contains just a port number...
1577 */
1578
1579 portname = buffer;
1580 hostname = NULL;
1581 }
1582 }
1583
1584 if (hostname && !strcmp(hostname, "*"))
1585 hostname = NULL;
1586
1587 /*
1588 * Now lookup the address using httpAddrGetList()...
1589 */
1590
1591 if ((addrlist = httpAddrGetList(hostname, AF_UNSPEC, portname)) == NULL)
1592 cupsdLogMessage(CUPSD_LOG_ERROR, "Hostname lookup for \"%s\" failed.",
1593 hostname ? hostname : "(nil)");
1594
1595 return (addrlist);
1596 }
1597
1598
1599 /*
1600 * 'get_addr_and_mask()' - Get an IP address and netmask.
1601 */
1602
1603 static int /* O - 1 on success, 0 on failure */
1604 get_addr_and_mask(const char *value, /* I - String from config file */
1605 unsigned *ip, /* O - Address value */
1606 unsigned *mask) /* O - Mask value */
1607 {
1608 int i, j, /* Looping vars */
1609 family, /* Address family */
1610 ipcount; /* Count of fields in address */
1611 unsigned ipval; /* Value */
1612 const char *maskval, /* Pointer to start of mask value */
1613 *ptr, /* Pointer into value */
1614 *ptr2; /* ... */
1615
1616
1617 /*
1618 * Get the address...
1619 */
1620
1621 ip[0] = ip[1] = ip[2] = ip[3] = 0x00000000;
1622 mask[0] = mask[1] = mask[2] = mask[3] = 0xffffffff;
1623
1624 if ((maskval = strchr(value, '/')) != NULL)
1625 maskval ++;
1626 else
1627 maskval = value + strlen(value);
1628
1629 #ifdef AF_INET6
1630 /*
1631 * Check for an IPv6 address...
1632 */
1633
1634 if (*value == '[')
1635 {
1636 /*
1637 * Parse hexadecimal IPv6 address...
1638 */
1639
1640 family = AF_INET6;
1641
1642 for (i = 0, ptr = value + 1; *ptr && i < 8; i ++)
1643 {
1644 if (*ptr == ']')
1645 break;
1646 else if (!strncmp(ptr, "::", 2))
1647 {
1648 for (ptr2 = strchr(ptr + 2, ':'), j = 0;
1649 ptr2;
1650 ptr2 = strchr(ptr2 + 1, ':'), j ++);
1651
1652 i = 7 - j;
1653 ptr ++;
1654 }
1655 else if (isxdigit(*ptr & 255))
1656 {
1657 ipval = strtoul(ptr, (char **)&ptr, 16);
1658
1659 if (ipval > 0xffff)
1660 return (0);
1661
1662 if (i & 1)
1663 ip[i / 2] |= ipval;
1664 else
1665 ip[i / 2] |= ipval << 16;
1666 }
1667 else
1668 return (0);
1669
1670 while (*ptr == ':')
1671 ptr ++;
1672 }
1673
1674 if (*ptr != ']')
1675 return (0);
1676
1677 ptr ++;
1678
1679 if (*ptr && *ptr != '/')
1680 return (0);
1681 }
1682 else
1683 #endif /* AF_INET6 */
1684 {
1685 /*
1686 * Parse dotted-decimal IPv4 address...
1687 */
1688
1689 unsigned val[4]; /* IPv4 address values */
1690
1691
1692 family = AF_INET;
1693 ipcount = sscanf(value, "%u.%u.%u.%u", val + 0, val + 1, val + 2, val + 3);
1694
1695 /*
1696 * Range check the IP numbers...
1697 */
1698
1699 for (i = 0; i < ipcount; i ++)
1700 if (val[i] > 255)
1701 return (0);
1702
1703 /*
1704 * Make sure the trailing values are zeroed, as some C libraries like
1705 * glibc apparently like to fill the unused arguments with garbage...
1706 */
1707
1708 for (i = ipcount; i < 4; i ++)
1709 val[i] = 0;
1710
1711 /*
1712 * Merge everything into a 32-bit IPv4 address in ip[3]...
1713 */
1714
1715 ip[3] = (((((val[0] << 8) | val[1]) << 8) | val[2]) << 8) | val[3];
1716
1717 if (ipcount < 4)
1718 mask[3] = (0xffffffff << (32 - 8 * ipcount)) & 0xffffffff;
1719 }
1720
1721 if (*maskval)
1722 {
1723 /*
1724 * Get the netmask value(s)...
1725 */
1726
1727 memset(mask, 0, sizeof(unsigned) * 4);
1728
1729 if (strchr(maskval, '.'))
1730 {
1731 /*
1732 * Get dotted-decimal mask...
1733 */
1734
1735 if (family != AF_INET)
1736 return (0);
1737
1738 if (sscanf(maskval, "%u.%u.%u.%u", mask + 0, mask + 1, mask + 2, mask + 3) != 4)
1739 return (0);
1740
1741 mask[3] |= ((((mask[0] << 8) | mask[1]) << 8) | mask[2]) << 8;
1742 mask[0] = mask[1] = mask[2] = 0;
1743 }
1744 else
1745 {
1746 /*
1747 * Get address/bits format...
1748 */
1749
1750 i = atoi(maskval);
1751
1752 #ifdef AF_INET6
1753 if (family == AF_INET6)
1754 {
1755 if (i > 128)
1756 return (0);
1757
1758 i = 128 - i;
1759
1760 if (i <= 96)
1761 mask[0] = 0xffffffff;
1762 else
1763 mask[0] = (0xffffffff << (i - 96)) & 0xffffffff;
1764
1765 if (i <= 64)
1766 mask[1] = 0xffffffff;
1767 else if (i >= 96)
1768 mask[1] = 0;
1769 else
1770 mask[1] = (0xffffffff << (i - 64)) & 0xffffffff;
1771
1772 if (i <= 32)
1773 mask[2] = 0xffffffff;
1774 else if (i >= 64)
1775 mask[2] = 0;
1776 else
1777 mask[2] = (0xffffffff << (i - 32)) & 0xffffffff;
1778
1779 if (i == 0)
1780 mask[3] = 0xffffffff;
1781 else if (i >= 32)
1782 mask[3] = 0;
1783 else
1784 mask[3] = (0xffffffff << i) & 0xffffffff;
1785 }
1786 else
1787 #endif /* AF_INET6 */
1788 {
1789 if (i > 32)
1790 return (0);
1791
1792 mask[0] = 0xffffffff;
1793 mask[1] = 0xffffffff;
1794 mask[2] = 0xffffffff;
1795
1796 if (i < 32)
1797 mask[3] = (0xffffffff << (32 - i)) & 0xffffffff;
1798 else
1799 mask[3] = 0xffffffff;
1800 }
1801 }
1802 }
1803
1804 cupsdLogMessage(CUPSD_LOG_DEBUG2,
1805 "get_addr_and_mask(value=\"%s\", "
1806 "ip=[%08x:%08x:%08x:%08x], mask=[%08x:%08x:%08x:%08x])",
1807 value, ip[0], ip[1], ip[2], ip[3], mask[0], mask[1], mask[2],
1808 mask[3]);
1809
1810 /*
1811 * Check for a valid netmask; no fallback like in CUPS 1.1.x!
1812 */
1813
1814 if ((ip[0] & ~mask[0]) != 0 ||
1815 (ip[1] & ~mask[1]) != 0 ||
1816 (ip[2] & ~mask[2]) != 0 ||
1817 (ip[3] & ~mask[3]) != 0)
1818 return (0);
1819
1820 return (1);
1821 }
1822
1823
1824 /*
1825 * 'parse_aaa()' - Parse authentication, authorization, and access control lines.
1826 */
1827
1828 static int /* O - 1 on success, 0 on failure */
1829 parse_aaa(cupsd_location_t *loc, /* I - Location */
1830 char *line, /* I - Line from file */
1831 char *value, /* I - Start of value data */
1832 int linenum) /* I - Current line number */
1833 {
1834 char *valptr; /* Pointer into value */
1835 unsigned ip[4], /* IP address components */
1836 mask[4]; /* IP netmask components */
1837
1838
1839 if (!strcasecmp(line, "Encryption"))
1840 {
1841 /*
1842 * "Encryption xxx" - set required encryption level...
1843 */
1844
1845 if (!strcasecmp(value, "never"))
1846 loc->encryption = HTTP_ENCRYPT_NEVER;
1847 else if (!strcasecmp(value, "always"))
1848 {
1849 cupsdLogMessage(CUPSD_LOG_ERROR,
1850 "Encryption value \"%s\" on line %d is invalid in this "
1851 "context. Using \"required\" instead.", value, linenum);
1852
1853 loc->encryption = HTTP_ENCRYPT_REQUIRED;
1854 }
1855 else if (!strcasecmp(value, "required"))
1856 loc->encryption = HTTP_ENCRYPT_REQUIRED;
1857 else if (!strcasecmp(value, "ifrequested"))
1858 loc->encryption = HTTP_ENCRYPT_IF_REQUESTED;
1859 else
1860 {
1861 cupsdLogMessage(CUPSD_LOG_ERROR,
1862 "Unknown Encryption value %s on line %d.", value, linenum);
1863 return (0);
1864 }
1865 }
1866 else if (!strcasecmp(line, "Order"))
1867 {
1868 /*
1869 * "Order Deny,Allow" or "Order Allow,Deny"...
1870 */
1871
1872 if (!strncasecmp(value, "deny", 4))
1873 loc->order_type = CUPSD_AUTH_ALLOW;
1874 else if (!strncasecmp(value, "allow", 5))
1875 loc->order_type = CUPSD_AUTH_DENY;
1876 else
1877 {
1878 cupsdLogMessage(CUPSD_LOG_ERROR, "Unknown Order value %s on line %d.",
1879 value, linenum);
1880 return (0);
1881 }
1882 }
1883 else if (!strcasecmp(line, "Allow") || !strcasecmp(line, "Deny"))
1884 {
1885 /*
1886 * Allow [From] host/ip...
1887 * Deny [From] host/ip...
1888 */
1889
1890 while (*value)
1891 {
1892 if (!strncasecmp(value, "from", 4))
1893 {
1894 /*
1895 * Strip leading "from"...
1896 */
1897
1898 value += 4;
1899
1900 while (isspace(*value & 255))
1901 value ++;
1902
1903 if (!*value)
1904 break;
1905 }
1906
1907 /*
1908 * Find the end of the value...
1909 */
1910
1911 for (valptr = value; *valptr && !isspace(*valptr & 255); valptr ++);
1912
1913 while (isspace(*valptr & 255))
1914 *valptr++ = '\0';
1915
1916 /*
1917 * Figure out what form the allow/deny address takes:
1918 *
1919 * All
1920 * None
1921 * *.domain.com
1922 * .domain.com
1923 * host.domain.com
1924 * nnn.*
1925 * nnn.nnn.*
1926 * nnn.nnn.nnn.*
1927 * nnn.nnn.nnn.nnn
1928 * nnn.nnn.nnn.nnn/mm
1929 * nnn.nnn.nnn.nnn/mmm.mmm.mmm.mmm
1930 */
1931
1932 if (!strcasecmp(value, "all"))
1933 {
1934 /*
1935 * All hosts...
1936 */
1937
1938 if (!strcasecmp(line, "Allow"))
1939 cupsdAddIPMask(&(loc->allow), zeros, zeros);
1940 else
1941 cupsdAddIPMask(&(loc->deny), zeros, zeros);
1942 }
1943 else if (!strcasecmp(value, "none"))
1944 {
1945 /*
1946 * No hosts...
1947 */
1948
1949 if (!strcasecmp(line, "Allow"))
1950 cupsdAddIPMask(&(loc->allow), ones, zeros);
1951 else
1952 cupsdAddIPMask(&(loc->deny), ones, zeros);
1953 }
1954 #ifdef AF_INET6
1955 else if (value[0] == '*' || value[0] == '.' ||
1956 (!isdigit(value[0] & 255) && value[0] != '['))
1957 #else
1958 else if (value[0] == '*' || value[0] == '.' || !isdigit(value[0] & 255))
1959 #endif /* AF_INET6 */
1960 {
1961 /*
1962 * Host or domain name...
1963 */
1964
1965 if (value[0] == '*')
1966 value ++;
1967
1968 if (!strcasecmp(line, "Allow"))
1969 cupsdAddNameMask(&(loc->allow), value);
1970 else
1971 cupsdAddNameMask(&(loc->deny), value);
1972 }
1973 else
1974 {
1975 /*
1976 * One of many IP address forms...
1977 */
1978
1979 if (!get_addr_and_mask(value, ip, mask))
1980 {
1981 cupsdLogMessage(CUPSD_LOG_ERROR, "Bad netmask value %s on line %d.",
1982 value, linenum);
1983 return (0);
1984 }
1985
1986 if (!strcasecmp(line, "Allow"))
1987 cupsdAddIPMask(&(loc->allow), ip, mask);
1988 else
1989 cupsdAddIPMask(&(loc->deny), ip, mask);
1990 }
1991
1992 /*
1993 * Advance to next value...
1994 */
1995
1996 value = valptr;
1997 }
1998 }
1999 else if (!strcasecmp(line, "AuthType"))
2000 {
2001 /*
2002 * AuthType {none,basic,digest,basicdigest,negotiate,default}
2003 */
2004
2005 if (!strcasecmp(value, "none"))
2006 {
2007 loc->type = CUPSD_AUTH_NONE;
2008 loc->level = CUPSD_AUTH_ANON;
2009 }
2010 else if (!strcasecmp(value, "basic"))
2011 {
2012 loc->type = CUPSD_AUTH_BASIC;
2013
2014 if (loc->level == CUPSD_AUTH_ANON)
2015 loc->level = CUPSD_AUTH_USER;
2016 }
2017 else if (!strcasecmp(value, "digest"))
2018 {
2019 loc->type = CUPSD_AUTH_DIGEST;
2020
2021 if (loc->level == CUPSD_AUTH_ANON)
2022 loc->level = CUPSD_AUTH_USER;
2023 }
2024 else if (!strcasecmp(value, "basicdigest"))
2025 {
2026 loc->type = CUPSD_AUTH_BASICDIGEST;
2027
2028 if (loc->level == CUPSD_AUTH_ANON)
2029 loc->level = CUPSD_AUTH_USER;
2030 }
2031 else if (!strcasecmp(value, "default"))
2032 {
2033 loc->type = CUPSD_AUTH_DEFAULT;
2034
2035 if (loc->level == CUPSD_AUTH_ANON)
2036 loc->level = CUPSD_AUTH_USER;
2037 }
2038 #ifdef HAVE_GSSAPI
2039 else if (!strcasecmp(value, "negotiate"))
2040 {
2041 loc->type = CUPSD_AUTH_NEGOTIATE;
2042
2043 if (loc->level == CUPSD_AUTH_ANON)
2044 loc->level = CUPSD_AUTH_USER;
2045 }
2046 #endif /* HAVE_GSSAPI */
2047 else
2048 {
2049 cupsdLogMessage(CUPSD_LOG_WARN,
2050 "Unknown authorization type %s on line %d.",
2051 value, linenum);
2052 return (0);
2053 }
2054 }
2055 else if (!strcasecmp(line, "AuthClass"))
2056 {
2057 /*
2058 * AuthClass anonymous, user, system, group
2059 */
2060
2061 if (!strcasecmp(value, "anonymous"))
2062 {
2063 loc->type = CUPSD_AUTH_NONE;
2064 loc->level = CUPSD_AUTH_ANON;
2065
2066 cupsdLogMessage(CUPSD_LOG_WARN,
2067 "\"AuthClass %s\" is deprecated; consider removing "
2068 "it from line %d.",
2069 value, linenum);
2070 }
2071 else if (!strcasecmp(value, "user"))
2072 {
2073 loc->level = CUPSD_AUTH_USER;
2074
2075 cupsdLogMessage(CUPSD_LOG_WARN,
2076 "\"AuthClass %s\" is deprecated; consider using "
2077 "\"Require valid-user\" on line %d.",
2078 value, linenum);
2079 }
2080 else if (!strcasecmp(value, "group"))
2081 {
2082 loc->level = CUPSD_AUTH_GROUP;
2083
2084 cupsdLogMessage(CUPSD_LOG_WARN,
2085 "\"AuthClass %s\" is deprecated; consider using "
2086 "\"Require user @groupname\" on line %d.",
2087 value, linenum);
2088 }
2089 else if (!strcasecmp(value, "system"))
2090 {
2091 loc->level = CUPSD_AUTH_GROUP;
2092
2093 cupsdAddName(loc, "@SYSTEM");
2094
2095 cupsdLogMessage(CUPSD_LOG_WARN,
2096 "\"AuthClass %s\" is deprecated; consider using "
2097 "\"Require user @SYSTEM\" on line %d.",
2098 value, linenum);
2099 }
2100 else
2101 {
2102 cupsdLogMessage(CUPSD_LOG_WARN,
2103 "Unknown authorization class %s on line %d.",
2104 value, linenum);
2105 return (0);
2106 }
2107 }
2108 else if (!strcasecmp(line, "AuthGroupName"))
2109 {
2110 cupsdAddName(loc, value);
2111
2112 cupsdLogMessage(CUPSD_LOG_WARN,
2113 "\"AuthGroupName %s\" directive is deprecated; consider "
2114 "using \"Require user @%s\" on line %d.",
2115 value, value, linenum);
2116 }
2117 else if (!strcasecmp(line, "Require"))
2118 {
2119 /*
2120 * Apache synonym for AuthClass and AuthGroupName...
2121 *
2122 * Get initial word:
2123 *
2124 * Require valid-user
2125 * Require group names
2126 * Require user names
2127 */
2128
2129 for (valptr = value; !isspace(*valptr & 255) && *valptr; valptr ++);
2130
2131 if (*valptr)
2132 *valptr++ = '\0';
2133
2134 if (!strcasecmp(value, "valid-user") ||
2135 !strcasecmp(value, "user"))
2136 loc->level = CUPSD_AUTH_USER;
2137 else if (!strcasecmp(value, "group"))
2138 loc->level = CUPSD_AUTH_GROUP;
2139 else
2140 {
2141 cupsdLogMessage(CUPSD_LOG_WARN, "Unknown Require type %s on line %d.",
2142 value, linenum);
2143 return (0);
2144 }
2145
2146 /*
2147 * Get the list of names from the line...
2148 */
2149
2150 for (value = valptr; *value;)
2151 {
2152 while (isspace(*value & 255))
2153 value ++;
2154
2155 #ifdef HAVE_AUTHORIZATION_H
2156 if (!strncmp(value, "@AUTHKEY(", 9))
2157 {
2158 /*
2159 * Grab "@AUTHKEY(name)" value...
2160 */
2161
2162 for (valptr = value + 9; *valptr != ')' && *valptr; valptr ++);
2163
2164 if (*valptr)
2165 *valptr++ = '\0';
2166 }
2167 else
2168 #endif /* HAVE_AUTHORIZATION_H */
2169 if (*value == '\"' || *value == '\'')
2170 {
2171 /*
2172 * Grab quoted name...
2173 */
2174
2175 for (valptr = value + 1; *valptr != *value && *valptr; valptr ++);
2176
2177 value ++;
2178 }
2179 else
2180 {
2181 /*
2182 * Grab literal name.
2183 */
2184
2185 for (valptr = value; !isspace(*valptr & 255) && *valptr; valptr ++);
2186 }
2187
2188 if (*valptr)
2189 *valptr++ = '\0';
2190
2191 cupsdAddName(loc, value);
2192
2193 for (value = valptr; isspace(*value & 255); value ++);
2194 }
2195 }
2196 else if (!strcasecmp(line, "Satisfy"))
2197 {
2198 if (!strcasecmp(value, "all"))
2199 loc->satisfy = CUPSD_AUTH_SATISFY_ALL;
2200 else if (!strcasecmp(value, "any"))
2201 loc->satisfy = CUPSD_AUTH_SATISFY_ANY;
2202 else
2203 {
2204 cupsdLogMessage(CUPSD_LOG_WARN, "Unknown Satisfy value %s on line %d.",
2205 value, linenum);
2206 return (0);
2207 }
2208 }
2209 else
2210 return (0);
2211
2212 return (1);
2213 }
2214
2215
2216 /*
2217 * 'parse_fatal_errors()' - Parse FatalErrors values in a string.
2218 */
2219
2220 static int /* O - FatalErrors bits */
2221 parse_fatal_errors(const char *s) /* I - FatalErrors string */
2222 {
2223 int fatal; /* FatalErrors bits */
2224 char value[1024], /* Value string */
2225 *valstart, /* Pointer into value */
2226 *valend; /* End of value */
2227
2228
2229 /*
2230 * Empty FatalErrors line yields NULL pointer...
2231 */
2232
2233 if (!s)
2234 return (CUPSD_FATAL_NONE);
2235
2236 /*
2237 * Loop through the value string,...
2238 */
2239
2240 strlcpy(value, s, sizeof(value));
2241
2242 fatal = CUPSD_FATAL_NONE;
2243
2244 for (valstart = value; *valstart;)
2245 {
2246 /*
2247 * Get the current space/comma-delimited kind name...
2248 */
2249
2250 for (valend = valstart; *valend; valend ++)
2251 if (isspace(*valend & 255) || *valend == ',')
2252 break;
2253
2254 if (*valend)
2255 *valend++ = '\0';
2256
2257 /*
2258 * Add the error to the bitmask...
2259 */
2260
2261 if (!strcasecmp(valstart, "all"))
2262 fatal = CUPSD_FATAL_ALL;
2263 else if (!strcasecmp(valstart, "browse"))
2264 fatal |= CUPSD_FATAL_BROWSE;
2265 else if (!strcasecmp(valstart, "-browse"))
2266 fatal &= ~CUPSD_FATAL_BROWSE;
2267 else if (!strcasecmp(valstart, "config"))
2268 fatal |= CUPSD_FATAL_CONFIG;
2269 else if (!strcasecmp(valstart, "-config"))
2270 fatal &= ~CUPSD_FATAL_CONFIG;
2271 else if (!strcasecmp(valstart, "listen"))
2272 fatal |= CUPSD_FATAL_LISTEN;
2273 else if (!strcasecmp(valstart, "-listen"))
2274 fatal &= ~CUPSD_FATAL_LISTEN;
2275 else if (!strcasecmp(valstart, "log"))
2276 fatal |= CUPSD_FATAL_LOG;
2277 else if (!strcasecmp(valstart, "-log"))
2278 fatal &= ~CUPSD_FATAL_LOG;
2279 else if (!strcasecmp(valstart, "permissions"))
2280 fatal |= CUPSD_FATAL_PERMISSIONS;
2281 else if (!strcasecmp(valstart, "-permissions"))
2282 fatal &= ~CUPSD_FATAL_PERMISSIONS;
2283 else if (strcasecmp(valstart, "none"))
2284 cupsdLogMessage(CUPSD_LOG_ERROR,
2285 "Unknown FatalErrors kind \"%s\" ignored.", valstart);
2286
2287 for (valstart = valend; *valstart; valstart ++)
2288 if (!isspace(*valstart & 255) || *valstart != ',')
2289 break;
2290 }
2291
2292 return (fatal);
2293 }
2294
2295
2296 /*
2297 * 'parse_groups()' - Parse system group names in a string.
2298 */
2299
2300 static int /* O - 1 on success, 0 on failure */
2301 parse_groups(const char *s) /* I - Space-delimited groups */
2302 {
2303 int status; /* Return status */
2304 char value[1024], /* Value string */
2305 *valstart, /* Pointer into value */
2306 *valend, /* End of value */
2307 quote; /* Quote character */
2308 struct group *group; /* Group */
2309
2310
2311 /*
2312 * Make a copy of the string and parse out the groups...
2313 */
2314
2315 strlcpy(value, s, sizeof(value));
2316
2317 status = 1;
2318 valstart = value;
2319
2320 while (*valstart && NumSystemGroups < MAX_SYSTEM_GROUPS)
2321 {
2322 if (*valstart == '\'' || *valstart == '\"')
2323 {
2324 /*
2325 * Scan quoted name...
2326 */
2327
2328 quote = *valstart++;
2329
2330 for (valend = valstart; *valend; valend ++)
2331 if (*valend == quote)
2332 break;
2333 }
2334 else
2335 {
2336 /*
2337 * Scan space or comma-delimited name...
2338 */
2339
2340 for (valend = valstart; *valend; valend ++)
2341 if (isspace(*valend) || *valend == ',')
2342 break;
2343 }
2344
2345 if (*valend)
2346 *valend++ = '\0';
2347
2348 group = getgrnam(valstart);
2349 if (group)
2350 {
2351 cupsdSetString(SystemGroups + NumSystemGroups, valstart);
2352 SystemGroupIDs[NumSystemGroups] = group->gr_gid;
2353
2354 NumSystemGroups ++;
2355 }
2356 else
2357 status = 0;
2358
2359 endgrent();
2360
2361 valstart = valend;
2362
2363 while (*valstart == ',' || isspace(*valstart))
2364 valstart ++;
2365 }
2366
2367 return (status);
2368 }
2369
2370
2371 /*
2372 * 'parse_protocols()' - Parse browse protocols in a string.
2373 */
2374
2375 static int /* O - Browse protocol bits */
2376 parse_protocols(const char *s) /* I - Space-delimited protocols */
2377 {
2378 int protocols; /* Browse protocol bits */
2379 char value[1024], /* Value string */
2380 *valstart, /* Pointer into value */
2381 *valend; /* End of value */
2382
2383
2384 /*
2385 * Empty protocol line yields NULL pointer...
2386 */
2387
2388 if (!s)
2389 return (0);
2390
2391 /*
2392 * Loop through the value string,...
2393 */
2394
2395 strlcpy(value, s, sizeof(value));
2396
2397 protocols = 0;
2398
2399 for (valstart = value; *valstart;)
2400 {
2401 /*
2402 * Get the current space/comma-delimited protocol name...
2403 */
2404
2405 for (valend = valstart; *valend; valend ++)
2406 if (isspace(*valend & 255) || *valend == ',')
2407 break;
2408
2409 if (*valend)
2410 *valend++ = '\0';
2411
2412 /*
2413 * Add the protocol to the bitmask...
2414 */
2415
2416 if (!strcasecmp(valstart, "cups"))
2417 protocols |= BROWSE_CUPS;
2418 else if (!strcasecmp(valstart, "slp"))
2419 protocols |= BROWSE_SLP;
2420 else if (!strcasecmp(valstart, "ldap"))
2421 protocols |= BROWSE_LDAP;
2422 else if (!strcasecmp(valstart, "dnssd") ||
2423 !strcasecmp(valstart, "dns-sd") ||
2424 !strcasecmp(valstart, "bonjour"))
2425 protocols |= BROWSE_DNSSD;
2426 else if (!strcasecmp(valstart, "lpd"))
2427 protocols |= BROWSE_LPD;
2428 else if (!strcasecmp(valstart, "smb"))
2429 protocols |= BROWSE_SMB;
2430 else if (!strcasecmp(valstart, "all"))
2431 protocols |= BROWSE_ALL;
2432 else if (strcasecmp(valstart, "none"))
2433 cupsdLogMessage(CUPSD_LOG_ERROR,
2434 "Unknown browse protocol \"%s\" ignored.", valstart);
2435
2436 for (valstart = valend; *valstart; valstart ++)
2437 if (!isspace(*valstart & 255) || *valstart != ',')
2438 break;
2439 }
2440
2441 return (protocols);
2442 }
2443
2444
2445 /*
2446 * 'read_configuration()' - Read a configuration file.
2447 */
2448
2449 static int /* O - 1 on success, 0 on failure */
2450 read_configuration(cups_file_t *fp) /* I - File to read from */
2451 {
2452 int i; /* Looping var */
2453 int linenum; /* Current line number */
2454 char line[HTTP_MAX_BUFFER],
2455 /* Line from file */
2456 temp[HTTP_MAX_BUFFER],
2457 /* Temporary buffer for value */
2458 *ptr, /* Pointer into line/temp */
2459 *value, /* Pointer to value */
2460 *valueptr; /* Pointer into value */
2461 int valuelen; /* Length of value */
2462 cupsd_var_t const *var; /* Current variable */
2463 http_addrlist_t *addrlist, /* Address list */
2464 *addr; /* Current address */
2465 unsigned ip[4], /* Address value */
2466 mask[4]; /* Netmask value */
2467 cupsd_dirsvc_relay_t *relay; /* Relay data */
2468 cupsd_dirsvc_poll_t *pollp; /* Polling data */
2469 cupsd_location_t *location; /* Browse location */
2470 cups_file_t *incfile; /* Include file */
2471 char incname[1024]; /* Include filename */
2472 struct group *group; /* Group */
2473
2474
2475 /*
2476 * Loop through each line in the file...
2477 */
2478
2479 linenum = 0;
2480
2481 while (cupsFileGetConf(fp, line, sizeof(line), &value, &linenum))
2482 {
2483 /*
2484 * Decode the directive...
2485 */
2486
2487 if (!strcasecmp(line, "Include") && value)
2488 {
2489 /*
2490 * Include filename
2491 */
2492
2493 if (value[0] == '/')
2494 strlcpy(incname, value, sizeof(incname));
2495 else
2496 snprintf(incname, sizeof(incname), "%s/%s", ServerRoot, value);
2497
2498 if ((incfile = cupsFileOpen(incname, "rb")) == NULL)
2499 cupsdLogMessage(CUPSD_LOG_ERROR,
2500 "Unable to include config file \"%s\" - %s",
2501 incname, strerror(errno));
2502 else
2503 {
2504 read_configuration(incfile);
2505 cupsFileClose(incfile);
2506 }
2507 }
2508 else if (!strcasecmp(line, "<Location") && value)
2509 {
2510 /*
2511 * <Location path>
2512 */
2513
2514 linenum = read_location(fp, value, linenum);
2515 if (linenum == 0)
2516 return (0);
2517 }
2518 else if (!strcasecmp(line, "<Policy") && value)
2519 {
2520 /*
2521 * <Policy name>
2522 */
2523
2524 linenum = read_policy(fp, value, linenum);
2525 if (linenum == 0)
2526 return (0);
2527 }
2528 else if (!strcasecmp(line, "FatalErrors"))
2529 FatalErrors = parse_fatal_errors(value);
2530 else if (!strcasecmp(line, "FaxRetryInterval") && value)
2531 {
2532 JobRetryInterval = atoi(value);
2533 cupsdLogMessage(CUPSD_LOG_WARN,
2534 "FaxRetryInterval is deprecated; use "
2535 "JobRetryInterval on line %d.", linenum);
2536 }
2537 else if (!strcasecmp(line, "FaxRetryLimit") && value)
2538 {
2539 JobRetryLimit = atoi(value);
2540 cupsdLogMessage(CUPSD_LOG_WARN,
2541 "FaxRetryLimit is deprecated; use "
2542 "JobRetryLimit on line %d.", linenum);
2543 }
2544 else if (!strcasecmp(line, "Port") || !strcasecmp(line, "Listen")
2545 #ifdef HAVE_SSL
2546 || !strcasecmp(line, "SSLPort") || !strcasecmp(line, "SSLListen")
2547 #endif /* HAVE_SSL */
2548 )
2549 {
2550 /*
2551 * Add listening address(es) to the list...
2552 */
2553
2554 cupsd_listener_t *lis; /* New listeners array */
2555
2556
2557 /*
2558 * Get the address list...
2559 */
2560
2561 addrlist = get_address(value, IPP_PORT);
2562
2563 if (!addrlist)
2564 {
2565 cupsdLogMessage(CUPSD_LOG_ERROR, "Bad %s address %s at line %d.", line,
2566 value, linenum);
2567 continue;
2568 }
2569
2570 /*
2571 * Add each address...
2572 */
2573
2574 for (addr = addrlist; addr; addr = addr->next)
2575 {
2576 /*
2577 * See if this address is already present...
2578 */
2579
2580 for (lis = (cupsd_listener_t *)cupsArrayFirst(Listeners);
2581 lis;
2582 lis = (cupsd_listener_t *)cupsArrayNext(Listeners))
2583 if (httpAddrEqual(&(addr->addr), &(lis->address)) &&
2584 _httpAddrPort(&(addr->addr)) == _httpAddrPort(&(lis->address)))
2585 break;
2586
2587 if (lis)
2588 {
2589 httpAddrString(&lis->address, temp, sizeof(temp));
2590 cupsdLogMessage(CUPSD_LOG_WARN,
2591 "Duplicate listen address \"%s\" ignored.", temp);
2592 continue;
2593 }
2594
2595 /*
2596 * Allocate another listener...
2597 */
2598
2599 if (!Listeners)
2600 Listeners = cupsArrayNew(NULL, NULL);
2601
2602 if (!Listeners)
2603 {
2604 cupsdLogMessage(CUPSD_LOG_ERROR,
2605 "Unable to allocate %s at line %d - %s.",
2606 line, linenum, strerror(errno));
2607 break;
2608 }
2609
2610 if ((lis = calloc(1, sizeof(cupsd_listener_t))) == NULL)
2611 {
2612 cupsdLogMessage(CUPSD_LOG_ERROR,
2613 "Unable to allocate %s at line %d - %s.",
2614 line, linenum, strerror(errno));
2615 break;
2616 }
2617
2618 cupsArrayAdd(Listeners, lis);
2619
2620 /*
2621 * Copy the current address and log it...
2622 */
2623
2624 memcpy(&(lis->address), &(addr->addr), sizeof(lis->address));
2625 lis->fd = -1;
2626
2627 #ifdef HAVE_SSL
2628 if (!strcasecmp(line, "SSLPort") || !strcasecmp(line, "SSLListen"))
2629 lis->encryption = HTTP_ENCRYPT_ALWAYS;
2630 #endif /* HAVE_SSL */
2631
2632 httpAddrString(&lis->address, temp, sizeof(temp));
2633
2634 #ifdef AF_LOCAL
2635 if (lis->address.addr.sa_family == AF_LOCAL)
2636 cupsdLogMessage(CUPSD_LOG_INFO, "Listening to %s (Domain)", temp);
2637 else
2638 #endif /* AF_LOCAL */
2639 cupsdLogMessage(CUPSD_LOG_INFO, "Listening to %s:%d (IPv%d)", temp,
2640 _httpAddrPort(&(lis->address)),
2641 _httpAddrFamily(&(lis->address)) == AF_INET ? 4 : 6);
2642
2643 if (!httpAddrLocalhost(&(lis->address)))
2644 RemotePort = _httpAddrPort(&(lis->address));
2645 }
2646
2647 /*
2648 * Free the list...
2649 */
2650
2651 httpAddrFreeList(addrlist);
2652 }
2653 else if (!strcasecmp(line, "BrowseAddress") && value)
2654 {
2655 /*
2656 * Add a browse address to the list...
2657 */
2658
2659 cupsd_dirsvc_addr_t *dira; /* New browse address array */
2660
2661
2662 if (NumBrowsers == 0)
2663 dira = malloc(sizeof(cupsd_dirsvc_addr_t));
2664 else
2665 dira = realloc(Browsers, (NumBrowsers + 1) * sizeof(cupsd_dirsvc_addr_t));
2666
2667 if (!dira)
2668 {
2669 cupsdLogMessage(CUPSD_LOG_ERROR,
2670 "Unable to allocate BrowseAddress at line %d - %s.",
2671 linenum, strerror(errno));
2672 continue;
2673 }
2674
2675 Browsers = dira;
2676 dira += NumBrowsers;
2677
2678 memset(dira, 0, sizeof(cupsd_dirsvc_addr_t));
2679
2680 if (!strcasecmp(value, "@LOCAL"))
2681 {
2682 /*
2683 * Send browse data to all local interfaces...
2684 */
2685
2686 strcpy(dira->iface, "*");
2687 NumBrowsers ++;
2688 }
2689 else if (!strncasecmp(value, "@IF(", 4))
2690 {
2691 /*
2692 * Send browse data to the named interface...
2693 */
2694
2695 strlcpy(dira->iface, value + 4, sizeof(Browsers[0].iface));
2696
2697 ptr = dira->iface + strlen(dira->iface) - 1;
2698 if (*ptr == ')')
2699 *ptr = '\0';
2700
2701 NumBrowsers ++;
2702 }
2703 else if ((addrlist = get_address(value, BrowsePort)) != NULL)
2704 {
2705 /*
2706 * Only IPv4 addresses are supported...
2707 */
2708
2709 for (addr = addrlist; addr; addr = addr->next)
2710 if (_httpAddrFamily(&(addr->addr)) == AF_INET)
2711 break;
2712
2713 if (addr)
2714 {
2715 memcpy(&(dira->to), &(addrlist->addr), sizeof(dira->to));
2716 httpAddrString(&(dira->to), temp, sizeof(temp));
2717
2718 cupsdLogMessage(CUPSD_LOG_INFO,
2719 "Sending browsing info to %s:%d (IPv4)",
2720 temp, _httpAddrPort(&(dira->to)));
2721
2722 NumBrowsers ++;
2723 }
2724 else
2725 cupsdLogMessage(CUPSD_LOG_ERROR, "Bad BrowseAddress %s at line %d.",
2726 value, linenum);
2727
2728 httpAddrFreeList(addrlist);
2729 }
2730 else
2731 cupsdLogMessage(CUPSD_LOG_ERROR, "Bad BrowseAddress %s at line %d.",
2732 value, linenum);
2733 }
2734 else if (!strcasecmp(line, "BrowseOrder") && value)
2735 {
2736 /*
2737 * "BrowseOrder Deny,Allow" or "BrowseOrder Allow,Deny"...
2738 */
2739
2740 if ((location = cupsdFindLocation("CUPS_INTERNAL_BROWSE_ACL")) == NULL)
2741 if ((location = cupsdNewLocation("CUPS_INTERNAL_BROWSE_ACL")) != NULL)
2742 cupsdAddLocation(location);
2743
2744 if (location == NULL)
2745 cupsdLogMessage(CUPSD_LOG_ERROR,
2746 "Unable to initialize browse access control list.");
2747 else if (!strncasecmp(value, "deny", 4))
2748 location->order_type = CUPSD_AUTH_ALLOW;
2749 else if (!strncasecmp(value, "allow", 5))
2750 location->order_type = CUPSD_AUTH_DENY;
2751 else
2752 cupsdLogMessage(CUPSD_LOG_ERROR,
2753 "Unknown BrowseOrder value %s on line %d.",
2754 value, linenum);
2755 }
2756 else if (!strcasecmp(line, "BrowseProtocols") ||
2757 !strcasecmp(line, "BrowseLocalProtocols") ||
2758 !strcasecmp(line, "BrowseRemoteProtocols"))
2759 {
2760 /*
2761 * "BrowseProtocols name [... name]"
2762 * "BrowseLocalProtocols name [... name]"
2763 * "BrowseRemoteProtocols name [... name]"
2764 */
2765
2766 int protocols = parse_protocols(value);
2767
2768 if (protocols < 0)
2769 {
2770 cupsdLogMessage(CUPSD_LOG_ERROR,
2771 "Unknown browse protocol \"%s\" on line %d.",
2772 value, linenum);
2773 break;
2774 }
2775
2776 if (strcasecmp(line, "BrowseLocalProtocols"))
2777 BrowseRemoteProtocols = protocols;
2778 if (strcasecmp(line, "BrowseRemoteProtocols"))
2779 BrowseLocalProtocols = protocols;
2780 }
2781 else if ((!strcasecmp(line, "BrowseAllow") ||
2782 !strcasecmp(line, "BrowseDeny")) && value)
2783 {
2784 /*
2785 * BrowseAllow [From] host/ip...
2786 * BrowseDeny [From] host/ip...
2787 */
2788
2789 if ((location = cupsdFindLocation("CUPS_INTERNAL_BROWSE_ACL")) == NULL)
2790 if ((location = cupsdNewLocation("CUPS_INTERNAL_BROWSE_ACL")) != NULL)
2791 cupsdAddLocation(location);
2792
2793
2794 if (location == NULL)
2795 cupsdLogMessage(CUPSD_LOG_ERROR,
2796 "Unable to initialize browse access control list.");
2797 else
2798 {
2799 if (!strncasecmp(value, "from", 4))
2800 {
2801 /*
2802 * Skip leading "from"...
2803 */
2804
2805 value += 4;
2806 }
2807
2808 while (*value)
2809 {
2810 /*
2811 * Skip leading whitespace...
2812 */
2813
2814 while (isspace(*value & 255))
2815 value ++;
2816
2817 if (!*value)
2818 break;
2819
2820 /*
2821 * Find the end of the value...
2822 */
2823
2824 for (valueptr = value;
2825 *valueptr && !isspace(*valueptr & 255);
2826 valueptr ++);
2827
2828 while (isspace(*valueptr & 255))
2829 *valueptr++ = '\0';
2830
2831 /*
2832 * Figure out what form the allow/deny address takes:
2833 *
2834 * All
2835 * None
2836 * *.domain.com
2837 * .domain.com
2838 * host.domain.com
2839 * nnn.*
2840 * nnn.nnn.*
2841 * nnn.nnn.nnn.*
2842 * nnn.nnn.nnn.nnn
2843 * nnn.nnn.nnn.nnn/mm
2844 * nnn.nnn.nnn.nnn/mmm.mmm.mmm.mmm
2845 */
2846
2847 if (!strcasecmp(value, "all"))
2848 {
2849 /*
2850 * All hosts...
2851 */
2852
2853 if (!strcasecmp(line, "BrowseAllow"))
2854 cupsdAddIPMask(&(location->allow), zeros, zeros);
2855 else
2856 cupsdAddIPMask(&(location->deny), zeros, zeros);
2857 }
2858 else if (!strcasecmp(value, "none"))
2859 {
2860 /*
2861 * No hosts...
2862 */
2863
2864 if (!strcasecmp(line, "BrowseAllow"))
2865 cupsdAddIPMask(&(location->allow), ones, zeros);
2866 else
2867 cupsdAddIPMask(&(location->deny), ones, zeros);
2868 }
2869 #ifdef AF_INET6
2870 else if (value[0] == '*' || value[0] == '.' ||
2871 (!isdigit(value[0] & 255) && value[0] != '['))
2872 #else
2873 else if (value[0] == '*' || value[0] == '.' ||
2874 !isdigit(value[0] & 255))
2875 #endif /* AF_INET6 */
2876 {
2877 /*
2878 * Host or domain name...
2879 */
2880
2881 if (!strcasecmp(line, "BrowseAllow"))
2882 cupsdAddNameMask(&(location->allow), value);
2883 else
2884 cupsdAddNameMask(&(location->deny), value);
2885 }
2886 else
2887 {
2888 /*
2889 * One of many IP address forms...
2890 */
2891
2892 if (!get_addr_and_mask(value, ip, mask))
2893 {
2894 cupsdLogMessage(CUPSD_LOG_ERROR, "Bad netmask value %s on line %d.",
2895 value, linenum);
2896 break;
2897 }
2898
2899 if (!strcasecmp(line, "BrowseAllow"))
2900 cupsdAddIPMask(&(location->allow), ip, mask);
2901 else
2902 cupsdAddIPMask(&(location->deny), ip, mask);
2903 }
2904
2905 /*
2906 * Advance to next value...
2907 */
2908
2909 value = valueptr;
2910 }
2911 }
2912 }
2913 else if (!strcasecmp(line, "BrowseRelay") && value)
2914 {
2915 /*
2916 * BrowseRelay [from] source [to] destination
2917 */
2918
2919 if (NumRelays == 0)
2920 relay = malloc(sizeof(cupsd_dirsvc_relay_t));
2921 else
2922 relay = realloc(Relays, (NumRelays + 1) * sizeof(cupsd_dirsvc_relay_t));
2923
2924 if (!relay)
2925 {
2926 cupsdLogMessage(CUPSD_LOG_ERROR,
2927 "Unable to allocate BrowseRelay at line %d - %s.",
2928 linenum, strerror(errno));
2929 continue;
2930 }
2931
2932 Relays = relay;
2933 relay += NumRelays;
2934
2935 memset(relay, 0, sizeof(cupsd_dirsvc_relay_t));
2936
2937 if (!strncasecmp(value, "from ", 5))
2938 {
2939 /*
2940 * Skip leading "from"...
2941 */
2942
2943 value += 5;
2944
2945 /*
2946 * Skip leading whitespace...
2947 */
2948
2949 while (isspace(*value))
2950 value ++;
2951 }
2952
2953 /*
2954 * Find the end of the from value...
2955 */
2956
2957 for (valueptr = value;
2958 *valueptr && !isspace(*valueptr & 255);
2959 valueptr ++);
2960
2961 while (isspace(*valueptr & 255))
2962 *valueptr++ = '\0';
2963
2964 /*
2965 * Figure out what form the from address takes:
2966 *
2967 * *.domain.com
2968 * .domain.com
2969 * host.domain.com
2970 * nnn.*
2971 * nnn.nnn.*
2972 * nnn.nnn.nnn.*
2973 * nnn.nnn.nnn.nnn
2974 * nnn.nnn.nnn.nnn/mm
2975 * nnn.nnn.nnn.nnn/mmm.mmm.mmm.mmm
2976 */
2977
2978 #ifdef AF_INET6
2979 if (value[0] == '*' || value[0] == '.' ||
2980 (!isdigit(value[0] & 255) && value[0] != '['))
2981 #else
2982 if (value[0] == '*' || value[0] == '.' || !isdigit(value[0] & 255))
2983 #endif /* AF_INET6 */
2984 {
2985 /*
2986 * Host or domain name...
2987 */
2988
2989 if (!cupsdAddNameMask(&(relay->from), value))
2990 {
2991 cupsdLogMessage(CUPSD_LOG_ERROR,
2992 "Unable to allocate BrowseRelay name at line %d - %s.",
2993 linenum, strerror(errno));
2994 continue;
2995 }
2996 }
2997 else
2998 {
2999 /*
3000 * One of many IP address forms...
3001 */
3002
3003 if (!get_addr_and_mask(value, ip, mask))
3004 {
3005 cupsdLogMessage(CUPSD_LOG_ERROR, "Bad netmask value %s on line %d.",
3006 value, linenum);
3007 break;
3008 }
3009
3010 if (!cupsdAddIPMask(&(relay->from), ip, mask))
3011 {
3012 cupsdLogMessage(CUPSD_LOG_ERROR,
3013 "Unable to allocate BrowseRelay IP at line %d - %s.",
3014 linenum, strerror(errno));
3015 continue;
3016 }
3017 }
3018
3019 /*
3020 * Get "to" address and port...
3021 */
3022
3023 if (!strncasecmp(valueptr, "to ", 3))
3024 {
3025 /*
3026 * Strip leading "to"...
3027 */
3028
3029 valueptr += 3;
3030
3031 while (isspace(*valueptr))
3032 valueptr ++;
3033 }
3034
3035 if ((addrlist = get_address(valueptr, BrowsePort)) != NULL)
3036 {
3037 /*
3038 * Only IPv4 addresses are supported...
3039 */
3040
3041 for (addr = addrlist; addr; addr = addr->next)
3042 if (addr->addr.addr.sa_family == AF_INET)
3043 break;
3044
3045 if (addr)
3046 {
3047 memcpy(&(relay->to), &(addrlist->addr), sizeof(relay->to));
3048
3049 httpAddrString(&(relay->to), temp, sizeof(temp));
3050
3051 cupsdLogMessage(CUPSD_LOG_INFO, "Relaying from %s to %s:%d (IPv4)",
3052 value, temp, _httpAddrPort(&(relay->to)));
3053
3054 NumRelays ++;
3055 }
3056 else
3057 {
3058 cupsArrayDelete(relay->from);
3059 relay->from = NULL;
3060
3061 cupsdLogMessage(CUPSD_LOG_ERROR, "Bad relay address %s at line %d.",
3062 valueptr, linenum);
3063 }
3064
3065 httpAddrFreeList(addrlist);
3066 }
3067 else
3068 {
3069 cupsArrayDelete(relay->from);
3070 relay->from = NULL;
3071
3072 cupsdLogMessage(CUPSD_LOG_ERROR, "Bad relay address %s at line %d.",
3073 valueptr, linenum);
3074 }
3075 }
3076 else if (!strcasecmp(line, "BrowsePoll") && value)
3077 {
3078 /*
3079 * BrowsePoll address[:port]
3080 */
3081
3082 char *portname; /* Port name */
3083 int portnum; /* Port number */
3084 struct servent *service; /* Service */
3085
3086
3087 /*
3088 * Extract the port name from the address...
3089 */
3090
3091 if ((portname = strrchr(value, ':')) != NULL && !strchr(portname, ']'))
3092 {
3093 *portname++ = '\0';
3094
3095 if (isdigit(*portname & 255))
3096 portnum = atoi(portname);
3097 else if ((service = getservbyname(portname, NULL)) != NULL)
3098 portnum = ntohs(service->s_port);
3099 else
3100 {
3101 cupsdLogMessage(CUPSD_LOG_ERROR, "Lookup of service \"%s\" failed.",
3102 portname);
3103 continue;
3104 }
3105 }
3106 else
3107 portnum = ippPort();
3108
3109 /*
3110 * Add the poll entry...
3111 */
3112
3113 if (NumPolled == 0)
3114 pollp = malloc(sizeof(cupsd_dirsvc_poll_t));
3115 else
3116 pollp = realloc(Polled, (NumPolled + 1) * sizeof(cupsd_dirsvc_poll_t));
3117
3118 if (!pollp)
3119 {
3120 cupsdLogMessage(CUPSD_LOG_ERROR,
3121 "Unable to allocate BrowsePoll at line %d - %s.",
3122 linenum, strerror(errno));
3123 continue;
3124 }
3125
3126 Polled = pollp;
3127 pollp += NumPolled;
3128
3129 NumPolled ++;
3130 memset(pollp, 0, sizeof(cupsd_dirsvc_poll_t));
3131
3132 strlcpy(pollp->hostname, value, sizeof(pollp->hostname));
3133 pollp->port = portnum;
3134
3135 cupsdLogMessage(CUPSD_LOG_INFO, "Polling %s:%d", pollp->hostname,
3136 pollp->port);
3137 }
3138 else if (!strcasecmp(line, "DefaultAuthType") && value)
3139 {
3140 /*
3141 * DefaultAuthType {basic,digest,basicdigest,negotiate}
3142 */
3143
3144 if (!strcasecmp(value, "none"))
3145 DefaultAuthType = CUPSD_AUTH_NONE;
3146 else if (!strcasecmp(value, "basic"))
3147 DefaultAuthType = CUPSD_AUTH_BASIC;
3148 else if (!strcasecmp(value, "digest"))
3149 DefaultAuthType = CUPSD_AUTH_DIGEST;
3150 else if (!strcasecmp(value, "basicdigest"))
3151 DefaultAuthType = CUPSD_AUTH_BASICDIGEST;
3152 #ifdef HAVE_GSSAPI
3153 else if (!strcasecmp(value, "negotiate"))
3154 DefaultAuthType = CUPSD_AUTH_NEGOTIATE;
3155 #endif /* HAVE_GSSAPI */
3156 else
3157 {
3158 cupsdLogMessage(CUPSD_LOG_WARN,
3159 "Unknown default authorization type %s on line %d.",
3160 value, linenum);
3161 if (FatalErrors & CUPSD_FATAL_CONFIG)
3162 return (0);
3163 }
3164 }
3165 #ifdef HAVE_SSL
3166 else if (!strcasecmp(line, "DefaultEncryption"))
3167 {
3168 /*
3169 * DefaultEncryption {Never,IfRequested,Required}
3170 */
3171
3172 if (!value || !strcasecmp(value, "never"))
3173 DefaultEncryption = HTTP_ENCRYPT_NEVER;
3174 else if (!strcasecmp(value, "required"))
3175 DefaultEncryption = HTTP_ENCRYPT_REQUIRED;
3176 else if (!strcasecmp(value, "ifrequested"))
3177 DefaultEncryption = HTTP_ENCRYPT_IF_REQUESTED;
3178 else
3179 {
3180 cupsdLogMessage(CUPSD_LOG_WARN,
3181 "Unknown default encryption %s on line %d.",
3182 value, linenum);
3183 if (FatalErrors & CUPSD_FATAL_CONFIG)
3184 return (0);
3185 }
3186 }
3187 #endif /* HAVE_SSL */
3188 else if (!strcasecmp(line, "User") && value)
3189 {
3190 /*
3191 * User ID to run as...
3192 */
3193
3194 if (isdigit(value[0] & 255))
3195 {
3196 int uid = atoi(value);
3197
3198 if (!uid)
3199 cupsdLogMessage(CUPSD_LOG_ERROR,
3200 "Will not use User 0 as specified on line %d "
3201 "for security reasons. You must use a non-"
3202 "privileged account instead.",
3203 linenum);
3204 else
3205 User = atoi(value);
3206 }
3207 else
3208 {
3209 struct passwd *p; /* Password information */
3210
3211 endpwent();
3212 p = getpwnam(value);
3213
3214 if (p)
3215 {
3216 if (!p->pw_uid)
3217 cupsdLogMessage(CUPSD_LOG_ERROR,
3218 "Will not use User %s (UID=0) as specified on line "
3219 "%d for security reasons. You must use a non-"
3220 "privileged account instead.",
3221 value, linenum);
3222 else
3223 User = p->pw_uid;
3224 }
3225 else
3226 cupsdLogMessage(CUPSD_LOG_ERROR,
3227 "Unknown User \"%s\" on line %d, ignoring.",
3228 value, linenum);
3229 }
3230 }
3231 else if (!strcasecmp(line, "Group") && value)
3232 {
3233 /*
3234 * Group ID to run as...
3235 */
3236
3237 if (isdigit(value[0]))
3238 Group = atoi(value);
3239 else
3240 {
3241 endgrent();
3242 group = getgrnam(value);
3243
3244 if (group != NULL)
3245 Group = group->gr_gid;
3246 else
3247 cupsdLogMessage(CUPSD_LOG_ERROR,
3248 "Unknown Group \"%s\" on line %d, ignoring.",
3249 value, linenum);
3250 }
3251 }
3252 else if (!strcasecmp(line, "SystemGroup") && value)
3253 {
3254 /*
3255 * SystemGroup (admin) group(s)...
3256 */
3257
3258 if (!parse_groups(value))
3259 cupsdLogMessage(CUPSD_LOG_ERROR,
3260 "Unknown SystemGroup \"%s\" on line %d, ignoring.",
3261 value, linenum);
3262 }
3263 else if (!strcasecmp(line, "HostNameLookups") && value)
3264 {
3265 /*
3266 * Do hostname lookups?
3267 */
3268
3269 if (!strcasecmp(value, "off") || !strcasecmp(value, "no") ||
3270 !strcasecmp(value, "false"))
3271 HostNameLookups = 0;
3272 else if (!strcasecmp(value, "on") || !strcasecmp(value, "yes") ||
3273 !strcasecmp(value, "true"))
3274 HostNameLookups = 1;
3275 else if (!strcasecmp(value, "double"))
3276 HostNameLookups = 2;
3277 else
3278 cupsdLogMessage(CUPSD_LOG_WARN, "Unknown HostNameLookups %s on line %d.",
3279 value, linenum);
3280 }
3281 else if (!strcasecmp(line, "AccessLogLevel") && value)
3282 {
3283 /*
3284 * Amount of logging to do to access log...
3285 */
3286
3287 if (!strcasecmp(value, "all"))
3288 AccessLogLevel = CUPSD_ACCESSLOG_ALL;
3289 else if (!strcasecmp(value, "actions"))
3290 AccessLogLevel = CUPSD_ACCESSLOG_ACTIONS;
3291 else if (!strcasecmp(value, "config"))
3292 AccessLogLevel = CUPSD_ACCESSLOG_CONFIG;
3293 else
3294 cupsdLogMessage(CUPSD_LOG_WARN, "Unknown AccessLogLevel %s on line %d.",
3295 value, linenum);
3296 }
3297 else if (!strcasecmp(line, "LogLevel") && value)
3298 {
3299 /*
3300 * Amount of logging to do to error log...
3301 */
3302
3303 if (!strcasecmp(value, "debug2"))
3304 LogLevel = CUPSD_LOG_DEBUG2;
3305 else if (!strcasecmp(value, "debug"))
3306 LogLevel = CUPSD_LOG_DEBUG;
3307 else if (!strcasecmp(value, "info"))
3308 LogLevel = CUPSD_LOG_INFO;
3309 else if (!strcasecmp(value, "notice"))
3310 LogLevel = CUPSD_LOG_NOTICE;
3311 else if (!strcasecmp(value, "warn"))
3312 LogLevel = CUPSD_LOG_WARN;
3313 else if (!strcasecmp(value, "error"))
3314 LogLevel = CUPSD_LOG_ERROR;
3315 else if (!strcasecmp(value, "crit"))
3316 LogLevel = CUPSD_LOG_CRIT;
3317 else if (!strcasecmp(value, "alert"))
3318 LogLevel = CUPSD_LOG_ALERT;
3319 else if (!strcasecmp(value, "emerg"))
3320 LogLevel = CUPSD_LOG_EMERG;
3321 else if (!strcasecmp(value, "none"))
3322 LogLevel = CUPSD_LOG_NONE;
3323 else
3324 cupsdLogMessage(CUPSD_LOG_WARN, "Unknown LogLevel %s on line %d.",
3325 value, linenum);
3326 }
3327 else if (!strcasecmp(line, "LogTimeFormat") && value)
3328 {
3329 /*
3330 * Amount of logging to do to error log...
3331 */
3332
3333 if (!strcasecmp(value, "standard"))
3334 LogTimeFormat = CUPSD_TIME_STANDARD;
3335 else if (!strcasecmp(value, "usecs"))
3336 LogTimeFormat = CUPSD_TIME_USECS;
3337 else
3338 cupsdLogMessage(CUPSD_LOG_WARN, "Unknown LogTimeFormat %s on line %d.",
3339 value, linenum);
3340 }
3341 else if (!strcasecmp(line, "PrintcapFormat") && value)
3342 {
3343 /*
3344 * Format of printcap file?
3345 */
3346
3347 if (!strcasecmp(value, "bsd"))
3348 PrintcapFormat = PRINTCAP_BSD;
3349 else if (!strcasecmp(value, "plist"))
3350 PrintcapFormat = PRINTCAP_PLIST;
3351 else if (!strcasecmp(value, "solaris"))
3352 PrintcapFormat = PRINTCAP_SOLARIS;
3353 else
3354 cupsdLogMessage(CUPSD_LOG_WARN, "Unknown PrintcapFormat %s on line %d.",
3355 value, linenum);
3356 }
3357 else if (!strcasecmp(line, "ServerTokens") && value)
3358 {
3359 /*
3360 * Set the string used for the Server header...
3361 */
3362
3363 struct utsname plat; /* Platform info */
3364
3365
3366 uname(&plat);
3367
3368 if (!strcasecmp(value, "ProductOnly"))
3369 cupsdSetString(&ServerHeader, "CUPS");
3370 else if (!strcasecmp(value, "Major"))
3371 cupsdSetString(&ServerHeader, "CUPS/1");
3372 else if (!strcasecmp(value, "Minor"))
3373 cupsdSetString(&ServerHeader, "CUPS/1.4");
3374 else if (!strcasecmp(value, "Minimal"))
3375 cupsdSetString(&ServerHeader, CUPS_MINIMAL);
3376 else if (!strcasecmp(value, "OS"))
3377 cupsdSetStringf(&ServerHeader, CUPS_MINIMAL " (%s)", plat.sysname);
3378 else if (!strcasecmp(value, "Full"))
3379 cupsdSetStringf(&ServerHeader, CUPS_MINIMAL " (%s) IPP/1.1",
3380 plat.sysname);
3381 else if (!strcasecmp(value, "None"))
3382 cupsdClearString(&ServerHeader);
3383 else
3384 cupsdLogMessage(CUPSD_LOG_WARN, "Unknown ServerTokens %s on line %d.",
3385 value, linenum);
3386 }
3387 else if (!strcasecmp(line, "PassEnv") && value)
3388 {
3389 /*
3390 * PassEnv variable [... variable]
3391 */
3392
3393 for (; *value;)
3394 {
3395 for (valuelen = 0; value[valuelen]; valuelen ++)
3396 if (isspace(value[valuelen]) || value[valuelen] == ',')
3397 break;
3398
3399 if (value[valuelen])
3400 {
3401 value[valuelen] = '\0';
3402 valuelen ++;
3403 }
3404
3405 cupsdSetEnv(value, NULL);
3406
3407 for (value += valuelen; *value; value ++)
3408 if (!isspace(*value) || *value != ',')
3409 break;
3410 }
3411 }
3412 else if (!strcasecmp(line, "ServerAlias") && value)
3413 {
3414 if (!ServerAlias)
3415 ServerAlias = cupsArrayNew(NULL, NULL);
3416
3417 cupsdAddAlias(ServerAlias, value);
3418 }
3419 else if (!strcasecmp(line, "SetEnv") && value)
3420 {
3421 /*
3422 * SetEnv variable value
3423 */
3424
3425 for (valueptr = value; *valueptr && !isspace(*valueptr & 255); valueptr ++);
3426
3427 if (*valueptr)
3428 {
3429 /*
3430 * Found a value...
3431 */
3432
3433 while (isspace(*valueptr & 255))
3434 *valueptr++ = '\0';
3435
3436 cupsdSetEnv(value, valueptr);
3437 }
3438 else
3439 cupsdLogMessage(CUPSD_LOG_ERROR,
3440 "Missing value for SetEnv directive on line %d.",
3441 linenum);
3442 }
3443 #ifdef HAVE_SSL
3444 else if (!strcasecmp(line, "SSLOptions"))
3445 {
3446 /*
3447 * SSLOptions options
3448 */
3449
3450 if (!value || !strcasecmp(value, "none"))
3451 SSLOptions = CUPSD_SSL_NONE;
3452 else if (!strcasecmp(value, "noemptyfragments"))
3453 SSLOptions = CUPSD_SSL_NOEMPTY;
3454 else
3455 cupsdLogMessage(CUPSD_LOG_ERROR,
3456 "Unknown value \"%s\" for SSLOptions directive on "
3457 "line %d.", value, linenum);
3458 }
3459 #endif /* HAVE_SSL */
3460 else
3461 {
3462 /*
3463 * Find a simple variable in the list...
3464 */
3465
3466 for (i = NUM_VARS, var = variables; i > 0; i --, var ++)
3467 if (!strcasecmp(line, var->name))
3468 break;
3469
3470 if (i == 0)
3471 {
3472 /*
3473 * Unknown directive! Output an error message and continue...
3474 */
3475
3476 if (!value)
3477 cupsdLogMessage(CUPSD_LOG_ERROR, "Missing value for %s on line %d.",
3478 line, linenum);
3479 else
3480 cupsdLogMessage(CUPSD_LOG_ERROR, "Unknown directive %s on line %d.",
3481 line, linenum);
3482 continue;
3483 }
3484
3485 switch (var->type)
3486 {
3487 case CUPSD_VARTYPE_INTEGER :
3488 if (!value)
3489 cupsdLogMessage(CUPSD_LOG_ERROR,
3490 "Missing integer value for %s on line %d.",
3491 line, linenum);
3492 else
3493 {
3494 int n; /* Number */
3495 char *units; /* Units */
3496
3497
3498 n = strtol(value, &units, 0);
3499
3500 if (units && *units)
3501 {
3502 if (tolower(units[0] & 255) == 'g')
3503 n *= 1024 * 1024 * 1024;
3504 else if (tolower(units[0] & 255) == 'm')
3505 n *= 1024 * 1024;
3506 else if (tolower(units[0] & 255) == 'k')
3507 n *= 1024;
3508 else if (tolower(units[0] & 255) == 't')
3509 n *= 262144;
3510 }
3511
3512 if (n < 0)
3513 cupsdLogMessage(CUPSD_LOG_ERROR,
3514 "Bad negative integer value for %s on line %d.",
3515 line, linenum);
3516 else
3517 *((int *)var->ptr) = n;
3518 }
3519 break;
3520
3521 case CUPSD_VARTYPE_BOOLEAN :
3522 if (!value)
3523 cupsdLogMessage(CUPSD_LOG_ERROR,
3524 "Missing boolean value for %s on line %d.",
3525 line, linenum);
3526 else if (!strcasecmp(value, "true") ||
3527 !strcasecmp(value, "on") ||
3528 !strcasecmp(value, "enabled") ||
3529 !strcasecmp(value, "yes") ||
3530 atoi(value) != 0)
3531 *((int *)var->ptr) = TRUE;
3532 else if (!strcasecmp(value, "false") ||
3533 !strcasecmp(value, "off") ||
3534 !strcasecmp(value, "disabled") ||
3535 !strcasecmp(value, "no") ||
3536 !strcasecmp(value, "0"))
3537 *((int *)var->ptr) = FALSE;
3538 else
3539 cupsdLogMessage(CUPSD_LOG_ERROR,
3540 "Unknown boolean value %s on line %d.",
3541 value, linenum);
3542 break;
3543
3544 case CUPSD_VARTYPE_PATHNAME :
3545 if (!value)
3546 {
3547 cupsdLogMessage(CUPSD_LOG_ERROR,
3548 "Missing pathname value for %s on line %d.",
3549 line, linenum);
3550 break;
3551 }
3552
3553 if (value[0] == '/')
3554 strlcpy(temp, value, sizeof(temp));
3555 else
3556 snprintf(temp, sizeof(temp), "%s/%s", ServerRoot, value);
3557
3558 if (access(temp, 0))
3559 {
3560 cupsdLogMessage(CUPSD_LOG_ERROR,
3561 "File or directory for \"%s %s\" on line %d "
3562 "does not exist.", line, value, linenum);
3563 break;
3564 }
3565
3566 case CUPSD_VARTYPE_STRING :
3567 cupsdSetString((char **)var->ptr, value);
3568 break;
3569 }
3570 }
3571 }
3572
3573 return (1);
3574 }
3575
3576
3577 /*
3578 * 'read_location()' - Read a <Location path> definition.
3579 */
3580
3581 static int /* O - New line number or 0 on error */
3582 read_location(cups_file_t *fp, /* I - Configuration file */
3583 char *location, /* I - Location name/path */
3584 int linenum) /* I - Current line number */
3585 {
3586 cupsd_location_t *loc, /* New location */
3587 *parent; /* Parent location */
3588 char line[HTTP_MAX_BUFFER],
3589 /* Line buffer */
3590 *value, /* Value for directive */
3591 *valptr; /* Pointer into value */
3592
3593
3594 if ((parent = cupsdFindLocation(location)) != NULL)
3595 cupsdLogMessage(CUPSD_LOG_WARN, "Duplicate <Location %s> on line %d.",
3596 location, linenum);
3597 else if ((parent = cupsdNewLocation(location)) == NULL)
3598 return (0);
3599 else
3600 {
3601 cupsdAddLocation(parent);
3602
3603 parent->limit = CUPSD_AUTH_LIMIT_ALL;
3604 }
3605
3606 loc = parent;
3607
3608 while (cupsFileGetConf(fp, line, sizeof(line), &value, &linenum))
3609 {
3610 /*
3611 * Decode the directive...
3612 */
3613
3614 if (!strcasecmp(line, "</Location>"))
3615 return (linenum);
3616 else if (!strcasecmp(line, "<Limit") ||
3617 !strcasecmp(line, "<LimitExcept"))
3618 {
3619 if (!value)
3620 {
3621 cupsdLogMessage(CUPSD_LOG_ERROR, "Syntax error on line %d.", linenum);
3622 if (FatalErrors & CUPSD_FATAL_CONFIG)
3623 return (0);
3624 else
3625 continue;
3626 }
3627
3628 if ((loc = cupsdCopyLocation(parent)) == NULL)
3629 return (0);
3630
3631 cupsdAddLocation(loc);
3632
3633 loc->limit = 0;
3634 while (*value)
3635 {
3636 for (valptr = value; !isspace(*valptr & 255) && *valptr; valptr ++);
3637
3638 if (*valptr)
3639 *valptr++ = '\0';
3640
3641 if (!strcmp(value, "ALL"))
3642 loc->limit = CUPSD_AUTH_LIMIT_ALL;
3643 else if (!strcmp(value, "GET"))
3644 loc->limit |= CUPSD_AUTH_LIMIT_GET;
3645 else if (!strcmp(value, "HEAD"))
3646 loc->limit |= CUPSD_AUTH_LIMIT_HEAD;
3647 else if (!strcmp(value, "OPTIONS"))
3648 loc->limit |= CUPSD_AUTH_LIMIT_OPTIONS;
3649 else if (!strcmp(value, "POST"))
3650 loc->limit |= CUPSD_AUTH_LIMIT_POST;
3651 else if (!strcmp(value, "PUT"))
3652 loc->limit |= CUPSD_AUTH_LIMIT_PUT;
3653 else if (!strcmp(value, "TRACE"))
3654 loc->limit |= CUPSD_AUTH_LIMIT_TRACE;
3655 else
3656 cupsdLogMessage(CUPSD_LOG_WARN, "Unknown request type %s on line %d.",
3657 value, linenum);
3658
3659 for (value = valptr; isspace(*value & 255); value ++);
3660 }
3661
3662 if (!strcasecmp(line, "<LimitExcept"))
3663 loc->limit = CUPSD_AUTH_LIMIT_ALL ^ loc->limit;
3664
3665 parent->limit &= ~loc->limit;
3666 }
3667 else if (!strcasecmp(line, "</Limit>") ||
3668 !strcasecmp(line, "</LimitExcept>"))
3669 loc = parent;
3670 else if (!parse_aaa(loc, line, value, linenum))
3671 {
3672 cupsdLogMessage(CUPSD_LOG_ERROR,
3673 "Unknown Location directive %s on line %d.",
3674 line, linenum);
3675 if (FatalErrors & CUPSD_FATAL_CONFIG)
3676 return (0);
3677 }
3678 }
3679
3680 cupsdLogMessage(CUPSD_LOG_ERROR,
3681 "Unexpected end-of-file at line %d while reading location.",
3682 linenum);
3683
3684 return ((FatalErrors & CUPSD_FATAL_CONFIG) ? 0 : linenum);
3685 }
3686
3687
3688 /*
3689 * 'read_policy()' - Read a <Policy name> definition.
3690 */
3691
3692 static int /* O - New line number or 0 on error */
3693 read_policy(cups_file_t *fp, /* I - Configuration file */
3694 char *policy, /* I - Location name/path */
3695 int linenum) /* I - Current line number */
3696 {
3697 int i; /* Looping var */
3698 cupsd_policy_t *pol; /* Policy */
3699 cupsd_location_t *op; /* Policy operation */
3700 int num_ops; /* Number of IPP operations */
3701 ipp_op_t ops[100]; /* Operations */
3702 char line[HTTP_MAX_BUFFER],
3703 /* Line buffer */
3704 *value, /* Value for directive */
3705 *valptr; /* Pointer into value */
3706
3707
3708 /*
3709 * Create the policy...
3710 */
3711
3712 if ((pol = cupsdFindPolicy(policy)) != NULL)
3713 cupsdLogMessage(CUPSD_LOG_WARN, "Duplicate <Policy %s> on line %d.",
3714 policy, linenum);
3715 else if ((pol = cupsdAddPolicy(policy)) == NULL)
3716 return (0);
3717
3718 /*
3719 * Read from the file...
3720 */
3721
3722 op = NULL;
3723 num_ops = 0;
3724
3725 while (cupsFileGetConf(fp, line, sizeof(line), &value, &linenum))
3726 {
3727 /*
3728 * Decode the directive...
3729 */
3730
3731 if (!strcasecmp(line, "</Policy>"))
3732 {
3733 if (op)
3734 cupsdLogMessage(CUPSD_LOG_WARN,
3735 "Missing </Limit> before </Policy> on line %d.",
3736 linenum);
3737
3738 set_policy_defaults(pol);
3739
3740 return (linenum);
3741 }
3742 else if (!strcasecmp(line, "<Limit") && !op)
3743 {
3744 if (!value)
3745 {
3746 cupsdLogMessage(CUPSD_LOG_ERROR, "Syntax error on line %d.", linenum);
3747 if (FatalErrors & CUPSD_FATAL_CONFIG)
3748 return (0);
3749 else
3750 continue;
3751 }
3752
3753 /*
3754 * Scan for IPP operation names...
3755 */
3756
3757 num_ops = 0;
3758
3759 while (*value)
3760 {
3761 for (valptr = value; !isspace(*valptr & 255) && *valptr; valptr ++);
3762
3763 if (*valptr)
3764 *valptr++ = '\0';
3765
3766 if (num_ops < (int)(sizeof(ops) / sizeof(ops[0])))
3767 {
3768 if (!strcasecmp(value, "All"))
3769 ops[num_ops] = IPP_ANY_OPERATION;
3770 else if ((ops[num_ops] = ippOpValue(value)) == IPP_BAD_OPERATION)
3771 cupsdLogMessage(CUPSD_LOG_ERROR,
3772 "Bad IPP operation name \"%s\" on line %d.",
3773 value, linenum);
3774 else
3775 num_ops ++;
3776 }
3777 else
3778 cupsdLogMessage(CUPSD_LOG_ERROR,
3779 "Too many operations listed on line %d.",
3780 linenum);
3781
3782 for (value = valptr; isspace(*value & 255); value ++);
3783 }
3784
3785 /*
3786 * If none are specified, apply the policy to all operations...
3787 */
3788
3789 if (num_ops == 0)
3790 {
3791 ops[0] = IPP_ANY_OPERATION;
3792 num_ops = 1;
3793 }
3794
3795 /*
3796 * Add a new policy for the first operation...
3797 */
3798
3799 op = cupsdAddPolicyOp(pol, NULL, ops[0]);
3800 }
3801 else if (!strcasecmp(line, "</Limit>") && op)
3802 {
3803 /*
3804 * Finish the current operation limit...
3805 */
3806
3807 if (num_ops > 1)
3808 {
3809 /*
3810 * Copy the policy to the other operations...
3811 */
3812
3813 for (i = 1; i < num_ops; i ++)
3814 cupsdAddPolicyOp(pol, op, ops[i]);
3815 }
3816
3817 op = NULL;
3818 }
3819 else if (!strcasecmp(line, "JobPrivateAccess") ||
3820 !strcasecmp(line, "JobPrivateValues") ||
3821 !strcasecmp(line, "SubscriptionPrivateAccess") ||
3822 !strcasecmp(line, "SubscriptionPrivateValues"))
3823 {
3824 if (op)
3825 {
3826 cupsdLogMessage(CUPSD_LOG_ERROR,
3827 "%s directive must appear outside <Limit>...</Limit> "
3828 "on line %d.", line, linenum);
3829 if (FatalErrors & CUPSD_FATAL_CONFIG)
3830 return (0);
3831 }
3832 else
3833 {
3834 /*
3835 * Pull out whitespace-delimited values...
3836 */
3837
3838 while (*value)
3839 {
3840 /*
3841 * Find the end of the current value...
3842 */
3843
3844 for (valptr = value; !isspace(*valptr & 255) && *valptr; valptr ++);
3845
3846 if (*valptr)
3847 *valptr++ = '\0';
3848
3849 /*
3850 * Save it appropriately...
3851 */
3852
3853 if (!strcasecmp(line, "JobPrivateAccess"))
3854 {
3855 /*
3856 * JobPrivateAccess {all|default|user/group list|@@ACL}
3857 */
3858
3859 if (!strcasecmp(value, "default"))
3860 {
3861 cupsdAddString(&(pol->job_access), "@OWNER");
3862 cupsdAddString(&(pol->job_access), "@SYSTEM");
3863 }
3864 else
3865 cupsdAddString(&(pol->job_access), value);
3866 }
3867 else if (!strcasecmp(line, "JobPrivateValues"))
3868 {
3869 /*
3870 * JobPrivateValues {all|none|default|attribute list}
3871 */
3872
3873 if (!strcasecmp(value, "default"))
3874 {
3875 cupsdAddString(&(pol->job_attrs), "job-name");
3876 cupsdAddString(&(pol->job_attrs), "job-originating-host-name");
3877 cupsdAddString(&(pol->job_attrs), "job-originating-user-name");
3878 }
3879 else
3880 cupsdAddString(&(pol->job_attrs), value);
3881 }
3882 else if (!strcasecmp(line, "SubscriptionPrivateAccess"))
3883 {
3884 /*
3885 * SubscriptionPrivateAccess {all|default|user/group list|@@ACL}
3886 */
3887
3888 if (!strcasecmp(value, "default"))
3889 {
3890 cupsdAddString(&(pol->sub_access), "@OWNER");
3891 cupsdAddString(&(pol->sub_access), "@SYSTEM");
3892 }
3893 else
3894 cupsdAddString(&(pol->sub_access), value);
3895 }
3896 else /* if (!strcasecmp(line, "SubscriptionPrivateValues")) */
3897 {
3898 /*
3899 * SubscriptionPrivateValues {all|none|default|attribute list}
3900 */
3901
3902 if (!strcasecmp(value, "default"))
3903 {
3904 cupsdAddString(&(pol->sub_attrs), "notify-events");
3905 cupsdAddString(&(pol->sub_attrs), "notify-pull-method");
3906 cupsdAddString(&(pol->sub_attrs), "notify-recipient-uri");
3907 cupsdAddString(&(pol->sub_attrs), "notify-subscriber-user-name");
3908 cupsdAddString(&(pol->sub_attrs), "notify-user-data");
3909 }
3910 else
3911 cupsdAddString(&(pol->sub_attrs), value);
3912 }
3913
3914 /*
3915 * Find the next string on the line...
3916 */
3917
3918 for (value = valptr; isspace(*value & 255); value ++);
3919 }
3920 }
3921 }
3922 else if (!op)
3923 {
3924 cupsdLogMessage(CUPSD_LOG_ERROR,
3925 "Missing <Limit ops> directive before %s on line %d.",
3926 line, linenum);
3927 if (FatalErrors & CUPSD_FATAL_CONFIG)
3928 return (0);
3929 }
3930 else if (!parse_aaa(op, line, value, linenum))
3931 {
3932 if (op)
3933 cupsdLogMessage(CUPSD_LOG_ERROR,
3934 "Unknown Policy Limit directive %s on line %d.",
3935 line, linenum);
3936 else
3937 cupsdLogMessage(CUPSD_LOG_ERROR,
3938 "Unknown Policy directive %s on line %d.",
3939 line, linenum);
3940
3941 if (FatalErrors & CUPSD_FATAL_CONFIG)
3942 return (0);
3943 }
3944 }
3945
3946 cupsdLogMessage(CUPSD_LOG_ERROR,
3947 "Unexpected end-of-file at line %d while reading policy "
3948 "\"%s\".", linenum, policy);
3949
3950 return ((FatalErrors & CUPSD_FATAL_CONFIG) ? 0 : linenum);
3951 }
3952
3953
3954 /*
3955 * 'set_policy_defaults()' - Set default policy values as needed.
3956 */
3957
3958 static void
3959 set_policy_defaults(cupsd_policy_t *pol)/* I - Policy */
3960 {
3961 cupsd_location_t *op; /* Policy operation */
3962
3963
3964 /*
3965 * Verify that we have an explicit policy for Validate-Job, Cancel-Jobs,
3966 * Cancel-My-Jobs, Close-Job, and CUPS-Get-Document, which ensures that
3967 * upgrades do not introduce new security issues...
3968 */
3969
3970 if ((op = cupsdFindPolicyOp(pol, IPP_VALIDATE_JOB)) == NULL ||
3971 op->op == IPP_ANY_OPERATION)
3972 {
3973 if ((op = cupsdFindPolicyOp(pol, IPP_PRINT_JOB)) != NULL &&
3974 op->op != IPP_ANY_OPERATION)
3975 {
3976 /*
3977 * Add a new limit for Validate-Job using the Print-Job limit as a
3978 * template...
3979 */
3980
3981 cupsdLogMessage(CUPSD_LOG_WARN,
3982 "No limit for Validate-Job defined in policy %s "
3983 "- using Print-Job's policy.", pol->name);
3984
3985 cupsdAddPolicyOp(pol, op, IPP_VALIDATE_JOB);
3986 }
3987 else
3988 cupsdLogMessage(CUPSD_LOG_WARN,
3989 "No limit for Validate-Job defined in policy %s "
3990 "and no suitable template found.", pol->name);
3991 }
3992
3993 if ((op = cupsdFindPolicyOp(pol, IPP_CANCEL_JOBS)) == NULL ||
3994 op->op == IPP_ANY_OPERATION)
3995 {
3996 if ((op = cupsdFindPolicyOp(pol, IPP_PAUSE_PRINTER)) != NULL &&
3997 op->op != IPP_ANY_OPERATION)
3998 {
3999 /*
4000 * Add a new limit for Cancel-Jobs using the Pause-Printer limit as a
4001 * template...
4002 */
4003
4004 cupsdLogMessage(CUPSD_LOG_WARN,
4005 "No limit for Cancel-Jobs defined in policy %s "
4006 "- using Pause-Printer's policy.", pol->name);
4007
4008 cupsdAddPolicyOp(pol, op, IPP_CANCEL_JOBS);
4009 }
4010 else
4011 cupsdLogMessage(CUPSD_LOG_WARN,
4012 "No limit for Cancel-Jobs defined in policy %s "
4013 "and no suitable template found.", pol->name);
4014 }
4015
4016 if ((op = cupsdFindPolicyOp(pol, IPP_CANCEL_MY_JOBS)) == NULL ||
4017 op->op == IPP_ANY_OPERATION)
4018 {
4019 if ((op = cupsdFindPolicyOp(pol, IPP_SEND_DOCUMENT)) != NULL &&
4020 op->op != IPP_ANY_OPERATION)
4021 {
4022 /*
4023 * Add a new limit for Cancel-My-Jobs using the Send-Document limit as
4024 * a template...
4025 */
4026
4027 cupsdLogMessage(CUPSD_LOG_WARN,
4028 "No limit for Cancel-My-Jobs defined in policy %s "
4029 "- using Send-Document's policy.", pol->name);
4030
4031 cupsdAddPolicyOp(pol, op, IPP_CANCEL_MY_JOBS);
4032 }
4033 else
4034 cupsdLogMessage(CUPSD_LOG_WARN,
4035 "No limit for Cancel-My-Jobs defined in policy %s "
4036 "and no suitable template found.", pol->name);
4037 }
4038
4039 if ((op = cupsdFindPolicyOp(pol, IPP_CLOSE_JOB)) == NULL ||
4040 op->op == IPP_ANY_OPERATION)
4041 {
4042 if ((op = cupsdFindPolicyOp(pol, IPP_SEND_DOCUMENT)) != NULL &&
4043 op->op != IPP_ANY_OPERATION)
4044 {
4045 /*
4046 * Add a new limit for Close-Job using the Send-Document limit as a
4047 * template...
4048 */
4049
4050 cupsdLogMessage(CUPSD_LOG_WARN,
4051 "No limit for Close-Job defined in policy %s "
4052 "- using Send-Document's policy.", pol->name);
4053
4054 cupsdAddPolicyOp(pol, op, IPP_CLOSE_JOB);
4055 }
4056 else
4057 cupsdLogMessage(CUPSD_LOG_WARN,
4058 "No limit for Close-Job defined in policy %s "
4059 "and no suitable template found.", pol->name);
4060 }
4061
4062 if ((op = cupsdFindPolicyOp(pol, CUPS_GET_DOCUMENT)) == NULL ||
4063 op->op == IPP_ANY_OPERATION)
4064 {
4065 if ((op = cupsdFindPolicyOp(pol, IPP_SEND_DOCUMENT)) != NULL &&
4066 op->op != IPP_ANY_OPERATION)
4067 {
4068 /*
4069 * Add a new limit for CUPS-Get-Document using the Send-Document
4070 * limit as a template...
4071 */
4072
4073 cupsdLogMessage(CUPSD_LOG_WARN,
4074 "No limit for CUPS-Get-Document defined in policy %s "
4075 "- using Send-Document's policy.", pol->name);
4076
4077 cupsdAddPolicyOp(pol, op, CUPS_GET_DOCUMENT);
4078 }
4079 else
4080 cupsdLogMessage(CUPSD_LOG_WARN,
4081 "No limit for CUPS-Get-Document defined in policy %s "
4082 "and no suitable template found.", pol->name);
4083 }
4084
4085 /*
4086 * Verify we have JobPrivateAccess, JobPrivateValues,
4087 * SubscriptionPrivateAccess, and SubscriptionPrivateValues in the policy.
4088 */
4089
4090 if (!pol->job_access)
4091 {
4092 cupsdLogMessage(CUPSD_LOG_WARN,
4093 "No JobPrivateAccess defined in policy %s "
4094 "- using defaults.", pol->name);
4095 cupsdAddString(&(pol->job_access), "@OWNER");
4096 cupsdAddString(&(pol->job_access), "@SYSTEM");
4097 }
4098
4099 if (!pol->job_attrs)
4100 {
4101 cupsdLogMessage(CUPSD_LOG_WARN,
4102 "No JobPrivateValues defined in policy %s "
4103 "- using defaults.", pol->name);
4104 cupsdAddString(&(pol->job_attrs), "job-name");
4105 cupsdAddString(&(pol->job_attrs), "job-originating-host-name");
4106 cupsdAddString(&(pol->job_attrs), "job-originating-user-name");
4107 }
4108
4109 if (!pol->sub_access)
4110 {
4111 cupsdLogMessage(CUPSD_LOG_WARN,
4112 "No SubscriptionPrivateAccess defined in policy %s "
4113 "- using defaults.", pol->name);
4114 cupsdAddString(&(pol->sub_access), "@OWNER");
4115 cupsdAddString(&(pol->sub_access), "@SYSTEM");
4116 }
4117
4118 if (!pol->sub_attrs)
4119 {
4120 cupsdLogMessage(CUPSD_LOG_WARN,
4121 "No SubscriptionPrivateValues defined in policy %s "
4122 "- using defaults.", pol->name);
4123 cupsdAddString(&(pol->sub_attrs), "notify-events");
4124 cupsdAddString(&(pol->sub_attrs), "notify-pull-method");
4125 cupsdAddString(&(pol->sub_attrs), "notify-recipient-uri");
4126 cupsdAddString(&(pol->sub_attrs), "notify-subscriber-user-name");
4127 cupsdAddString(&(pol->sub_attrs), "notify-user-data");
4128 }
4129 }
4130
4131
4132 /*
4133 * End of "$Id: conf.c 9352 2010-11-06 04:55:26Z mike $".
4134 */