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