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