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