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