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