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