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