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