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