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