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