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