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