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