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