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