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