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