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