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