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