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