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