Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
srohatgi01
GitHub Repository: srohatgi01/cups
Path: blob/master/scheduler/conf.c
1090 views
1
/*
2
* Configuration routines for the CUPS scheduler.
3
*
4
* Copyright © 2021-2022 by OpenPrinting.
5
* Copyright © 2007-2018 by Apple Inc.
6
* Copyright © 1997-2007 by Easy Software Products, all rights reserved.
7
*
8
* Licensed under Apache License v2.0. See the file "LICENSE" for more
9
* information.
10
*/
11
12
/*
13
* Include necessary headers...
14
*/
15
16
#include "cupsd.h"
17
#include <stdarg.h>
18
#include <grp.h>
19
#include <sys/utsname.h>
20
#ifdef HAVE_ASL_H
21
# include <asl.h>
22
#elif defined(HAVE_SYSTEMD_SD_JOURNAL_H)
23
# define SD_JOURNAL_SUPPRESS_LOCATION
24
# include <systemd/sd-journal.h>
25
#endif /* HAVE_ASL_H */
26
#include <syslog.h>
27
28
#ifdef HAVE_LIBPAPER
29
# include <paper.h>
30
#endif /* HAVE_LIBPAPER */
31
32
33
/*
34
* Possibly missing network definitions...
35
*/
36
37
#ifndef INADDR_NONE
38
# define INADDR_NONE 0xffffffff
39
#endif /* !INADDR_NONE */
40
41
42
/*
43
* Configuration variable structure...
44
*/
45
46
typedef enum
47
{
48
CUPSD_VARTYPE_INTEGER, /* Integer option */
49
CUPSD_VARTYPE_TIME, /* Time interval option */
50
CUPSD_VARTYPE_STRING, /* String option */
51
CUPSD_VARTYPE_BOOLEAN, /* Boolean option */
52
CUPSD_VARTYPE_PATHNAME, /* File/directory name option */
53
CUPSD_VARTYPE_PERM /* File/directory permissions */
54
} cupsd_vartype_t;
55
56
typedef struct
57
{
58
const char *name; /* Name of variable */
59
void *ptr; /* Pointer to variable */
60
cupsd_vartype_t type; /* Type (int, string, address) */
61
} cupsd_var_t;
62
63
64
/*
65
* Local globals...
66
*/
67
68
static const cupsd_var_t cupsd_vars[] =
69
{
70
{ "AutoPurgeJobs", &JobAutoPurge, CUPSD_VARTYPE_BOOLEAN },
71
#ifdef HAVE_DNSSD
72
{ "BrowseDNSSDSubTypes", &DNSSDSubTypes, CUPSD_VARTYPE_STRING },
73
#endif /* HAVE_DNSSD */
74
{ "BrowseWebIF", &BrowseWebIF, CUPSD_VARTYPE_BOOLEAN },
75
{ "Browsing", &Browsing, CUPSD_VARTYPE_BOOLEAN },
76
{ "Classification", &Classification, CUPSD_VARTYPE_STRING },
77
{ "ClassifyOverride", &ClassifyOverride, CUPSD_VARTYPE_BOOLEAN },
78
{ "DefaultLanguage", &DefaultLanguage, CUPSD_VARTYPE_STRING },
79
{ "DefaultLeaseDuration", &DefaultLeaseDuration, CUPSD_VARTYPE_TIME },
80
{ "DefaultPaperSize", &DefaultPaperSize, CUPSD_VARTYPE_STRING },
81
{ "DefaultPolicy", &DefaultPolicy, CUPSD_VARTYPE_STRING },
82
{ "DefaultShared", &DefaultShared, CUPSD_VARTYPE_BOOLEAN },
83
{ "DirtyCleanInterval", &DirtyCleanInterval, CUPSD_VARTYPE_TIME },
84
#ifdef HAVE_DNSSD
85
{ "DNSSDHostName", &DNSSDHostName, CUPSD_VARTYPE_STRING },
86
#endif /* HAVE_DNSSD */
87
{ "ErrorPolicy", &ErrorPolicy, CUPSD_VARTYPE_STRING },
88
{ "FilterLimit", &FilterLimit, CUPSD_VARTYPE_INTEGER },
89
{ "FilterNice", &FilterNice, CUPSD_VARTYPE_INTEGER },
90
#ifdef HAVE_GSSAPI
91
{ "GSSServiceName", &GSSServiceName, CUPSD_VARTYPE_STRING },
92
#endif /* HAVE_GSSAPI */
93
#ifdef HAVE_ONDEMAND
94
{ "IdleExitTimeout", &IdleExitTimeout, CUPSD_VARTYPE_TIME },
95
#endif /* HAVE_ONDEMAND */
96
{ "JobKillDelay", &JobKillDelay, CUPSD_VARTYPE_TIME },
97
{ "JobRetryLimit", &JobRetryLimit, CUPSD_VARTYPE_INTEGER },
98
{ "JobRetryInterval", &JobRetryInterval, CUPSD_VARTYPE_TIME },
99
{ "KeepAlive", &KeepAlive, CUPSD_VARTYPE_BOOLEAN },
100
#ifdef HAVE_LAUNCHD
101
{ "LaunchdTimeout", &IdleExitTimeout, CUPSD_VARTYPE_TIME },
102
#endif /* HAVE_LAUNCHD */
103
{ "LimitRequestBody", &MaxRequestSize, CUPSD_VARTYPE_INTEGER },
104
{ "LogDebugHistory", &LogDebugHistory, CUPSD_VARTYPE_INTEGER },
105
{ "MaxActiveJobs", &MaxActiveJobs, CUPSD_VARTYPE_INTEGER },
106
{ "MaxClients", &MaxClients, CUPSD_VARTYPE_INTEGER },
107
{ "MaxClientsPerHost", &MaxClientsPerHost, CUPSD_VARTYPE_INTEGER },
108
{ "MaxCopies", &MaxCopies, CUPSD_VARTYPE_INTEGER },
109
{ "MaxEvents", &MaxEvents, CUPSD_VARTYPE_INTEGER },
110
{ "MaxHoldTime", &MaxHoldTime, CUPSD_VARTYPE_TIME },
111
{ "MaxJobs", &MaxJobs, CUPSD_VARTYPE_INTEGER },
112
{ "MaxJobsPerPrinter", &MaxJobsPerPrinter, CUPSD_VARTYPE_INTEGER },
113
{ "MaxJobsPerUser", &MaxJobsPerUser, CUPSD_VARTYPE_INTEGER },
114
{ "MaxJobTime", &MaxJobTime, CUPSD_VARTYPE_TIME },
115
{ "MaxLeaseDuration", &MaxLeaseDuration, CUPSD_VARTYPE_TIME },
116
{ "MaxLogSize", &MaxLogSize, CUPSD_VARTYPE_INTEGER },
117
{ "MaxRequestSize", &MaxRequestSize, CUPSD_VARTYPE_INTEGER },
118
{ "MaxSubscriptions", &MaxSubscriptions, CUPSD_VARTYPE_INTEGER },
119
{ "MaxSubscriptionsPerJob", &MaxSubscriptionsPerJob, CUPSD_VARTYPE_INTEGER },
120
{ "MaxSubscriptionsPerPrinter",&MaxSubscriptionsPerPrinter, CUPSD_VARTYPE_INTEGER },
121
{ "MaxSubscriptionsPerUser", &MaxSubscriptionsPerUser, CUPSD_VARTYPE_INTEGER },
122
{ "MultipleOperationTimeout", &MultipleOperationTimeout, CUPSD_VARTYPE_TIME },
123
{ "PageLogFormat", &PageLogFormat, CUPSD_VARTYPE_STRING },
124
{ "PreserveJobFiles", &JobFiles, CUPSD_VARTYPE_TIME },
125
{ "PreserveJobHistory", &JobHistory, CUPSD_VARTYPE_TIME },
126
{ "ReloadTimeout", &ReloadTimeout, CUPSD_VARTYPE_TIME },
127
{ "RootCertDuration", &RootCertDuration, CUPSD_VARTYPE_TIME },
128
{ "ServerAdmin", &ServerAdmin, CUPSD_VARTYPE_STRING },
129
{ "ServerName", &ServerName, CUPSD_VARTYPE_STRING },
130
{ "StrictConformance", &StrictConformance, CUPSD_VARTYPE_BOOLEAN },
131
{ "Timeout", &Timeout, CUPSD_VARTYPE_TIME },
132
{ "WebInterface", &WebInterface, CUPSD_VARTYPE_BOOLEAN }
133
};
134
static const cupsd_var_t cupsfiles_vars[] =
135
{
136
{ "AccessLog", &AccessLog, CUPSD_VARTYPE_STRING },
137
{ "CacheDir", &CacheDir, CUPSD_VARTYPE_STRING },
138
{ "ConfigFilePerm", &ConfigFilePerm, CUPSD_VARTYPE_PERM },
139
#ifdef HAVE_TLS
140
{ "CreateSelfSignedCerts", &CreateSelfSignedCerts, CUPSD_VARTYPE_BOOLEAN },
141
#endif /* HAVE_TLS */
142
{ "DataDir", &DataDir, CUPSD_VARTYPE_STRING },
143
{ "DocumentRoot", &DocumentRoot, CUPSD_VARTYPE_STRING },
144
{ "ErrorLog", &ErrorLog, CUPSD_VARTYPE_STRING },
145
{ "FileDevice", &FileDevice, CUPSD_VARTYPE_BOOLEAN },
146
{ "LogFilePerm", &LogFilePerm, CUPSD_VARTYPE_PERM },
147
{ "PageLog", &PageLog, CUPSD_VARTYPE_STRING },
148
{ "Printcap", &Printcap, CUPSD_VARTYPE_STRING },
149
{ "RemoteRoot", &RemoteRoot, CUPSD_VARTYPE_STRING },
150
{ "RequestRoot", &RequestRoot, CUPSD_VARTYPE_STRING },
151
{ "ServerBin", &ServerBin, CUPSD_VARTYPE_PATHNAME },
152
#ifdef HAVE_TLS
153
{ "ServerKeychain", &ServerKeychain, CUPSD_VARTYPE_PATHNAME },
154
#endif /* HAVE_TLS */
155
{ "ServerRoot", &ServerRoot, CUPSD_VARTYPE_PATHNAME },
156
{ "StateDir", &StateDir, CUPSD_VARTYPE_STRING },
157
{ "SyncOnClose", &SyncOnClose, CUPSD_VARTYPE_BOOLEAN },
158
#ifdef HAVE_AUTHORIZATION_H
159
{ "SystemGroupAuthKey", &SystemGroupAuthKey, CUPSD_VARTYPE_STRING },
160
#endif /* HAVE_AUTHORIZATION_H */
161
{ "TempDir", &TempDir, CUPSD_VARTYPE_PATHNAME }
162
};
163
164
static int default_auth_type = CUPSD_AUTH_AUTO;
165
/* Default AuthType, if not specified */
166
167
static const unsigned ones[4] =
168
{
169
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff
170
};
171
static const unsigned zeros[4] =
172
{
173
0x00000000, 0x00000000, 0x00000000, 0x00000000
174
};
175
176
177
/*
178
* Local functions...
179
*/
180
181
static http_addrlist_t *get_address(const char *value, int defport);
182
static int get_addr_and_mask(const char *value, unsigned *ip,
183
unsigned *mask);
184
static void mime_error_cb(void *ctx, const char *message);
185
static int parse_aaa(cupsd_location_t *loc, char *line,
186
char *value, int linenum);
187
static int parse_fatal_errors(const char *s);
188
static int parse_groups(const char *s, int linenum);
189
static int parse_protocols(const char *s);
190
static int parse_variable(const char *filename, int linenum,
191
const char *line, const char *value,
192
size_t num_vars,
193
const cupsd_var_t *vars);
194
static int read_cupsd_conf(cups_file_t *fp);
195
static int read_cups_files_conf(cups_file_t *fp);
196
static int read_location(cups_file_t *fp, char *name, int linenum);
197
static int read_policy(cups_file_t *fp, char *name, int linenum);
198
static void set_policy_defaults(cupsd_policy_t *pol);
199
200
201
/*
202
* 'cupsdAddAlias()' - Add a host alias.
203
*/
204
205
void
206
cupsdAddAlias(cups_array_t *aliases, /* I - Array of aliases */
207
const char *name) /* I - Name to add */
208
{
209
cupsd_alias_t *a; /* New alias */
210
size_t namelen; /* Length of name */
211
212
213
namelen = strlen(name);
214
215
if ((a = (cupsd_alias_t *)malloc(sizeof(cupsd_alias_t) + namelen)) == NULL)
216
return;
217
218
a->namelen = namelen;
219
memcpy(a->name, name, namelen + 1); /* OK since a->name is allocated */
220
221
cupsArrayAdd(aliases, a);
222
}
223
224
225
/*
226
* 'cupsdCheckPermissions()' - Fix the mode and ownership of a file or directory.
227
*/
228
229
int /* O - 0 on success, -1 on error, 1 on warning */
230
cupsdCheckPermissions(
231
const char *filename, /* I - File/directory name */
232
const char *suffix, /* I - Additional file/directory name */
233
mode_t mode, /* I - Permissions */
234
uid_t user, /* I - Owner */
235
gid_t group, /* I - Group */
236
int is_dir, /* I - 1 = directory, 0 = file */
237
int create_dir) /* I - 1 = create directory, -1 = create w/o logging, 0 = not */
238
{
239
int dir_created = 0; /* Did we create a directory? */
240
char pathname[1024]; /* File name with prefix */
241
struct stat fileinfo; /* Stat buffer */
242
int is_symlink; /* Is "filename" a symlink? */
243
244
245
/*
246
* Prepend the given root to the filename before testing it...
247
*/
248
249
if (suffix)
250
{
251
snprintf(pathname, sizeof(pathname), "%s/%s", filename, suffix);
252
filename = pathname;
253
}
254
255
/*
256
* See if we can stat the file/directory...
257
*/
258
259
if (lstat(filename, &fileinfo))
260
{
261
if (errno == ENOENT && create_dir)
262
{
263
if (create_dir > 0)
264
cupsdLogMessage(CUPSD_LOG_DEBUG, "Creating missing directory \"%s\"",
265
filename);
266
267
if (mkdir(filename, mode))
268
{
269
if (create_dir > 0)
270
cupsdLogMessage(CUPSD_LOG_ERROR,
271
"Unable to create directory \"%s\" - %s", filename,
272
strerror(errno));
273
else
274
#ifdef HAVE_SYSTEMD_SD_JOURNAL_H
275
sd_journal_print(LOG_ERR, "Unable to create directory \"%s\" - %s", filename, strerror(errno));
276
#else
277
syslog(LOG_ERR, "Unable to create directory \"%s\" - %s", filename, strerror(errno));
278
#endif /* HAVE_SYSTEMD_SD_JOURNAL_H */
279
280
return (-1);
281
}
282
283
dir_created = 1;
284
fileinfo.st_mode = mode | S_IFDIR;
285
}
286
else
287
return (create_dir ? -1 : 1);
288
}
289
290
if ((is_symlink = S_ISLNK(fileinfo.st_mode)) != 0)
291
{
292
if (stat(filename, &fileinfo))
293
{
294
cupsdLogMessage(CUPSD_LOG_ERROR, "\"%s\" is a bad symlink - %s",
295
filename, strerror(errno));
296
return (-1);
297
}
298
}
299
300
/*
301
* Make sure it's a regular file or a directory as needed...
302
*/
303
304
if (!dir_created && !is_dir && !S_ISREG(fileinfo.st_mode))
305
{
306
cupsdLogMessage(CUPSD_LOG_ERROR, "\"%s\" is not a regular file.", filename);
307
return (-1);
308
}
309
310
if (!dir_created && is_dir && !S_ISDIR(fileinfo.st_mode))
311
{
312
if (create_dir >= 0)
313
cupsdLogMessage(CUPSD_LOG_ERROR, "\"%s\" is not a directory.", filename);
314
else
315
#ifdef HAVE_SYSTEMD_SD_JOURNAL_H
316
sd_journal_print(LOG_ERR, "\"%s\" is not a directory.", filename);
317
#else
318
syslog(LOG_ERR, "\"%s\" is not a directory.", filename);
319
#endif /* HAVE_SYSTEMD_SD_JOURNAL_H */
320
321
return (-1);
322
}
323
324
/*
325
* If the filename is a symlink, do not change permissions (STR #2937)...
326
*/
327
328
if (is_symlink)
329
return (0);
330
331
/*
332
* Fix owner, group, and mode as needed...
333
*/
334
335
if (dir_created || fileinfo.st_uid != user || fileinfo.st_gid != group)
336
{
337
if (create_dir >= 0)
338
cupsdLogMessage(CUPSD_LOG_DEBUG, "Repairing ownership of \"%s\"",
339
filename);
340
341
if (chown(filename, user, group) && !getuid())
342
{
343
if (create_dir >= 0)
344
cupsdLogMessage(CUPSD_LOG_ERROR,
345
"Unable to change ownership of \"%s\" - %s", filename,
346
strerror(errno));
347
else
348
#ifdef HAVE_SYSTEMD_SD_JOURNAL_H
349
sd_journal_print(LOG_ERR, "Unable to change ownership of \"%s\" - %s", filename, strerror(errno));
350
#else
351
syslog(LOG_ERR, "Unable to change ownership of \"%s\" - %s", filename, strerror(errno));
352
#endif /* HAVE_SYSTEMD_SD_JOURNAL_H */
353
354
return (1);
355
}
356
}
357
358
if (dir_created || (fileinfo.st_mode & 07777) != mode)
359
{
360
if (create_dir >= 0)
361
cupsdLogMessage(CUPSD_LOG_DEBUG, "Repairing access permissions of \"%s\"",
362
filename);
363
364
if (chmod(filename, mode))
365
{
366
if (create_dir >= 0)
367
cupsdLogMessage(CUPSD_LOG_ERROR,
368
"Unable to change permissions of \"%s\" - %s", filename,
369
strerror(errno));
370
else
371
#ifdef HAVE_SYSTEMD_SD_JOURNAL_H
372
sd_journal_print(LOG_ERR, "Unable to change permissions of \"%s\" - %s", filename, strerror(errno));
373
#else
374
syslog(LOG_ERR, "Unable to change permissions of \"%s\" - %s", filename, strerror(errno));
375
#endif /* HAVE_SYSTEMD_SD_JOURNAL_H */
376
377
return (1);
378
}
379
}
380
381
/*
382
* Everything is OK...
383
*/
384
385
return (0);
386
}
387
388
389
/*
390
* 'cupsdDefaultAuthType()' - Get the default AuthType.
391
*
392
* When the default_auth_type is "auto", this function tries to get the GSS
393
* credentials for the server. If that succeeds we use Kerberos authentication,
394
* otherwise we do a fallback to Basic authentication against the local user
395
* accounts.
396
*/
397
398
int /* O - Default AuthType value */
399
cupsdDefaultAuthType(void)
400
{
401
#ifdef HAVE_GSSAPI
402
OM_uint32 major_status, /* Major status code */
403
minor_status; /* Minor status code */
404
gss_name_t server_name; /* Server name */
405
gss_buffer_desc token = GSS_C_EMPTY_BUFFER;
406
/* Service name token */
407
char buf[1024]; /* Service name buffer */
408
#endif /* HAVE_GSSAPI */
409
410
411
/*
412
* If we have already determined the correct default AuthType, use it...
413
*/
414
415
if (default_auth_type != CUPSD_AUTH_AUTO)
416
return (default_auth_type);
417
418
#ifdef HAVE_GSSAPI
419
# ifdef __APPLE__
420
/*
421
* If the weak-linked GSSAPI/Kerberos library is not present, don't try
422
* to use it...
423
*/
424
425
if (&gss_init_sec_context == NULL)
426
return (default_auth_type = CUPSD_AUTH_BASIC);
427
# endif /* __APPLE__ */
428
429
/*
430
* Try to obtain the server's GSS credentials (GSSServiceName@servername). If
431
* that fails we must use Basic...
432
*/
433
434
snprintf(buf, sizeof(buf), "%s@%s", GSSServiceName, ServerName);
435
436
token.value = buf;
437
token.length = strlen(buf);
438
server_name = GSS_C_NO_NAME;
439
major_status = gss_import_name(&minor_status, &token,
440
GSS_C_NT_HOSTBASED_SERVICE,
441
&server_name);
442
443
memset(&token, 0, sizeof(token));
444
445
if (GSS_ERROR(major_status))
446
{
447
cupsdLogGSSMessage(CUPSD_LOG_DEBUG, major_status, minor_status,
448
"cupsdDefaultAuthType: gss_import_name(%s) failed", buf);
449
return (default_auth_type = CUPSD_AUTH_BASIC);
450
}
451
452
major_status = gss_display_name(&minor_status, server_name, &token, NULL);
453
454
if (GSS_ERROR(major_status))
455
{
456
cupsdLogGSSMessage(CUPSD_LOG_DEBUG, major_status, minor_status,
457
"cupsdDefaultAuthType: gss_display_name(%s) failed",
458
buf);
459
return (default_auth_type = CUPSD_AUTH_BASIC);
460
}
461
462
cupsdLogMessage(CUPSD_LOG_DEBUG,
463
"cupsdDefaultAuthType: Attempting to acquire Kerberos "
464
"credentials for %s...", (char *)token.value);
465
466
ServerCreds = GSS_C_NO_CREDENTIAL;
467
major_status = gss_acquire_cred(&minor_status, server_name, GSS_C_INDEFINITE,
468
GSS_C_NO_OID_SET, GSS_C_ACCEPT,
469
&ServerCreds, NULL, NULL);
470
if (GSS_ERROR(major_status))
471
{
472
cupsdLogGSSMessage(CUPSD_LOG_DEBUG, major_status, minor_status,
473
"cupsdDefaultAuthType: gss_acquire_cred(%s) failed",
474
(char *)token.value);
475
gss_release_name(&minor_status, &server_name);
476
gss_release_buffer(&minor_status, &token);
477
return (default_auth_type = CUPSD_AUTH_BASIC);
478
}
479
480
cupsdLogMessage(CUPSD_LOG_DEBUG,
481
"cupsdDefaultAuthType: Kerberos credentials acquired "
482
"successfully for %s.", (char *)token.value);
483
484
gss_release_name(&minor_status, &server_name);
485
gss_release_buffer(&minor_status, &token);
486
487
HaveServerCreds = 1;
488
489
return (default_auth_type = CUPSD_AUTH_NEGOTIATE);
490
491
#else
492
/*
493
* No Kerberos support compiled in so just use Basic all the time...
494
*/
495
496
return (default_auth_type = CUPSD_AUTH_BASIC);
497
#endif /* HAVE_GSSAPI */
498
}
499
500
501
/*
502
* 'cupsdFreeAliases()' - Free all of the alias entries.
503
*/
504
505
void
506
cupsdFreeAliases(cups_array_t *aliases) /* I - Array of aliases */
507
{
508
cupsd_alias_t *a; /* Current alias */
509
510
511
for (a = (cupsd_alias_t *)cupsArrayFirst(aliases);
512
a;
513
a = (cupsd_alias_t *)cupsArrayNext(aliases))
514
free(a);
515
516
cupsArrayDelete(aliases);
517
}
518
519
520
/*
521
* 'cupsdReadConfiguration()' - Read the cupsd.conf file.
522
*/
523
524
int /* O - 1 on success, 0 otherwise */
525
cupsdReadConfiguration(void)
526
{
527
int i; /* Looping var */
528
cups_file_t *fp; /* Configuration file */
529
int status; /* Return status */
530
char temp[1024], /* Temporary buffer */
531
mimedir[1024], /* MIME directory */
532
*slash; /* Directory separator */
533
cups_lang_t *language; /* Language */
534
struct passwd *user; /* Default user */
535
struct group *group; /* Default group */
536
char *old_serverroot, /* Old ServerRoot */
537
*old_requestroot; /* Old RequestRoot */
538
int old_remote_port; /* Old RemotePort */
539
const char *tmpdir; /* TMPDIR environment variable */
540
struct stat tmpinfo; /* Temporary directory info */
541
cupsd_policy_t *p; /* Policy */
542
543
544
/*
545
* Save the old root paths...
546
*/
547
548
old_serverroot = NULL;
549
cupsdSetString(&old_serverroot, ServerRoot);
550
old_requestroot = NULL;
551
cupsdSetString(&old_requestroot, RequestRoot);
552
553
/*
554
* Reset the server configuration data...
555
*/
556
557
cupsdDeleteAllLocations();
558
559
cupsdDeleteAllListeners();
560
561
old_remote_port = RemotePort;
562
RemotePort = 0;
563
564
/*
565
* String options...
566
*/
567
568
cupsdFreeAliases(ServerAlias);
569
ServerAlias = NULL;
570
571
cupsdClearString(&ServerName);
572
cupsdClearString(&ServerAdmin);
573
cupsdSetString(&ServerBin, CUPS_SERVERBIN);
574
cupsdSetString(&RequestRoot, CUPS_REQUESTS);
575
cupsdSetString(&CacheDir, CUPS_CACHEDIR);
576
cupsdSetString(&DataDir, CUPS_DATADIR);
577
cupsdSetString(&DocumentRoot, CUPS_DOCROOT);
578
cupsdSetString(&AccessLog, CUPS_LOGDIR "/access_log");
579
cupsdClearString(&ErrorLog);
580
cupsdSetString(&PageLog, CUPS_LOGDIR "/page_log");
581
cupsdSetString(&PageLogFormat,
582
"%p %u %j %T %P %C %{job-billing} "
583
"%{job-originating-host-name} %{job-name} %{media} %{sides}");
584
cupsdSetString(&Printcap, CUPS_DEFAULT_PRINTCAP);
585
cupsdSetString(&RemoteRoot, "remroot");
586
cupsdSetStringf(&ServerHeader, "CUPS/%d.%d IPP/2.1", CUPS_VERSION_MAJOR,
587
CUPS_VERSION_MINOR);
588
cupsdSetString(&StateDir, CUPS_STATEDIR);
589
590
if (!strcmp(CUPS_DEFAULT_PRINTCAP, "/etc/printers.conf"))
591
PrintcapFormat = PRINTCAP_SOLARIS;
592
else if (!strcmp(CUPS_DEFAULT_PRINTCAP,
593
"/Library/Preferences/org.cups.printers.plist"))
594
PrintcapFormat = PRINTCAP_PLIST;
595
else
596
PrintcapFormat = PRINTCAP_BSD;
597
598
strlcpy(temp, ConfigurationFile, sizeof(temp));
599
if ((slash = strrchr(temp, '/')) != NULL)
600
*slash = '\0';
601
602
cupsdSetString(&ServerRoot, temp);
603
604
cupsdClearString(&Classification);
605
ClassifyOverride = 0;
606
607
#ifdef HAVE_TLS
608
# ifdef HAVE_GNUTLS
609
cupsdSetString(&ServerKeychain, "ssl");
610
# else
611
cupsdSetString(&ServerKeychain, "/Library/Keychains/System.keychain");
612
# endif /* HAVE_GNUTLS */
613
614
_httpTLSSetOptions(_HTTP_TLS_NONE, _HTTP_TLS_1_0, _HTTP_TLS_MAX);
615
#endif /* HAVE_TLS */
616
617
language = cupsLangDefault();
618
619
if (!strcmp(language->language, "C") || !strcmp(language->language, "POSIX"))
620
cupsdSetString(&DefaultLanguage, "en");
621
else
622
cupsdSetString(&DefaultLanguage, language->language);
623
624
cupsdClearString(&DefaultPaperSize);
625
cupsArrayDelete(ReadyPaperSizes);
626
ReadyPaperSizes = NULL;
627
628
cupsdSetString(&TempDir, NULL);
629
630
#ifdef HAVE_GSSAPI
631
cupsdSetString(&GSSServiceName, CUPS_DEFAULT_GSSSERVICENAME);
632
633
if (HaveServerCreds)
634
{
635
OM_uint32 minor_status; /* Minor status code */
636
637
gss_release_cred(&minor_status, &ServerCreds);
638
639
HaveServerCreds = 0;
640
}
641
642
ServerCreds = GSS_C_NO_CREDENTIAL;
643
#endif /* HAVE_GSSAPI */
644
645
/*
646
* Find the default user...
647
*/
648
649
if ((user = getpwnam(CUPS_DEFAULT_USER)) != NULL)
650
User = user->pw_uid;
651
else
652
{
653
/*
654
* Use the (historical) NFS nobody user ID (-2 as a 16-bit twos-
655
* complement number...)
656
*/
657
658
User = 65534;
659
}
660
661
endpwent();
662
663
/*
664
* Find the default group...
665
*/
666
667
group = getgrnam(CUPS_DEFAULT_GROUP);
668
endgrent();
669
670
if (group)
671
Group = group->gr_gid;
672
else
673
{
674
/*
675
* Fallback to group "nobody"...
676
*/
677
678
group = getgrnam("nobody");
679
endgrent();
680
681
if (group)
682
Group = group->gr_gid;
683
else
684
{
685
/*
686
* Use the (historical) NFS nobody group ID (-2 as a 16-bit twos-
687
* complement number...)
688
*/
689
690
Group = 65534;
691
}
692
}
693
694
/*
695
* Numeric options...
696
*/
697
698
AccessLogLevel = CUPSD_ACCESSLOG_ACTIONS;
699
ConfigFilePerm = CUPS_DEFAULT_CONFIG_FILE_PERM;
700
FatalErrors = parse_fatal_errors(CUPS_DEFAULT_FATAL_ERRORS);
701
default_auth_type = CUPSD_AUTH_BASIC;
702
#ifdef HAVE_TLS
703
CreateSelfSignedCerts = TRUE;
704
DefaultEncryption = HTTP_ENCRYPT_REQUIRED;
705
#endif /* HAVE_TLS */
706
DirtyCleanInterval = DEFAULT_KEEPALIVE;
707
JobKillDelay = DEFAULT_TIMEOUT;
708
JobRetryLimit = 5;
709
JobRetryInterval = 300;
710
FileDevice = FALSE;
711
FilterLevel = 0;
712
FilterLimit = 0;
713
FilterNice = 0;
714
HostNameLookups = FALSE;
715
KeepAlive = TRUE;
716
LogDebugHistory = 200;
717
LogFilePerm = CUPS_DEFAULT_LOG_FILE_PERM;
718
LogFileGroup = Group;
719
LogLevel = CUPSD_LOG_WARN;
720
LogTimeFormat = CUPSD_TIME_STANDARD;
721
MaxClients = 100;
722
MaxClientsPerHost = 0;
723
MaxLogSize = 1024 * 1024;
724
MaxRequestSize = 0;
725
MultipleOperationTimeout = 900;
726
NumSystemGroups = 0;
727
ReloadTimeout = DEFAULT_KEEPALIVE;
728
RootCertDuration = 300;
729
Sandboxing = CUPSD_SANDBOXING_STRICT;
730
StrictConformance = FALSE;
731
#ifdef CUPS_DEFAULT_SYNC_ON_CLOSE
732
SyncOnClose = TRUE;
733
#else
734
SyncOnClose = FALSE;
735
#endif /* CUPS_DEFAULT_SYNC_ON_CLOSE */
736
Timeout = 900;
737
WebInterface = CUPS_DEFAULT_WEBIF;
738
739
BrowseLocalProtocols = parse_protocols(CUPS_DEFAULT_BROWSE_LOCAL_PROTOCOLS);
740
BrowseWebIF = FALSE;
741
Browsing = CUPS_DEFAULT_BROWSING;
742
DefaultShared = CUPS_DEFAULT_DEFAULT_SHARED;
743
744
#ifdef HAVE_DNSSD
745
cupsdSetString(&DNSSDSubTypes, "_cups,_print,_universal");
746
cupsdClearString(&DNSSDHostName);
747
#endif /* HAVE_DNSSD */
748
749
cupsdSetString(&ErrorPolicy, CUPS_DEFAULT_ERROR_POLICY);
750
751
JobHistory = DEFAULT_HISTORY;
752
JobFiles = DEFAULT_FILES;
753
JobAutoPurge = 0;
754
MaxHoldTime = 0;
755
MaxJobs = 500;
756
MaxActiveJobs = 0;
757
MaxJobsPerUser = 0;
758
MaxJobsPerPrinter = 0;
759
MaxJobTime = 3 * 60 * 60; /* 3 hours */
760
MaxCopies = CUPS_DEFAULT_MAX_COPIES;
761
762
cupsdDeleteAllPolicies();
763
cupsdClearString(&DefaultPolicy);
764
765
#ifdef HAVE_AUTHORIZATION_H
766
cupsdSetString(&SystemGroupAuthKey, CUPS_DEFAULT_SYSTEM_AUTHKEY);
767
#endif /* HAVE_AUTHORIZATION_H */
768
769
MaxSubscriptions = 100;
770
MaxSubscriptionsPerJob = 0;
771
MaxSubscriptionsPerPrinter = 0;
772
MaxSubscriptionsPerUser = 0;
773
DefaultLeaseDuration = 86400;
774
MaxLeaseDuration = 0;
775
776
#ifdef HAVE_ONDEMAND
777
IdleExitTimeout = 60;
778
#endif /* HAVE_ONDEMAND */
779
780
/*
781
* Setup environment variables...
782
*/
783
784
cupsdInitEnv();
785
786
/*
787
* Read the cups-files.conf file...
788
*/
789
790
if ((fp = cupsFileOpen(CupsFilesFile, "r")) != NULL)
791
{
792
status = read_cups_files_conf(fp);
793
794
cupsFileClose(fp);
795
796
if (!status)
797
{
798
if (TestConfigFile)
799
printf("\"%s\" contains errors.\n", CupsFilesFile);
800
else
801
#ifdef HAVE_SYSTEMD_SD_JOURNAL_H
802
sd_journal_print(LOG_ERR, "Unable to read \"%s\" due to errors.", CupsFilesFile);
803
#else
804
syslog(LOG_LPR, "Unable to read \"%s\" due to errors.", CupsFilesFile);
805
#endif /* HAVE_SYSTEMD_SD_JOURNAL_H */
806
807
return (0);
808
}
809
}
810
else if (errno == ENOENT)
811
cupsdLogMessage(CUPSD_LOG_INFO, "No %s, using defaults.", CupsFilesFile);
812
else
813
{
814
#ifdef HAVE_SYSTEMD_SD_JOURNAL_H
815
sd_journal_print(LOG_ERR, "Unable to open \"%s\" - %s", CupsFilesFile, strerror(errno));
816
#else
817
syslog(LOG_LPR, "Unable to open \"%s\" - %s", CupsFilesFile, strerror(errno));
818
#endif /* HAVE_SYSTEMD_SD_JOURNAL_H */
819
820
return (0);
821
}
822
823
if (!ErrorLog)
824
cupsdSetString(&ErrorLog, CUPS_LOGDIR "/error_log");
825
826
/*
827
* Read the cupsd.conf file...
828
*/
829
830
if ((fp = cupsFileOpen(ConfigurationFile, "r")) == NULL)
831
{
832
#ifdef HAVE_SYSTEMD_SD_JOURNAL_H
833
sd_journal_print(LOG_ERR, "Unable to open \"%s\" - %s", ConfigurationFile, strerror(errno));
834
#else
835
syslog(LOG_LPR, "Unable to open \"%s\" - %s", ConfigurationFile, strerror(errno));
836
#endif /* HAVE_SYSTEMD_SD_JOURNAL_H */
837
838
return (0);
839
}
840
841
status = read_cupsd_conf(fp);
842
843
cupsFileClose(fp);
844
845
if (!status)
846
{
847
if (TestConfigFile)
848
printf("\"%s\" contains errors.\n", ConfigurationFile);
849
else
850
#ifdef HAVE_SYSTEMD_SD_JOURNAL_H
851
sd_journal_print(LOG_ERR, "Unable to read \"%s\" due to errors.", ConfigurationFile);
852
#else
853
syslog(LOG_LPR, "Unable to read \"%s\" due to errors.", ConfigurationFile);
854
#endif /* HAVE_SYSTEMD_SD_JOURNAL_H */
855
856
return (0);
857
}
858
859
RunUser = getuid();
860
861
cupsdLogMessage(CUPSD_LOG_INFO, "Remote access is %s.",
862
RemotePort ? "enabled" : "disabled");
863
864
if (!RemotePort)
865
BrowseLocalProtocols = 0; /* Disable sharing - no remote access */
866
867
/*
868
* See if the ServerName is an IP address...
869
*/
870
871
if (ServerName)
872
{
873
if (!ServerAlias)
874
ServerAlias = cupsArrayNew(NULL, NULL);
875
876
cupsdAddAlias(ServerAlias, ServerName);
877
cupsdLogMessage(CUPSD_LOG_DEBUG, "Added auto ServerAlias %s", ServerName);
878
}
879
else
880
{
881
if (gethostname(temp, sizeof(temp)))
882
{
883
cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to get hostname: %s",
884
strerror(errno));
885
strlcpy(temp, "localhost", sizeof(temp));
886
}
887
888
cupsdSetString(&ServerName, temp);
889
890
if (!ServerAlias)
891
ServerAlias = cupsArrayNew(NULL, NULL);
892
893
cupsdAddAlias(ServerAlias, temp);
894
cupsdLogMessage(CUPSD_LOG_DEBUG, "Added auto ServerAlias %s", temp);
895
896
if (HostNameLookups)
897
{
898
struct hostent *host; /* Host entry to get FQDN */
899
900
if ((host = gethostbyname(temp)) != NULL)
901
{
902
if (_cups_strcasecmp(temp, host->h_name))
903
{
904
cupsdSetString(&ServerName, host->h_name);
905
cupsdAddAlias(ServerAlias, host->h_name);
906
cupsdLogMessage(CUPSD_LOG_DEBUG, "Added auto ServerAlias %s",
907
host->h_name);
908
}
909
910
if (host->h_aliases)
911
{
912
for (i = 0; host->h_aliases[i]; i ++)
913
if (_cups_strcasecmp(temp, host->h_aliases[i]))
914
{
915
cupsdAddAlias(ServerAlias, host->h_aliases[i]);
916
cupsdLogMessage(CUPSD_LOG_DEBUG, "Added auto ServerAlias %s",
917
host->h_aliases[i]);
918
}
919
}
920
}
921
}
922
923
/*
924
* Make sure we have the base hostname added as an alias, too!
925
*/
926
927
if ((slash = strchr(temp, '.')) != NULL)
928
{
929
*slash = '\0';
930
cupsdAddAlias(ServerAlias, temp);
931
cupsdLogMessage(CUPSD_LOG_DEBUG, "Added auto ServerAlias %s", temp);
932
}
933
}
934
935
for (slash = ServerName; isdigit(*slash & 255) || *slash == '.'; slash ++);
936
937
ServerNameIsIP = !*slash;
938
939
/*
940
* Make sure ServerAdmin is initialized...
941
*/
942
943
if (!ServerAdmin)
944
cupsdSetStringf(&ServerAdmin, "root@%s", ServerName);
945
946
/*
947
* Use the default system group if none was supplied in cupsd.conf...
948
*/
949
950
if (NumSystemGroups == 0)
951
{
952
if (!parse_groups(CUPS_DEFAULT_SYSTEM_GROUPS, 0))
953
{
954
/*
955
* Find the group associated with GID 0...
956
*/
957
958
group = getgrgid(0);
959
endgrent();
960
961
if (group != NULL)
962
cupsdSetString(&SystemGroups[0], group->gr_name);
963
else
964
cupsdSetString(&SystemGroups[0], "unknown");
965
966
SystemGroupIDs[0] = 0;
967
NumSystemGroups = 1;
968
}
969
}
970
971
/*
972
* Make sure ConfigFilePerm and LogFilePerm have sane values...
973
*/
974
975
ConfigFilePerm &= 0664;
976
LogFilePerm &= 0664;
977
978
/*
979
* Open the system log for cupsd if necessary...
980
*/
981
982
if (!LogStderr)
983
{
984
if (!strcmp(AccessLog, "stderr"))
985
cupsdSetString(&AccessLog, "syslog");
986
987
if (!strcmp(ErrorLog, "stderr"))
988
cupsdSetString(&ErrorLog, "syslog");
989
990
if (!strcmp(PageLog, "stderr"))
991
cupsdSetString(&PageLog, "syslog");
992
}
993
994
#if defined(HAVE_VSYSLOG) && !defined(HAVE_ASL_H) && !defined(HAVE_SYSTEMD_SD_JOURNAL_H)
995
if (!strcmp(AccessLog, "syslog") ||
996
!strcmp(ErrorLog, "syslog") ||
997
!strcmp(PageLog, "syslog"))
998
openlog("cupsd", LOG_PID | LOG_NOWAIT | LOG_NDELAY, LOG_LPR);
999
#endif /* HAVE_VSYSLOG && !HAVE_ASL_H && !HAVE_SYSTEMD_SD_JOURNAL_H */
1000
1001
/*
1002
* Log the configuration file that was used...
1003
*/
1004
1005
cupsdLogMessage(CUPSD_LOG_INFO, "Loaded configuration file \"%s\"",
1006
ConfigurationFile);
1007
1008
/*
1009
* Validate the Group and SystemGroup settings - they cannot be the same,
1010
* otherwise the CGI programs will be able to authenticate as root without
1011
* a password!
1012
*/
1013
1014
if (!RunUser)
1015
{
1016
for (i = 0; i < NumSystemGroups; i ++)
1017
if (Group == SystemGroupIDs[i])
1018
break;
1019
1020
if (i < NumSystemGroups)
1021
{
1022
/*
1023
* Log the error and reset the group to a safe value...
1024
*/
1025
1026
cupsdLogMessage(CUPSD_LOG_ERROR,
1027
"Group and SystemGroup cannot use the same groups.");
1028
if (FatalErrors & (CUPSD_FATAL_CONFIG | CUPSD_FATAL_PERMISSIONS))
1029
return (0);
1030
1031
cupsdLogMessage(CUPSD_LOG_INFO, "Resetting Group to \"nobody\"...");
1032
1033
group = getgrnam("nobody");
1034
endgrent();
1035
1036
if (group != NULL)
1037
Group = group->gr_gid;
1038
else
1039
{
1040
/*
1041
* Use the (historical) NFS nobody group ID (-2 as a 16-bit twos-
1042
* complement number...)
1043
*/
1044
1045
Group = 65534;
1046
}
1047
}
1048
}
1049
1050
/*
1051
* Check that we have at least one listen/port line; if not, report this
1052
* as an error and exit!
1053
*/
1054
1055
if (cupsArrayCount(Listeners) == 0)
1056
{
1057
/*
1058
* No listeners!
1059
*/
1060
1061
cupsdLogMessage(CUPSD_LOG_EMERG,
1062
"No valid Listen or Port lines were found in the "
1063
"configuration file.");
1064
1065
/*
1066
* Commit suicide...
1067
*/
1068
1069
cupsdEndProcess(getpid(), 0);
1070
}
1071
1072
/*
1073
* Set the default locale using the language and charset...
1074
*/
1075
1076
cupsdSetStringf(&DefaultLocale, "%s.UTF-8", DefaultLanguage);
1077
1078
/*
1079
* Update all relative filenames to include the full path from ServerRoot...
1080
*/
1081
1082
if (DocumentRoot[0] != '/')
1083
cupsdSetStringf(&DocumentRoot, "%s/%s", ServerRoot, DocumentRoot);
1084
1085
if (RequestRoot[0] != '/')
1086
cupsdSetStringf(&RequestRoot, "%s/%s", ServerRoot, RequestRoot);
1087
1088
if (ServerBin[0] != '/')
1089
cupsdSetStringf(&ServerBin, "%s/%s", ServerRoot, ServerBin);
1090
1091
if (StateDir[0] != '/')
1092
cupsdSetStringf(&StateDir, "%s/%s", ServerRoot, StateDir);
1093
1094
if (CacheDir[0] != '/')
1095
cupsdSetStringf(&CacheDir, "%s/%s", ServerRoot, CacheDir);
1096
1097
#ifdef HAVE_TLS
1098
if (!_cups_strcasecmp(ServerKeychain, "internal"))
1099
cupsdClearString(&ServerKeychain);
1100
else if (ServerKeychain[0] != '/')
1101
cupsdSetStringf(&ServerKeychain, "%s/%s", ServerRoot, ServerKeychain);
1102
1103
cupsdLogMessage(CUPSD_LOG_DEBUG, "Using keychain \"%s\" for server name \"%s\".", ServerKeychain ? ServerKeychain : "internal", ServerName);
1104
if (!CreateSelfSignedCerts)
1105
cupsdLogMessage(CUPSD_LOG_DEBUG, "Self-signed TLS certificate generation is disabled.");
1106
cupsSetServerCredentials(ServerKeychain, ServerName, CreateSelfSignedCerts);
1107
#endif /* HAVE_TLS */
1108
1109
/*
1110
* Make sure that directories and config files are owned and
1111
* writable by the user and group in the cupsd.conf file...
1112
*/
1113
1114
snprintf(temp, sizeof(temp), "%s/rss", CacheDir);
1115
1116
if ((cupsdCheckPermissions(RequestRoot, NULL, 0710, RunUser,
1117
Group, 1, 1) < 0 ||
1118
cupsdCheckPermissions(CacheDir, NULL, 0770, RunUser,
1119
Group, 1, 1) < 0 ||
1120
cupsdCheckPermissions(temp, NULL, 0775, RunUser,
1121
Group, 1, 1) < 0 ||
1122
cupsdCheckPermissions(StateDir, NULL, 0755, RunUser,
1123
Group, 1, 1) < 0 ||
1124
#if CUPS_SNAP
1125
cupsdCheckPermissions(StateDir, "certs", 0711, RunUser, 0, 1, 1) < 0 ||
1126
#else
1127
cupsdCheckPermissions(StateDir, "certs", RunUser ? 0711 : 0511, User, SystemGroupIDs[0], 1, 1) < 0 ||
1128
#endif /* CUPS_SNAP */
1129
cupsdCheckPermissions(ServerRoot, NULL, 0755, RunUser,
1130
Group, 1, 0) < 0 ||
1131
cupsdCheckPermissions(ServerRoot, "ppd", 0755, RunUser,
1132
Group, 1, 1) < 0 ||
1133
cupsdCheckPermissions(ServerRoot, "ssl", 0700, RunUser,
1134
Group, 1, 0) < 0 ||
1135
cupsdCheckPermissions(ConfigurationFile, NULL, ConfigFilePerm, RunUser,
1136
Group, 0, 0) < 0 ||
1137
cupsdCheckPermissions(CupsFilesFile, NULL, ConfigFilePerm, RunUser,
1138
Group, 0, 0) < 0 ||
1139
cupsdCheckPermissions(ServerRoot, "classes.conf", 0600, RunUser,
1140
Group, 0, 0) < 0 ||
1141
cupsdCheckPermissions(ServerRoot, "printers.conf", 0600, RunUser,
1142
Group, 0, 0) < 0 ||
1143
cupsdCheckPermissions(ServerRoot, "passwd.md5", 0600, User,
1144
Group, 0, 0) < 0) &&
1145
(FatalErrors & CUPSD_FATAL_PERMISSIONS))
1146
return (0);
1147
1148
/*
1149
* Update TempDir to the default if it hasn't been set already...
1150
*/
1151
1152
#ifdef __APPLE__
1153
if (TempDir && !RunUser &&
1154
(!strncmp(TempDir, "/private/tmp", 12) || !strncmp(TempDir, "/tmp", 4)))
1155
{
1156
cupsdLogMessage(CUPSD_LOG_ERROR, "Cannot use %s for TempDir.", TempDir);
1157
cupsdClearString(&TempDir);
1158
}
1159
#endif /* __APPLE__ */
1160
1161
if (!TempDir)
1162
{
1163
#ifdef __APPLE__
1164
if ((tmpdir = getenv("TMPDIR")) != NULL &&
1165
strncmp(tmpdir, "/private/tmp", 12) && strncmp(tmpdir, "/tmp", 4))
1166
#else
1167
if ((tmpdir = getenv("TMPDIR")) != NULL)
1168
#endif /* __APPLE__ */
1169
{
1170
/*
1171
* TMPDIR is defined, see if it is OK for us to use...
1172
*/
1173
1174
if (stat(tmpdir, &tmpinfo))
1175
cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to access TMPDIR (%s): %s",
1176
tmpdir, strerror(errno));
1177
else if (!S_ISDIR(tmpinfo.st_mode))
1178
cupsdLogMessage(CUPSD_LOG_ERROR, "TMPDIR (%s) is not a directory.",
1179
tmpdir);
1180
else if ((tmpinfo.st_uid != User || !(tmpinfo.st_mode & S_IWUSR)) &&
1181
(tmpinfo.st_gid != Group || !(tmpinfo.st_mode & S_IWGRP)) &&
1182
!(tmpinfo.st_mode & S_IWOTH))
1183
cupsdLogMessage(CUPSD_LOG_ERROR,
1184
"TMPDIR (%s) has the wrong permissions.", tmpdir);
1185
else
1186
cupsdSetString(&TempDir, tmpdir);
1187
}
1188
}
1189
1190
if (!TempDir)
1191
{
1192
cupsdLogMessage(CUPSD_LOG_INFO, "Using default TempDir of %s/tmp...",
1193
RequestRoot);
1194
cupsdSetStringf(&TempDir, "%s/tmp", RequestRoot);
1195
}
1196
1197
setenv("TMPDIR", TempDir, 1);
1198
1199
/*
1200
* Make sure the temporary directory has the right permissions...
1201
*/
1202
1203
if (!strncmp(TempDir, RequestRoot, strlen(RequestRoot)) ||
1204
access(TempDir, 0))
1205
{
1206
/*
1207
* Update ownership and permissions if the CUPS temp directory
1208
* is under the spool directory or does not exist...
1209
*/
1210
1211
if (cupsdCheckPermissions(TempDir, NULL, 01770, RunUser, Group, 1, 1) < 0 &&
1212
(FatalErrors & CUPSD_FATAL_PERMISSIONS))
1213
return (0);
1214
}
1215
1216
/*
1217
* Update environment variables...
1218
*/
1219
1220
cupsdUpdateEnv();
1221
1222
/*
1223
* Validate the default error policy...
1224
*/
1225
1226
if (strcmp(ErrorPolicy, "retry-current-job") &&
1227
strcmp(ErrorPolicy, "abort-job") &&
1228
strcmp(ErrorPolicy, "retry-job") &&
1229
strcmp(ErrorPolicy, "stop-printer"))
1230
{
1231
cupsdLogMessage(CUPSD_LOG_ALERT, "Invalid ErrorPolicy \"%s\", resetting to \"stop-printer\".", ErrorPolicy);
1232
cupsdSetString(&ErrorPolicy, "stop-printer");
1233
}
1234
1235
/*
1236
* Update default paper size setting as needed...
1237
*/
1238
1239
if (!DefaultPaperSize)
1240
{
1241
#ifdef HAVE_LIBPAPER
1242
char *paper_result; /* Paper size name from libpaper */
1243
1244
if ((paper_result = systempapername()) != NULL)
1245
{
1246
cupsdSetString(&DefaultPaperSize, paper_result);
1247
free(paper_result);
1248
}
1249
else
1250
#endif /* HAVE_LIBPAPER */
1251
if (!DefaultLanguage ||
1252
!_cups_strcasecmp(DefaultLanguage, "C") ||
1253
!_cups_strcasecmp(DefaultLanguage, "POSIX") ||
1254
!_cups_strcasecmp(DefaultLanguage, "en") ||
1255
!_cups_strncasecmp(DefaultLanguage, "en.", 3) ||
1256
!_cups_strncasecmp(DefaultLanguage, "en_US", 5) ||
1257
!_cups_strncasecmp(DefaultLanguage, "en_CA", 5) ||
1258
!_cups_strncasecmp(DefaultLanguage, "fr_CA", 5))
1259
{
1260
/*
1261
* These are the only locales that will default to "letter" size...
1262
*/
1263
1264
cupsdSetString(&DefaultPaperSize, "Letter");
1265
}
1266
else
1267
cupsdSetString(&DefaultPaperSize, "A4");
1268
}
1269
1270
if (!ReadyPaperSizes)
1271
{
1272
// Build default list of common sizes for North America and worldwide...
1273
if (!strcasecmp(DefaultPaperSize, "Letter"))
1274
ReadyPaperSizes = _cupsArrayNewStrings("Letter,Legal,Tabloid,4x6,Env10", ',');
1275
else if (!strcasecmp(DefaultPaperSize, "A4"))
1276
ReadyPaperSizes = _cupsArrayNewStrings("A4,A3,A5,A6,EnvDL", ',');
1277
else
1278
ReadyPaperSizes = _cupsArrayNewStrings(DefaultPaperSize, ',');
1279
}
1280
1281
/*
1282
* Update classification setting as needed...
1283
*/
1284
1285
if (Classification && !_cups_strcasecmp(Classification, "none"))
1286
cupsdClearString(&Classification);
1287
1288
if (Classification)
1289
cupsdLogMessage(CUPSD_LOG_INFO, "Security set to \"%s\"", Classification);
1290
1291
/*
1292
* Check the MaxClients setting, and then allocate memory for it...
1293
*/
1294
1295
if (MaxClients > (MaxFDs / 3) || MaxClients <= 0)
1296
{
1297
if (MaxClients > 0)
1298
cupsdLogMessage(CUPSD_LOG_INFO,
1299
"MaxClients limited to 1/3 (%d) of the file descriptor "
1300
"limit (%d)...",
1301
MaxFDs / 3, MaxFDs);
1302
1303
MaxClients = MaxFDs / 3;
1304
}
1305
1306
cupsdLogMessage(CUPSD_LOG_INFO, "Configured for up to %d clients.",
1307
MaxClients);
1308
1309
/*
1310
* Check the MaxActiveJobs setting; limit to 1/3 the available
1311
* file descriptors, since we need a pipe for each job...
1312
*/
1313
1314
if (MaxActiveJobs > (MaxFDs / 3))
1315
MaxActiveJobs = MaxFDs / 3;
1316
1317
/*
1318
* Update the MaxClientsPerHost value, as needed...
1319
*/
1320
1321
if (MaxClientsPerHost <= 0)
1322
MaxClientsPerHost = MaxClients;
1323
1324
if (MaxClientsPerHost > MaxClients)
1325
MaxClientsPerHost = MaxClients;
1326
1327
cupsdLogMessage(CUPSD_LOG_INFO,
1328
"Allowing up to %d client connections per host.",
1329
MaxClientsPerHost);
1330
1331
/*
1332
* Update the default policy, as needed...
1333
*/
1334
1335
if (DefaultPolicy)
1336
DefaultPolicyPtr = cupsdFindPolicy(DefaultPolicy);
1337
else
1338
DefaultPolicyPtr = NULL;
1339
1340
if (!DefaultPolicyPtr)
1341
{
1342
cupsd_location_t *po; /* New policy operation */
1343
1344
1345
if (DefaultPolicy)
1346
cupsdLogMessage(CUPSD_LOG_ERROR, "Default policy \"%s\" not found.",
1347
DefaultPolicy);
1348
1349
cupsdSetString(&DefaultPolicy, "default");
1350
1351
if ((DefaultPolicyPtr = cupsdFindPolicy("default")) != NULL)
1352
cupsdLogMessage(CUPSD_LOG_INFO,
1353
"Using policy \"default\" as the default.");
1354
else
1355
{
1356
cupsdLogMessage(CUPSD_LOG_INFO,
1357
"Creating CUPS default administrative policy:");
1358
1359
DefaultPolicyPtr = p = cupsdAddPolicy("default");
1360
1361
cupsdLogMessage(CUPSD_LOG_INFO, "<Policy default>");
1362
cupsdLogMessage(CUPSD_LOG_INFO, "JobPrivateAccess default");
1363
cupsdAddString(&(p->job_access), "@OWNER");
1364
cupsdAddString(&(p->job_access), "@SYSTEM");
1365
1366
cupsdLogMessage(CUPSD_LOG_INFO, "JobPrivateValues default");
1367
cupsdAddString(&(p->job_attrs), "job-name");
1368
cupsdAddString(&(p->job_attrs), "job-originating-host-name");
1369
cupsdAddString(&(p->job_attrs), "job-originating-user-name");
1370
cupsdAddString(&(p->job_attrs), "phone");
1371
1372
cupsdLogMessage(CUPSD_LOG_INFO, "SubscriptionPrivateAccess default");
1373
cupsdAddString(&(p->sub_access), "@OWNER");
1374
cupsdAddString(&(p->sub_access), "@SYSTEM");
1375
1376
cupsdLogMessage(CUPSD_LOG_INFO, "SubscriptionPrivateValues default");
1377
cupsdAddString(&(p->job_attrs), "notify-events");
1378
cupsdAddString(&(p->job_attrs), "notify-pull-method");
1379
cupsdAddString(&(p->job_attrs), "notify-recipient-uri");
1380
cupsdAddString(&(p->job_attrs), "notify-subscriber-user-name");
1381
cupsdAddString(&(p->job_attrs), "notify-user-data");
1382
1383
cupsdLogMessage(CUPSD_LOG_INFO, "<Limit Create-Job Print-Job Print-URI Validate-Job>");
1384
po = cupsdAddPolicyOp(p, NULL, IPP_CREATE_JOB);
1385
cupsdAddPolicyOp(p, po, IPP_PRINT_JOB);
1386
cupsdAddPolicyOp(p, po, IPP_PRINT_URI);
1387
cupsdAddPolicyOp(p, po, IPP_VALIDATE_JOB);
1388
1389
cupsdLogMessage(CUPSD_LOG_INFO, "Order Deny,Allow");
1390
po->order_type = CUPSD_AUTH_ALLOW;
1391
cupsdLogMessage(CUPSD_LOG_INFO, "</Limit>");
1392
1393
cupsdLogMessage(CUPSD_LOG_INFO, "<Limit Send-Document Send-URI Hold-Job Release-Job Restart-Job Purge-Jobs Set-Job-Attributes Create-Job-Subscription Renew-Subscription Cancel-Subscription Get-Notifications Reprocess-Job Cancel-Current-Job Suspend-Current-Job Resume-Job Cancel-My-Jobs Close-Job CUPS-Move-Job>");
1394
po = cupsdAddPolicyOp(p, NULL, IPP_SEND_DOCUMENT);
1395
cupsdAddPolicyOp(p, po, IPP_SEND_URI);
1396
cupsdAddPolicyOp(p, po, IPP_HOLD_JOB);
1397
cupsdAddPolicyOp(p, po, IPP_RELEASE_JOB);
1398
cupsdAddPolicyOp(p, po, IPP_RESTART_JOB);
1399
cupsdAddPolicyOp(p, po, IPP_PURGE_JOBS);
1400
cupsdAddPolicyOp(p, po, IPP_SET_JOB_ATTRIBUTES);
1401
cupsdAddPolicyOp(p, po, IPP_CREATE_JOB_SUBSCRIPTION);
1402
cupsdAddPolicyOp(p, po, IPP_RENEW_SUBSCRIPTION);
1403
cupsdAddPolicyOp(p, po, IPP_CANCEL_SUBSCRIPTION);
1404
cupsdAddPolicyOp(p, po, IPP_GET_NOTIFICATIONS);
1405
cupsdAddPolicyOp(p, po, IPP_REPROCESS_JOB);
1406
cupsdAddPolicyOp(p, po, IPP_CANCEL_CURRENT_JOB);
1407
cupsdAddPolicyOp(p, po, IPP_SUSPEND_CURRENT_JOB);
1408
cupsdAddPolicyOp(p, po, IPP_RESUME_JOB);
1409
cupsdAddPolicyOp(p, po, IPP_CANCEL_MY_JOBS);
1410
cupsdAddPolicyOp(p, po, IPP_CLOSE_JOB);
1411
cupsdAddPolicyOp(p, po, CUPS_MOVE_JOB);
1412
1413
cupsdLogMessage(CUPSD_LOG_INFO, "Order Deny,Allow");
1414
po->order_type = CUPSD_AUTH_ALLOW;
1415
1416
cupsdLogMessage(CUPSD_LOG_INFO, "Require user @OWNER @SYSTEM");
1417
po->level = CUPSD_AUTH_USER;
1418
cupsdAddName(po, "@OWNER");
1419
cupsdAddName(po, "@SYSTEM");
1420
cupsdLogMessage(CUPSD_LOG_INFO, "</Limit>");
1421
1422
cupsdLogMessage(CUPSD_LOG_INFO, "<Limit CUPS-Authenticate-Job>");
1423
po = cupsdAddPolicyOp(p, NULL, CUPS_GET_DOCUMENT);
1424
1425
cupsdLogMessage(CUPSD_LOG_INFO, "Order Deny,Allow");
1426
po->order_type = CUPSD_AUTH_ALLOW;
1427
1428
cupsdLogMessage(CUPSD_LOG_INFO, "AuthType Default");
1429
po->type = CUPSD_AUTH_DEFAULT;
1430
1431
cupsdLogMessage(CUPSD_LOG_INFO, "Require user @OWNER @SYSTEM");
1432
po->level = CUPSD_AUTH_USER;
1433
cupsdAddName(po, "@OWNER");
1434
cupsdAddName(po, "@SYSTEM");
1435
cupsdLogMessage(CUPSD_LOG_INFO, "</Limit>");
1436
1437
cupsdLogMessage(CUPSD_LOG_INFO, "<Limit Pause-Printer Resume-Printer Set-Printer-Attributes Enable-Printer Disable-Printer Pause-Printer-After-Current-Job Hold-New-Jobs Release-Held-New-Jobs Deactivate-Printer Activate-Printer Restart-Printer Shutdown-Printer Startup-Printer Promote-Job Schedule-Job-After Cancel-Jobs CUPS-Add-Printer CUPS-Delete-Printer CUPS-Add-Class CUPS-Delete-Class CUPS-Accept-Jobs CUPS-Reject-Jobs CUPS-Set-Default>");
1438
po = cupsdAddPolicyOp(p, NULL, IPP_PAUSE_PRINTER);
1439
cupsdAddPolicyOp(p, po, IPP_RESUME_PRINTER);
1440
cupsdAddPolicyOp(p, po, IPP_SET_PRINTER_ATTRIBUTES);
1441
cupsdAddPolicyOp(p, po, IPP_ENABLE_PRINTER);
1442
cupsdAddPolicyOp(p, po, IPP_DISABLE_PRINTER);
1443
cupsdAddPolicyOp(p, po, IPP_PAUSE_PRINTER_AFTER_CURRENT_JOB);
1444
cupsdAddPolicyOp(p, po, IPP_HOLD_NEW_JOBS);
1445
cupsdAddPolicyOp(p, po, IPP_RELEASE_HELD_NEW_JOBS);
1446
cupsdAddPolicyOp(p, po, IPP_DEACTIVATE_PRINTER);
1447
cupsdAddPolicyOp(p, po, IPP_ACTIVATE_PRINTER);
1448
cupsdAddPolicyOp(p, po, IPP_RESTART_PRINTER);
1449
cupsdAddPolicyOp(p, po, IPP_SHUTDOWN_PRINTER);
1450
cupsdAddPolicyOp(p, po, IPP_STARTUP_PRINTER);
1451
cupsdAddPolicyOp(p, po, IPP_PROMOTE_JOB);
1452
cupsdAddPolicyOp(p, po, IPP_SCHEDULE_JOB_AFTER);
1453
cupsdAddPolicyOp(p, po, IPP_CANCEL_JOBS);
1454
cupsdAddPolicyOp(p, po, CUPS_ADD_PRINTER);
1455
cupsdAddPolicyOp(p, po, CUPS_DELETE_PRINTER);
1456
cupsdAddPolicyOp(p, po, CUPS_ADD_CLASS);
1457
cupsdAddPolicyOp(p, po, CUPS_DELETE_CLASS);
1458
cupsdAddPolicyOp(p, po, CUPS_ACCEPT_JOBS);
1459
cupsdAddPolicyOp(p, po, CUPS_REJECT_JOBS);
1460
cupsdAddPolicyOp(p, po, CUPS_SET_DEFAULT);
1461
1462
cupsdLogMessage(CUPSD_LOG_INFO, "Order Deny,Allow");
1463
po->order_type = CUPSD_AUTH_ALLOW;
1464
1465
cupsdLogMessage(CUPSD_LOG_INFO, "AuthType Default");
1466
po->type = CUPSD_AUTH_DEFAULT;
1467
1468
cupsdLogMessage(CUPSD_LOG_INFO, "Require user @SYSTEM");
1469
po->level = CUPSD_AUTH_USER;
1470
cupsdAddName(po, "@SYSTEM");
1471
cupsdLogMessage(CUPSD_LOG_INFO, "</Limit>");
1472
1473
cupsdLogMessage(CUPSD_LOG_INFO, "<Limit Cancel-Job>");
1474
po = cupsdAddPolicyOp(p, NULL, IPP_CANCEL_JOB);
1475
1476
cupsdLogMessage(CUPSD_LOG_INFO, "Order Deny,Allow");
1477
po->order_type = CUPSD_AUTH_ALLOW;
1478
1479
cupsdLogMessage(CUPSD_LOG_INFO, "Require user @OWNER " CUPS_DEFAULT_PRINTOPERATOR_AUTH);
1480
po->level = CUPSD_AUTH_USER;
1481
cupsdAddName(po, "@OWNER");
1482
cupsdAddName(po, CUPS_DEFAULT_PRINTOPERATOR_AUTH);
1483
cupsdLogMessage(CUPSD_LOG_INFO, "</Limit>");
1484
1485
cupsdLogMessage(CUPSD_LOG_INFO, "<Limit CUPS-Authenticate-Job>");
1486
po = cupsdAddPolicyOp(p, NULL, CUPS_AUTHENTICATE_JOB);
1487
1488
cupsdLogMessage(CUPSD_LOG_INFO, "AuthType Default");
1489
po->type = CUPSD_AUTH_DEFAULT;
1490
1491
cupsdLogMessage(CUPSD_LOG_INFO, "Order Deny,Allow");
1492
po->order_type = CUPSD_AUTH_ALLOW;
1493
1494
cupsdLogMessage(CUPSD_LOG_INFO, "Require user @OWNER " CUPS_DEFAULT_PRINTOPERATOR_AUTH);
1495
po->level = CUPSD_AUTH_USER;
1496
cupsdAddName(po, "@OWNER");
1497
cupsdAddName(po, CUPS_DEFAULT_PRINTOPERATOR_AUTH);
1498
cupsdLogMessage(CUPSD_LOG_INFO, "</Limit>");
1499
1500
cupsdLogMessage(CUPSD_LOG_INFO, "<Limit All>");
1501
po = cupsdAddPolicyOp(p, NULL, IPP_ANY_OPERATION);
1502
1503
cupsdLogMessage(CUPSD_LOG_INFO, "Order Deny,Allow");
1504
po->order_type = CUPSD_AUTH_ALLOW;
1505
cupsdLogMessage(CUPSD_LOG_INFO, "</Limit>");
1506
cupsdLogMessage(CUPSD_LOG_INFO, "</Policy>");
1507
}
1508
}
1509
1510
if (LogLevel >= CUPSD_LOG_DEBUG2)
1511
{
1512
cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdReadConfiguration: NumPolicies=%d",
1513
cupsArrayCount(Policies));
1514
for (i = 0, p = (cupsd_policy_t *)cupsArrayFirst(Policies);
1515
p;
1516
i ++, p = (cupsd_policy_t *)cupsArrayNext(Policies))
1517
{
1518
int j; /* Looping var */
1519
cupsd_location_t *loc; /* Current location */
1520
1521
cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdReadConfiguration: Policies[%d]=\"%s\"", i, p->name);
1522
1523
for (j = 0, loc = (cupsd_location_t *)cupsArrayFirst(p->ops); loc; j ++, loc = (cupsd_location_t *)cupsArrayNext(p->ops))
1524
{
1525
cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdReadConfiguration: ops[%d]=%s", j, ippOpString(loc->op));
1526
}
1527
}
1528
}
1529
1530
/*
1531
* If we are doing a full reload or the server root has changed, flush
1532
* the jobs, printers, etc. and start from scratch...
1533
*/
1534
1535
if (NeedReload == RELOAD_ALL ||
1536
old_remote_port != RemotePort ||
1537
!old_serverroot || !ServerRoot || strcmp(old_serverroot, ServerRoot) ||
1538
!old_requestroot || !RequestRoot || strcmp(old_requestroot, RequestRoot))
1539
{
1540
mime_type_t *type; /* Current type */
1541
char mimetype[MIME_MAX_SUPER + MIME_MAX_TYPE];
1542
/* MIME type name */
1543
1544
1545
cupsdLogMessage(CUPSD_LOG_INFO, "Full reload is required.");
1546
1547
/*
1548
* Free all memory...
1549
*/
1550
1551
cupsdDeleteAllSubscriptions();
1552
cupsdFreeAllJobs();
1553
cupsdDeleteAllPrinters();
1554
1555
DefaultPrinter = NULL;
1556
1557
if (MimeDatabase != NULL)
1558
mimeDelete(MimeDatabase);
1559
1560
if (NumMimeTypes)
1561
{
1562
for (i = 0; i < NumMimeTypes; i ++)
1563
_cupsStrFree(MimeTypes[i]);
1564
1565
free(MimeTypes);
1566
}
1567
1568
/*
1569
* Read the MIME type and conversion database...
1570
*/
1571
1572
snprintf(temp, sizeof(temp), "%s/filter", ServerBin);
1573
snprintf(mimedir, sizeof(mimedir), "%s/mime", DataDir);
1574
1575
MimeDatabase = mimeNew();
1576
mimeSetErrorCallback(MimeDatabase, mime_error_cb, NULL);
1577
_cupsRWInit(&MimeDatabase->lock);
1578
1579
_cupsRWLockWrite(&MimeDatabase->lock);
1580
MimeDatabase = mimeLoadTypes(MimeDatabase, mimedir);
1581
MimeDatabase = mimeLoadTypes(MimeDatabase, ServerRoot);
1582
MimeDatabase = mimeLoadFilters(MimeDatabase, mimedir, temp);
1583
MimeDatabase = mimeLoadFilters(MimeDatabase, ServerRoot, temp);
1584
_cupsRWUnlock(&MimeDatabase->lock);
1585
1586
if (!MimeDatabase)
1587
{
1588
cupsdLogMessage(CUPSD_LOG_EMERG,
1589
"Unable to load MIME database from \"%s\" or \"%s\".",
1590
mimedir, ServerRoot);
1591
if (FatalErrors & CUPSD_FATAL_CONFIG)
1592
return (0);
1593
}
1594
1595
cupsdLogMessage(CUPSD_LOG_INFO,
1596
"Loaded MIME database from \"%s\" and \"%s\": %d types, "
1597
"%d filters...", mimedir, ServerRoot,
1598
mimeNumTypes(MimeDatabase), mimeNumFilters(MimeDatabase));
1599
1600
/*
1601
* Create a list of MIME types for the document-format-supported
1602
* attribute...
1603
*/
1604
1605
NumMimeTypes = mimeNumTypes(MimeDatabase);
1606
if (!mimeType(MimeDatabase, "application", "octet-stream"))
1607
NumMimeTypes ++;
1608
1609
if ((MimeTypes = calloc((size_t)NumMimeTypes, sizeof(const char *))) == NULL)
1610
{
1611
cupsdLogMessage(CUPSD_LOG_ERROR,
1612
"Unable to allocate memory for %d MIME types.",
1613
NumMimeTypes);
1614
NumMimeTypes = 0;
1615
}
1616
else
1617
{
1618
for (i = 0, type = mimeFirstType(MimeDatabase);
1619
type;
1620
i ++, type = mimeNextType(MimeDatabase))
1621
{
1622
snprintf(mimetype, sizeof(mimetype), "%s/%s", type->super, type->type);
1623
1624
MimeTypes[i] = _cupsStrAlloc(mimetype);
1625
}
1626
1627
if (i < NumMimeTypes)
1628
MimeTypes[i] = _cupsStrAlloc("application/octet-stream");
1629
}
1630
1631
if (LogLevel == CUPSD_LOG_DEBUG2)
1632
{
1633
mime_filter_t *filter; /* Current filter */
1634
1635
1636
for (type = mimeFirstType(MimeDatabase);
1637
type;
1638
type = mimeNextType(MimeDatabase))
1639
cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdReadConfiguration: type %s/%s",
1640
type->super, type->type);
1641
1642
for (filter = mimeFirstFilter(MimeDatabase);
1643
filter;
1644
filter = mimeNextFilter(MimeDatabase))
1645
cupsdLogMessage(CUPSD_LOG_DEBUG2,
1646
"cupsdReadConfiguration: filter %s/%s to %s/%s %d %s",
1647
filter->src->super, filter->src->type,
1648
filter->dst->super, filter->dst->type,
1649
filter->cost, filter->filter);
1650
}
1651
1652
/*
1653
* Load banners...
1654
*/
1655
1656
snprintf(temp, sizeof(temp), "%s/banners", DataDir);
1657
cupsdLoadBanners(temp);
1658
1659
/*
1660
* Load printers and classes...
1661
*/
1662
1663
cupsdLoadAllPrinters();
1664
cupsdLoadAllClasses();
1665
1666
cupsdCreateCommonData();
1667
1668
/*
1669
* Update the printcap file as needed...
1670
*/
1671
1672
if (Printcap && *Printcap && access(Printcap, 0))
1673
cupsdWritePrintcap();
1674
1675
/*
1676
* Load queued jobs...
1677
*/
1678
1679
cupsdLoadAllJobs();
1680
1681
/*
1682
* Load subscriptions...
1683
*/
1684
1685
cupsdLoadAllSubscriptions();
1686
1687
cupsdLogMessage(CUPSD_LOG_INFO, "Full reload complete.");
1688
}
1689
else
1690
{
1691
/*
1692
* Not a full reload, so recreate the common printer attributes...
1693
*/
1694
1695
cupsdCreateCommonData();
1696
1697
/*
1698
* Update all jobs as needed...
1699
*/
1700
1701
cupsdUpdateJobs();
1702
1703
/*
1704
* Update all printers as needed...
1705
*/
1706
1707
cupsdUpdatePrinters();
1708
cupsdMarkDirty(CUPSD_DIRTY_PRINTCAP);
1709
1710
cupsdLogMessage(CUPSD_LOG_INFO, "Partial reload complete.");
1711
}
1712
1713
/*
1714
* Reset the reload state...
1715
*/
1716
1717
NeedReload = RELOAD_NONE;
1718
1719
cupsdClearString(&old_serverroot);
1720
cupsdClearString(&old_requestroot);
1721
1722
return (1);
1723
}
1724
1725
1726
/*
1727
* 'get_address()' - Get an address + port number from a line.
1728
*/
1729
1730
static http_addrlist_t * /* O - Pointer to list if address good, NULL if bad */
1731
get_address(const char *value, /* I - Value string */
1732
int defport) /* I - Default port */
1733
{
1734
char buffer[1024], /* Hostname + port number buffer */
1735
defpname[255], /* Default port name */
1736
*hostname, /* Hostname or IP */
1737
*portname; /* Port number or name */
1738
http_addrlist_t *addrlist; /* Address list */
1739
1740
1741
/*
1742
* Check for an empty value...
1743
*/
1744
1745
if (!*value)
1746
{
1747
cupsdLogMessage(CUPSD_LOG_ERROR, "Bad (empty) address.");
1748
return (NULL);
1749
}
1750
1751
/*
1752
* Grab a hostname and port number; if there is no colon and the port name
1753
* is only digits, then we have a port number by itself...
1754
*/
1755
1756
strlcpy(buffer, value, sizeof(buffer));
1757
1758
if ((portname = strrchr(buffer, ':')) != NULL && !strchr(portname, ']'))
1759
{
1760
*portname++ = '\0';
1761
hostname = buffer;
1762
}
1763
else
1764
{
1765
for (portname = buffer; isdigit(*portname & 255); portname ++);
1766
1767
if (*portname)
1768
{
1769
/*
1770
* Use the default port...
1771
*/
1772
1773
snprintf(defpname, sizeof(defpname), "%d", defport);
1774
portname = defpname;
1775
hostname = buffer;
1776
}
1777
else
1778
{
1779
/*
1780
* The buffer contains just a port number...
1781
*/
1782
1783
portname = buffer;
1784
hostname = NULL;
1785
}
1786
}
1787
1788
if (hostname && !strcmp(hostname, "*"))
1789
hostname = NULL;
1790
1791
/*
1792
* Now lookup the address using httpAddrGetList()...
1793
*/
1794
1795
if ((addrlist = httpAddrGetList(hostname, AF_UNSPEC, portname)) == NULL)
1796
cupsdLogMessage(CUPSD_LOG_ERROR, "Hostname lookup for \"%s\" failed.",
1797
hostname ? hostname : "(nil)");
1798
1799
return (addrlist);
1800
}
1801
1802
1803
/*
1804
* 'get_addr_and_mask()' - Get an IP address and netmask.
1805
*/
1806
1807
static int /* O - 1 on success, 0 on failure */
1808
get_addr_and_mask(const char *value, /* I - String from config file */
1809
unsigned *ip, /* O - Address value */
1810
unsigned *mask) /* O - Mask value */
1811
{
1812
int i, j, /* Looping vars */
1813
family, /* Address family */
1814
ipcount; /* Count of fields in address */
1815
unsigned ipval; /* Value */
1816
const char *maskval, /* Pointer to start of mask value */
1817
*ptr, /* Pointer into value */
1818
*ptr2; /* ... */
1819
1820
1821
/*
1822
* Get the address...
1823
*/
1824
1825
ip[0] = ip[1] = ip[2] = ip[3] = 0x00000000;
1826
mask[0] = mask[1] = mask[2] = mask[3] = 0xffffffff;
1827
1828
if ((maskval = strchr(value, '/')) != NULL)
1829
maskval ++;
1830
else
1831
maskval = value + strlen(value);
1832
1833
#ifdef AF_INET6
1834
/*
1835
* Check for an IPv6 address...
1836
*/
1837
1838
if (*value == '[')
1839
{
1840
/*
1841
* Parse hexadecimal IPv6/IPv4 address...
1842
*/
1843
1844
family = AF_INET6;
1845
1846
for (i = 0, ptr = value + 1; *ptr && i < 8; i ++)
1847
{
1848
if (*ptr == ']')
1849
break;
1850
else if (!strncmp(ptr, "::", 2))
1851
{
1852
for (ptr2 = strchr(ptr + 2, ':'), j = 0;
1853
ptr2;
1854
ptr2 = strchr(ptr2 + 1, ':'), j ++);
1855
1856
i = 6 - j;
1857
ptr += 2;
1858
}
1859
else if (isdigit(*ptr & 255) && strchr(ptr + 1, '.') && i >= 6)
1860
{
1861
/*
1862
* Read IPv4 dotted quad...
1863
*/
1864
1865
unsigned val[4] = { 0, 0, 0, 0 };
1866
/* IPv4 address values */
1867
1868
ipcount = sscanf(ptr, "%u.%u.%u.%u", val + 0, val + 1, val + 2,
1869
val + 3);
1870
1871
/*
1872
* Range check the IP numbers...
1873
*/
1874
1875
for (i = 0; i < ipcount; i ++)
1876
if (val[i] > 255)
1877
return (0);
1878
1879
/*
1880
* Merge everything into a 32-bit IPv4 address in ip[3]...
1881
*/
1882
1883
ip[3] = (val[0] << 24) | (val[1] << 16) | (val[2] << 8) | val[3];
1884
1885
if (ipcount < 4)
1886
mask[3] = (0xffffffff << (32 - 8 * ipcount)) & 0xffffffff;
1887
1888
/*
1889
* If the leading words are all 0's then this is an IPv4 address...
1890
*/
1891
1892
if (!val[0] && !val[1] && !val[2])
1893
family = AF_INET;
1894
1895
while (isdigit(*ptr & 255) || *ptr == '.')
1896
ptr ++;
1897
break;
1898
}
1899
else if (isxdigit(*ptr & 255))
1900
{
1901
ipval = strtoul(ptr, (char **)&ptr, 16);
1902
1903
if (*ptr == ':' && ptr[1] != ':')
1904
ptr ++;
1905
1906
if (ipval > 0xffff)
1907
return (0);
1908
1909
if (i & 1)
1910
ip[i / 2] |= ipval;
1911
else
1912
ip[i / 2] |= ipval << 16;
1913
}
1914
else
1915
return (0);
1916
}
1917
1918
if (*ptr != ']')
1919
return (0);
1920
1921
ptr ++;
1922
1923
if (*ptr && *ptr != '/')
1924
return (0);
1925
}
1926
else
1927
#endif /* AF_INET6 */
1928
{
1929
/*
1930
* Parse dotted-decimal IPv4 address...
1931
*/
1932
1933
unsigned val[4] = { 0, 0, 0, 0 }; /* IPv4 address values */
1934
1935
1936
family = AF_INET;
1937
ipcount = sscanf(value, "%u.%u.%u.%u", val + 0, val + 1, val + 2, val + 3);
1938
1939
/*
1940
* Range check the IP numbers...
1941
*/
1942
1943
for (i = 0; i < ipcount; i ++)
1944
if (val[i] > 255)
1945
return (0);
1946
1947
/*
1948
* Merge everything into a 32-bit IPv4 address in ip[3]...
1949
*/
1950
1951
ip[3] = ((((((unsigned)val[0] << 8) | (unsigned)val[1]) << 8) |
1952
(unsigned)val[2]) << 8) | (unsigned)val[3];
1953
1954
if (ipcount < 4)
1955
mask[3] = (0xffffffff << (32 - 8 * ipcount)) & 0xffffffff;
1956
}
1957
1958
if (*maskval)
1959
{
1960
/*
1961
* Get the netmask value(s)...
1962
*/
1963
1964
memset(mask, 0, sizeof(unsigned) * 4);
1965
1966
if (strchr(maskval, '.'))
1967
{
1968
/*
1969
* Get dotted-decimal mask...
1970
*/
1971
1972
if (family != AF_INET)
1973
return (0);
1974
1975
if (sscanf(maskval, "%u.%u.%u.%u", mask + 0, mask + 1, mask + 2,
1976
mask + 3) != 4)
1977
return (0);
1978
1979
mask[3] |= (((((unsigned)mask[0] << 8) | (unsigned)mask[1]) << 8) |
1980
(unsigned)mask[2]) << 8;
1981
mask[0] = mask[1] = mask[2] = 0;
1982
}
1983
else
1984
{
1985
/*
1986
* Get address/bits format...
1987
*/
1988
1989
i = atoi(maskval);
1990
1991
#ifdef AF_INET6
1992
if (family == AF_INET6)
1993
{
1994
if (i > 128)
1995
return (0);
1996
1997
i = 128 - i;
1998
1999
if (i <= 96)
2000
mask[0] = 0xffffffff;
2001
else
2002
mask[0] = (0xffffffff << (i - 96)) & 0xffffffff;
2003
2004
if (i <= 64)
2005
mask[1] = 0xffffffff;
2006
else if (i >= 96)
2007
mask[1] = 0;
2008
else
2009
mask[1] = (0xffffffff << (i - 64)) & 0xffffffff;
2010
2011
if (i <= 32)
2012
mask[2] = 0xffffffff;
2013
else if (i >= 64)
2014
mask[2] = 0;
2015
else
2016
mask[2] = (0xffffffff << (i - 32)) & 0xffffffff;
2017
2018
if (i == 0)
2019
mask[3] = 0xffffffff;
2020
else if (i >= 32)
2021
mask[3] = 0;
2022
else
2023
mask[3] = (0xffffffff << i) & 0xffffffff;
2024
}
2025
else
2026
#endif /* AF_INET6 */
2027
{
2028
if (i > 32)
2029
return (0);
2030
2031
mask[0] = 0xffffffff;
2032
mask[1] = 0xffffffff;
2033
mask[2] = 0xffffffff;
2034
2035
if (i < 32)
2036
mask[3] = (0xffffffff << (32 - i)) & 0xffffffff;
2037
else
2038
mask[3] = 0xffffffff;
2039
}
2040
}
2041
}
2042
2043
cupsdLogMessage(CUPSD_LOG_DEBUG2,
2044
"get_addr_and_mask(value=\"%s\", "
2045
"ip=[%08x:%08x:%08x:%08x], mask=[%08x:%08x:%08x:%08x])",
2046
value, ip[0], ip[1], ip[2], ip[3], mask[0], mask[1], mask[2],
2047
mask[3]);
2048
2049
/*
2050
* Check for a valid netmask; no fallback like in CUPS 1.1.x!
2051
*/
2052
2053
if ((ip[0] & ~mask[0]) != 0 ||
2054
(ip[1] & ~mask[1]) != 0 ||
2055
(ip[2] & ~mask[2]) != 0 ||
2056
(ip[3] & ~mask[3]) != 0)
2057
return (0);
2058
2059
return (1);
2060
}
2061
2062
2063
/*
2064
* 'mime_error_cb()' - Log a MIME error.
2065
*/
2066
2067
static void
2068
mime_error_cb(void *ctx, /* I - Context pointer (unused) */
2069
const char *message) /* I - Message */
2070
{
2071
(void)ctx;
2072
2073
cupsdLogMessage(CUPSD_LOG_ERROR, "%s", message);
2074
}
2075
2076
2077
/*
2078
* 'parse_aaa()' - Parse authentication, authorization, and access control lines.
2079
*/
2080
2081
static int /* O - 1 on success, 0 on failure */
2082
parse_aaa(cupsd_location_t *loc, /* I - Location */
2083
char *line, /* I - Line from file */
2084
char *value, /* I - Start of value data */
2085
int linenum) /* I - Current line number */
2086
{
2087
char *valptr; /* Pointer into value */
2088
unsigned ip[4], /* IP address components */
2089
mask[4]; /* IP netmask components */
2090
2091
2092
if (!_cups_strcasecmp(line, "Encryption"))
2093
{
2094
/*
2095
* "Encryption xxx" - set required encryption level...
2096
*/
2097
2098
if (!_cups_strcasecmp(value, "never"))
2099
loc->encryption = HTTP_ENCRYPT_NEVER;
2100
else if (!_cups_strcasecmp(value, "always"))
2101
{
2102
cupsdLogMessage(CUPSD_LOG_ERROR,
2103
"Encryption value \"%s\" on line %d of %s is invalid in this "
2104
"context. Using \"required\" instead.", value, linenum, ConfigurationFile);
2105
2106
loc->encryption = HTTP_ENCRYPT_REQUIRED;
2107
}
2108
else if (!_cups_strcasecmp(value, "required"))
2109
loc->encryption = HTTP_ENCRYPT_REQUIRED;
2110
else if (!_cups_strcasecmp(value, "ifrequested"))
2111
loc->encryption = HTTP_ENCRYPT_IF_REQUESTED;
2112
else
2113
{
2114
cupsdLogMessage(CUPSD_LOG_ERROR,
2115
"Unknown Encryption value %s on line %d of %s.", value, linenum, ConfigurationFile);
2116
return (0);
2117
}
2118
}
2119
else if (!_cups_strcasecmp(line, "Order"))
2120
{
2121
/*
2122
* "Order Deny,Allow" or "Order Allow,Deny"...
2123
*/
2124
2125
if (!_cups_strncasecmp(value, "deny", 4))
2126
loc->order_type = CUPSD_AUTH_ALLOW;
2127
else if (!_cups_strncasecmp(value, "allow", 5))
2128
loc->order_type = CUPSD_AUTH_DENY;
2129
else
2130
{
2131
cupsdLogMessage(CUPSD_LOG_ERROR, "Unknown Order value %s on line %d of %s.",
2132
value, linenum, ConfigurationFile);
2133
return (0);
2134
}
2135
}
2136
else if (!_cups_strcasecmp(line, "Allow") || !_cups_strcasecmp(line, "Deny"))
2137
{
2138
/*
2139
* Allow [From] host/ip...
2140
* Deny [From] host/ip...
2141
*/
2142
2143
while (*value)
2144
{
2145
if (!_cups_strncasecmp(value, "from", 4))
2146
{
2147
/*
2148
* Strip leading "from"...
2149
*/
2150
2151
value += 4;
2152
2153
while (_cups_isspace(*value))
2154
value ++;
2155
2156
if (!*value)
2157
break;
2158
}
2159
2160
/*
2161
* Find the end of the value...
2162
*/
2163
2164
for (valptr = value; *valptr && !_cups_isspace(*valptr); valptr ++);
2165
2166
while (_cups_isspace(*valptr))
2167
*valptr++ = '\0';
2168
2169
/*
2170
* Figure out what form the allow/deny address takes:
2171
*
2172
* All
2173
* None
2174
* *.domain.com
2175
* .domain.com
2176
* host.domain.com
2177
* nnn.*
2178
* nnn.nnn.*
2179
* nnn.nnn.nnn.*
2180
* nnn.nnn.nnn.nnn
2181
* nnn.nnn.nnn.nnn/mm
2182
* nnn.nnn.nnn.nnn/mmm.mmm.mmm.mmm
2183
*/
2184
2185
if (!_cups_strcasecmp(value, "all"))
2186
{
2187
/*
2188
* All hosts...
2189
*/
2190
2191
if (!_cups_strcasecmp(line, "Allow"))
2192
cupsdAddIPMask(&(loc->allow), zeros, zeros);
2193
else
2194
cupsdAddIPMask(&(loc->deny), zeros, zeros);
2195
}
2196
else if (!_cups_strcasecmp(value, "none"))
2197
{
2198
/*
2199
* No hosts...
2200
*/
2201
2202
if (!_cups_strcasecmp(line, "Allow"))
2203
cupsdAddIPMask(&(loc->allow), ones, zeros);
2204
else
2205
cupsdAddIPMask(&(loc->deny), ones, zeros);
2206
}
2207
#ifdef AF_INET6
2208
else if (value[0] == '*' || value[0] == '.' ||
2209
(!isdigit(value[0] & 255) && value[0] != '['))
2210
#else
2211
else if (value[0] == '*' || value[0] == '.' || !isdigit(value[0] & 255))
2212
#endif /* AF_INET6 */
2213
{
2214
/*
2215
* Host or domain name...
2216
*/
2217
2218
if (value[0] == '*')
2219
value ++;
2220
2221
if (!_cups_strcasecmp(line, "Allow"))
2222
cupsdAddNameMask(&(loc->allow), value);
2223
else
2224
cupsdAddNameMask(&(loc->deny), value);
2225
}
2226
else
2227
{
2228
/*
2229
* One of many IP address forms...
2230
*/
2231
2232
if (!get_addr_and_mask(value, ip, mask))
2233
{
2234
cupsdLogMessage(CUPSD_LOG_ERROR, "Bad netmask value %s on line %d of %s.",
2235
value, linenum, ConfigurationFile);
2236
return (0);
2237
}
2238
2239
if (!_cups_strcasecmp(line, "Allow"))
2240
cupsdAddIPMask(&(loc->allow), ip, mask);
2241
else
2242
cupsdAddIPMask(&(loc->deny), ip, mask);
2243
}
2244
2245
/*
2246
* Advance to next value...
2247
*/
2248
2249
value = valptr;
2250
}
2251
}
2252
else if (!_cups_strcasecmp(line, "AuthType"))
2253
{
2254
/*
2255
* AuthType {none,basic,digest,basicdigest,negotiate,default}
2256
*/
2257
2258
if (!_cups_strcasecmp(value, "none"))
2259
{
2260
loc->type = CUPSD_AUTH_NONE;
2261
loc->level = CUPSD_AUTH_ANON;
2262
}
2263
else if (!_cups_strcasecmp(value, "basic"))
2264
{
2265
loc->type = CUPSD_AUTH_BASIC;
2266
2267
if (loc->level == CUPSD_AUTH_ANON)
2268
loc->level = CUPSD_AUTH_USER;
2269
}
2270
else if (!_cups_strcasecmp(value, "default"))
2271
{
2272
loc->type = CUPSD_AUTH_DEFAULT;
2273
2274
if (loc->level == CUPSD_AUTH_ANON)
2275
loc->level = CUPSD_AUTH_USER;
2276
}
2277
else if (!_cups_strcasecmp(value, "negotiate"))
2278
{
2279
loc->type = CUPSD_AUTH_NEGOTIATE;
2280
2281
if (loc->level == CUPSD_AUTH_ANON)
2282
loc->level = CUPSD_AUTH_USER;
2283
}
2284
else
2285
{
2286
cupsdLogMessage(CUPSD_LOG_WARN,
2287
"Unknown authorization type %s on line %d of %s.",
2288
value, linenum, ConfigurationFile);
2289
return (0);
2290
}
2291
}
2292
else if (!_cups_strcasecmp(line, "AuthClass"))
2293
{
2294
/*
2295
* AuthClass anonymous, user, system, group
2296
*/
2297
2298
if (!_cups_strcasecmp(value, "anonymous"))
2299
{
2300
loc->type = CUPSD_AUTH_NONE;
2301
loc->level = CUPSD_AUTH_ANON;
2302
2303
cupsdLogMessage(CUPSD_LOG_WARN,
2304
"\"AuthClass %s\" is deprecated; consider removing "
2305
"it from line %d.",
2306
value, linenum);
2307
}
2308
else if (!_cups_strcasecmp(value, "user"))
2309
{
2310
loc->level = CUPSD_AUTH_USER;
2311
2312
cupsdLogMessage(CUPSD_LOG_WARN,
2313
"\"AuthClass %s\" is deprecated; consider using "
2314
"\"Require valid-user\" on line %d of %s.",
2315
value, linenum, ConfigurationFile);
2316
}
2317
else if (!_cups_strcasecmp(value, "group"))
2318
{
2319
loc->level = CUPSD_AUTH_GROUP;
2320
2321
cupsdLogMessage(CUPSD_LOG_WARN,
2322
"\"AuthClass %s\" is deprecated; consider using "
2323
"\"Require user @groupname\" on line %d of %s.",
2324
value, linenum, ConfigurationFile);
2325
}
2326
else if (!_cups_strcasecmp(value, "system"))
2327
{
2328
loc->level = CUPSD_AUTH_GROUP;
2329
2330
cupsdAddName(loc, "@SYSTEM");
2331
2332
cupsdLogMessage(CUPSD_LOG_WARN,
2333
"\"AuthClass %s\" is deprecated; consider using "
2334
"\"Require user @SYSTEM\" on line %d of %s.",
2335
value, linenum, ConfigurationFile);
2336
}
2337
else
2338
{
2339
cupsdLogMessage(CUPSD_LOG_WARN,
2340
"Unknown authorization class %s on line %d of %s.",
2341
value, linenum, ConfigurationFile);
2342
return (0);
2343
}
2344
}
2345
else if (!_cups_strcasecmp(line, "AuthGroupName"))
2346
{
2347
cupsdAddName(loc, value);
2348
2349
cupsdLogMessage(CUPSD_LOG_WARN,
2350
"\"AuthGroupName %s\" directive is deprecated; consider "
2351
"using \"Require user @%s\" on line %d of %s.",
2352
value, value, linenum, ConfigurationFile);
2353
}
2354
else if (!_cups_strcasecmp(line, "Require"))
2355
{
2356
/*
2357
* Apache synonym for AuthClass and AuthGroupName...
2358
*
2359
* Get initial word:
2360
*
2361
* Require valid-user
2362
* Require group names
2363
* Require user names
2364
*/
2365
2366
for (valptr = value; !_cups_isspace(*valptr) && *valptr; valptr ++);
2367
2368
if (*valptr)
2369
*valptr++ = '\0';
2370
2371
if (!_cups_strcasecmp(value, "valid-user") ||
2372
!_cups_strcasecmp(value, "user"))
2373
loc->level = CUPSD_AUTH_USER;
2374
else if (!_cups_strcasecmp(value, "group"))
2375
loc->level = CUPSD_AUTH_GROUP;
2376
else
2377
{
2378
cupsdLogMessage(CUPSD_LOG_WARN, "Unknown Require type %s on line %d of %s.",
2379
value, linenum, ConfigurationFile);
2380
return (0);
2381
}
2382
2383
/*
2384
* Get the list of names from the line...
2385
*/
2386
2387
for (value = valptr; *value;)
2388
{
2389
while (_cups_isspace(*value))
2390
value ++;
2391
2392
#ifdef HAVE_AUTHORIZATION_H
2393
if (!strncmp(value, "@AUTHKEY(", 9))
2394
{
2395
/*
2396
* Grab "@AUTHKEY(name)" value...
2397
*/
2398
2399
for (valptr = value + 9; *valptr != ')' && *valptr; valptr ++);
2400
2401
if (*valptr)
2402
*valptr++ = '\0';
2403
}
2404
else
2405
#endif /* HAVE_AUTHORIZATION_H */
2406
if (*value == '\"' || *value == '\'')
2407
{
2408
/*
2409
* Grab quoted name...
2410
*/
2411
2412
for (valptr = value + 1; *valptr != *value && *valptr; valptr ++);
2413
2414
value ++;
2415
}
2416
else
2417
{
2418
/*
2419
* Grab literal name.
2420
*/
2421
2422
for (valptr = value; !_cups_isspace(*valptr) && *valptr; valptr ++);
2423
}
2424
2425
if (*valptr)
2426
*valptr++ = '\0';
2427
2428
cupsdAddName(loc, value);
2429
2430
for (value = valptr; _cups_isspace(*value); value ++);
2431
}
2432
}
2433
else if (!_cups_strcasecmp(line, "Satisfy"))
2434
{
2435
if (!_cups_strcasecmp(value, "all"))
2436
loc->satisfy = CUPSD_AUTH_SATISFY_ALL;
2437
else if (!_cups_strcasecmp(value, "any"))
2438
loc->satisfy = CUPSD_AUTH_SATISFY_ANY;
2439
else
2440
{
2441
cupsdLogMessage(CUPSD_LOG_WARN, "Unknown Satisfy value %s on line %d of %s.",
2442
value, linenum, ConfigurationFile);
2443
return (0);
2444
}
2445
}
2446
else
2447
return (0);
2448
2449
return (1);
2450
}
2451
2452
2453
/*
2454
* 'parse_fatal_errors()' - Parse FatalErrors values in a string.
2455
*/
2456
2457
static int /* O - FatalErrors bits */
2458
parse_fatal_errors(const char *s) /* I - FatalErrors string */
2459
{
2460
int fatal; /* FatalErrors bits */
2461
char value[1024], /* Value string */
2462
*valstart, /* Pointer into value */
2463
*valend; /* End of value */
2464
2465
2466
/*
2467
* Empty FatalErrors line yields NULL pointer...
2468
*/
2469
2470
if (!s)
2471
return (CUPSD_FATAL_NONE);
2472
2473
/*
2474
* Loop through the value string,...
2475
*/
2476
2477
strlcpy(value, s, sizeof(value));
2478
2479
fatal = CUPSD_FATAL_NONE;
2480
2481
for (valstart = value; *valstart;)
2482
{
2483
/*
2484
* Get the current space/comma-delimited kind name...
2485
*/
2486
2487
for (valend = valstart; *valend; valend ++)
2488
if (_cups_isspace(*valend) || *valend == ',')
2489
break;
2490
2491
if (*valend)
2492
*valend++ = '\0';
2493
2494
/*
2495
* Add the error to the bitmask...
2496
*/
2497
2498
if (!_cups_strcasecmp(valstart, "all"))
2499
fatal = CUPSD_FATAL_ALL;
2500
else if (!_cups_strcasecmp(valstart, "browse"))
2501
fatal |= CUPSD_FATAL_BROWSE;
2502
else if (!_cups_strcasecmp(valstart, "-browse"))
2503
fatal &= ~CUPSD_FATAL_BROWSE;
2504
else if (!_cups_strcasecmp(valstart, "config"))
2505
fatal |= CUPSD_FATAL_CONFIG;
2506
else if (!_cups_strcasecmp(valstart, "-config"))
2507
fatal &= ~CUPSD_FATAL_CONFIG;
2508
else if (!_cups_strcasecmp(valstart, "listen"))
2509
fatal |= CUPSD_FATAL_LISTEN;
2510
else if (!_cups_strcasecmp(valstart, "-listen"))
2511
fatal &= ~CUPSD_FATAL_LISTEN;
2512
else if (!_cups_strcasecmp(valstart, "log"))
2513
fatal |= CUPSD_FATAL_LOG;
2514
else if (!_cups_strcasecmp(valstart, "-log"))
2515
fatal &= ~CUPSD_FATAL_LOG;
2516
else if (!_cups_strcasecmp(valstart, "permissions"))
2517
fatal |= CUPSD_FATAL_PERMISSIONS;
2518
else if (!_cups_strcasecmp(valstart, "-permissions"))
2519
fatal &= ~CUPSD_FATAL_PERMISSIONS;
2520
else if (_cups_strcasecmp(valstart, "none"))
2521
cupsdLogMessage(CUPSD_LOG_ERROR,
2522
"Unknown FatalErrors kind \"%s\" ignored.", valstart);
2523
2524
for (valstart = valend; *valstart; valstart ++)
2525
if (!_cups_isspace(*valstart) || *valstart != ',')
2526
break;
2527
}
2528
2529
return (fatal);
2530
}
2531
2532
2533
/*
2534
* 'parse_groups()' - Parse system group names in a string.
2535
*/
2536
2537
static int /* O - 1 on success, 0 on failure */
2538
parse_groups(const char *s, /* I - Space-delimited groups */
2539
int linenum) /* I - Line number in cups-files.conf */
2540
{
2541
int status; /* Return status */
2542
char value[1024], /* Value string */
2543
*valstart, /* Pointer into value */
2544
*valend, /* End of value */
2545
quote; /* Quote character */
2546
struct group *group; /* Group */
2547
2548
2549
/*
2550
* Make a copy of the string and parse out the groups...
2551
*/
2552
2553
strlcpy(value, s, sizeof(value));
2554
2555
status = 1;
2556
valstart = value;
2557
2558
while (*valstart && NumSystemGroups < MAX_SYSTEM_GROUPS)
2559
{
2560
if (*valstart == '\'' || *valstart == '\"')
2561
{
2562
/*
2563
* Scan quoted name...
2564
*/
2565
2566
quote = *valstart++;
2567
2568
for (valend = valstart; *valend; valend ++)
2569
if (*valend == quote)
2570
break;
2571
}
2572
else
2573
{
2574
/*
2575
* Scan space or comma-delimited name...
2576
*/
2577
2578
for (valend = valstart; *valend; valend ++)
2579
if (_cups_isspace(*valend) || *valend == ',')
2580
break;
2581
}
2582
2583
if (*valend)
2584
*valend++ = '\0';
2585
2586
group = getgrnam(valstart);
2587
if (group)
2588
{
2589
cupsdSetString(SystemGroups + NumSystemGroups, valstart);
2590
SystemGroupIDs[NumSystemGroups] = group->gr_gid;
2591
2592
NumSystemGroups ++;
2593
}
2594
else
2595
{
2596
if (linenum)
2597
cupsdLogMessage(CUPSD_LOG_ERROR, "Unknown SystemGroup \"%s\" on line %d of %s.", valstart, linenum, CupsFilesFile);
2598
else
2599
cupsdLogMessage(CUPSD_LOG_ERROR, "Unknown default SystemGroup \"%s\".", valstart);
2600
2601
status = 0;
2602
}
2603
2604
endgrent();
2605
2606
valstart = valend;
2607
2608
while (*valstart == ',' || _cups_isspace(*valstart))
2609
valstart ++;
2610
}
2611
2612
return (status);
2613
}
2614
2615
2616
/*
2617
* 'parse_protocols()' - Parse browse protocols in a string.
2618
*/
2619
2620
static int /* O - Browse protocol bits */
2621
parse_protocols(const char *s) /* I - Space-delimited protocols */
2622
{
2623
int protocols; /* Browse protocol bits */
2624
char value[1024], /* Value string */
2625
*valstart, /* Pointer into value */
2626
*valend; /* End of value */
2627
2628
2629
/*
2630
* Empty protocol line yields NULL pointer...
2631
*/
2632
2633
if (!s)
2634
return (0);
2635
2636
/*
2637
* Loop through the value string,...
2638
*/
2639
2640
strlcpy(value, s, sizeof(value));
2641
2642
protocols = 0;
2643
2644
for (valstart = value; *valstart;)
2645
{
2646
/*
2647
* Get the current space/comma-delimited protocol name...
2648
*/
2649
2650
for (valend = valstart; *valend; valend ++)
2651
if (_cups_isspace(*valend) || *valend == ',')
2652
break;
2653
2654
if (*valend)
2655
*valend++ = '\0';
2656
2657
/*
2658
* Add the protocol to the bitmask...
2659
*/
2660
2661
if (!_cups_strcasecmp(valstart, "dnssd") ||
2662
!_cups_strcasecmp(valstart, "dns-sd") ||
2663
!_cups_strcasecmp(valstart, "bonjour"))
2664
protocols |= BROWSE_DNSSD;
2665
else if (!_cups_strcasecmp(valstart, "all"))
2666
protocols |= BROWSE_ALL;
2667
else if (_cups_strcasecmp(valstart, "none"))
2668
cupsdLogMessage(CUPSD_LOG_ERROR,
2669
"Unknown browse protocol \"%s\" ignored.", valstart);
2670
2671
for (valstart = valend; *valstart; valstart ++)
2672
if (!_cups_isspace(*valstart) || *valstart != ',')
2673
break;
2674
}
2675
2676
return (protocols);
2677
}
2678
2679
2680
/*
2681
* 'parse_variable()' - Parse a variable line.
2682
*/
2683
2684
static int /* O - 1 on success, 0 on failure */
2685
parse_variable(
2686
const char *filename, /* I - Name of configuration file */
2687
int linenum, /* I - Line in configuration file */
2688
const char *line, /* I - Line from configuration file */
2689
const char *value, /* I - Value from configuration file */
2690
size_t num_vars, /* I - Number of variables */
2691
const cupsd_var_t *vars) /* I - Variables */
2692
{
2693
size_t i; /* Looping var */
2694
const cupsd_var_t *var; /* Variables */
2695
char temp[1024]; /* Temporary string */
2696
2697
2698
for (i = num_vars, var = vars; i; i --, var ++)
2699
if (!_cups_strcasecmp(line, var->name))
2700
break;
2701
2702
if (i == 0)
2703
{
2704
/*
2705
* Unknown directive! Output an error message and continue...
2706
*/
2707
2708
if (!value)
2709
cupsdLogMessage(CUPSD_LOG_ERROR, "Missing value for %s on line %d of %s.",
2710
line, linenum, filename);
2711
else
2712
cupsdLogMessage(CUPSD_LOG_ERROR, "Unknown directive %s on line %d of %s.",
2713
line, linenum, filename);
2714
2715
return (0);
2716
}
2717
2718
switch (var->type)
2719
{
2720
case CUPSD_VARTYPE_INTEGER :
2721
if (!value)
2722
{
2723
cupsdLogMessage(CUPSD_LOG_ERROR,
2724
"Missing integer value for %s on line %d of %s.",
2725
line, linenum, filename);
2726
return (0);
2727
}
2728
else if (!isdigit(*value & 255))
2729
{
2730
cupsdLogMessage(CUPSD_LOG_ERROR,
2731
"Bad integer value for %s on line %d of %s.",
2732
line, linenum, filename);
2733
return (0);
2734
}
2735
else
2736
{
2737
int n; /* Number */
2738
char *units; /* Units */
2739
2740
n = (int)strtol(value, &units, 0);
2741
2742
if (units && *units)
2743
{
2744
if (tolower(units[0] & 255) == 'g')
2745
n *= 1024 * 1024 * 1024;
2746
else if (tolower(units[0] & 255) == 'm')
2747
n *= 1024 * 1024;
2748
else if (tolower(units[0] & 255) == 'k')
2749
n *= 1024;
2750
else if (tolower(units[0] & 255) == 't')
2751
n *= 262144;
2752
else
2753
{
2754
cupsdLogMessage(CUPSD_LOG_ERROR,
2755
"Unknown integer value for %s on line %d of %s.",
2756
line, linenum, filename);
2757
return (0);
2758
}
2759
}
2760
2761
if (n < 0)
2762
{
2763
cupsdLogMessage(CUPSD_LOG_ERROR,
2764
"Bad negative integer value for %s on line %d of "
2765
"%s.", line, linenum, filename);
2766
return (0);
2767
}
2768
else
2769
{
2770
*((int *)var->ptr) = n;
2771
}
2772
}
2773
break;
2774
2775
case CUPSD_VARTYPE_PERM :
2776
if (!value)
2777
{
2778
cupsdLogMessage(CUPSD_LOG_ERROR,
2779
"Missing permissions value for %s on line %d of %s.",
2780
line, linenum, filename);
2781
return (0);
2782
}
2783
else if (!isdigit(*value & 255))
2784
{
2785
/* TODO: Add chmod UGO syntax support */
2786
cupsdLogMessage(CUPSD_LOG_ERROR,
2787
"Bad permissions value for %s on line %d of %s.",
2788
line, linenum, filename);
2789
return (0);
2790
}
2791
else
2792
{
2793
int n = (int)strtol(value, NULL, 8);
2794
/* Permissions value */
2795
2796
if (n < 0)
2797
{
2798
cupsdLogMessage(CUPSD_LOG_ERROR,
2799
"Bad negative permissions value for %s on line %d of "
2800
"%s.", line, linenum, filename);
2801
return (0);
2802
}
2803
else
2804
{
2805
*((mode_t *)var->ptr) = (mode_t)n;
2806
}
2807
}
2808
break;
2809
2810
case CUPSD_VARTYPE_TIME :
2811
if (!value)
2812
{
2813
cupsdLogMessage(CUPSD_LOG_ERROR,
2814
"Missing time interval value for %s on line %d of "
2815
"%s.", line, linenum, filename);
2816
return (0);
2817
}
2818
else if (!_cups_strncasecmp(line, "PreserveJob", 11) &&
2819
(!_cups_strcasecmp(value, "true") ||
2820
!_cups_strcasecmp(value, "on") ||
2821
!_cups_strcasecmp(value, "enabled") ||
2822
!_cups_strcasecmp(value, "yes")))
2823
{
2824
*((int *)var->ptr) = INT_MAX;
2825
}
2826
else if (!_cups_strcasecmp(value, "false") ||
2827
!_cups_strcasecmp(value, "off") ||
2828
!_cups_strcasecmp(value, "disabled") ||
2829
!_cups_strcasecmp(value, "no"))
2830
{
2831
*((int *)var->ptr) = 0;
2832
}
2833
else if (!isdigit(*value & 255))
2834
{
2835
cupsdLogMessage(CUPSD_LOG_ERROR,
2836
"Unknown time interval value for %s on line %d of "
2837
"%s.", line, linenum, filename);
2838
return (0);
2839
}
2840
else
2841
{
2842
double n; /* Number */
2843
char *units; /* Units */
2844
2845
n = strtod(value, &units);
2846
2847
if (units && *units)
2848
{
2849
if (tolower(units[0] & 255) == 'w')
2850
n *= 7 * 24 * 60 * 60;
2851
else if (tolower(units[0] & 255) == 'd')
2852
n *= 24 * 60 * 60;
2853
else if (tolower(units[0] & 255) == 'h')
2854
n *= 60 * 60;
2855
else if (tolower(units[0] & 255) == 'm')
2856
n *= 60;
2857
else
2858
{
2859
cupsdLogMessage(CUPSD_LOG_ERROR,
2860
"Unknown time interval value for %s on line "
2861
"%d of %s.", line, linenum, filename);
2862
return (0);
2863
}
2864
}
2865
2866
if (n < 0.0 || n > INT_MAX)
2867
{
2868
cupsdLogMessage(CUPSD_LOG_ERROR,
2869
"Bad time value for %s on line %d of %s.",
2870
line, linenum, filename);
2871
return (0);
2872
}
2873
else
2874
{
2875
*((int *)var->ptr) = (int)n;
2876
}
2877
}
2878
break;
2879
2880
case CUPSD_VARTYPE_BOOLEAN :
2881
if (!value)
2882
{
2883
cupsdLogMessage(CUPSD_LOG_ERROR,
2884
"Missing boolean value for %s on line %d of %s.",
2885
line, linenum, filename);
2886
return (0);
2887
}
2888
else if (!_cups_strcasecmp(value, "true") ||
2889
!_cups_strcasecmp(value, "on") ||
2890
!_cups_strcasecmp(value, "enabled") ||
2891
!_cups_strcasecmp(value, "yes") ||
2892
atoi(value) != 0)
2893
{
2894
*((int *)var->ptr) = TRUE;
2895
}
2896
else if (!_cups_strcasecmp(value, "false") ||
2897
!_cups_strcasecmp(value, "off") ||
2898
!_cups_strcasecmp(value, "disabled") ||
2899
!_cups_strcasecmp(value, "no") ||
2900
!_cups_strcasecmp(value, "0"))
2901
{
2902
*((int *)var->ptr) = FALSE;
2903
}
2904
else
2905
{
2906
cupsdLogMessage(CUPSD_LOG_ERROR,
2907
"Unknown boolean value %s on line %d of %s.",
2908
value, linenum, filename);
2909
return (0);
2910
}
2911
break;
2912
2913
case CUPSD_VARTYPE_PATHNAME :
2914
if (!value)
2915
{
2916
cupsdLogMessage(CUPSD_LOG_ERROR,
2917
"Missing pathname value for %s on line %d of %s.",
2918
line, linenum, filename);
2919
return (0);
2920
}
2921
2922
if (value[0] == '/')
2923
strlcpy(temp, value, sizeof(temp));
2924
else
2925
snprintf(temp, sizeof(temp), "%s/%s", ServerRoot, value);
2926
2927
if (access(temp, 0) && _cups_strcasecmp(value, "internal") && _cups_strcasecmp(line, "ServerKeychain"))
2928
{
2929
cupsdLogMessage(CUPSD_LOG_ERROR,
2930
"File or directory for \"%s %s\" on line %d of %s "
2931
"does not exist.", line, value, linenum, filename);
2932
return (0);
2933
}
2934
2935
cupsdSetString((char **)var->ptr, temp);
2936
break;
2937
2938
case CUPSD_VARTYPE_STRING :
2939
cupsdSetString((char **)var->ptr, value);
2940
break;
2941
}
2942
2943
return (1);
2944
}
2945
2946
2947
/*
2948
* 'read_cupsd_conf()' - Read the cupsd.conf configuration file.
2949
*/
2950
2951
static int /* O - 1 on success, 0 on failure */
2952
read_cupsd_conf(cups_file_t *fp) /* I - File to read from */
2953
{
2954
int linenum; /* Current line number */
2955
char line[HTTP_MAX_BUFFER],
2956
/* Line from file */
2957
temp[HTTP_MAX_BUFFER],
2958
/* Temporary buffer for value */
2959
*value; /* Pointer to value */
2960
http_addrlist_t *addrlist, /* Address list */
2961
*addr; /* Current address */
2962
2963
2964
/*
2965
* Loop through each line in the file...
2966
*/
2967
2968
linenum = 0;
2969
2970
while (cupsFileGetConf(fp, line, sizeof(line), &value, &linenum))
2971
{
2972
/*
2973
* Decode the directive...
2974
*/
2975
2976
if (!_cups_strcasecmp(line, "<Location") && value)
2977
{
2978
/*
2979
* <Location path>
2980
*/
2981
2982
linenum = read_location(fp, value, linenum);
2983
if (linenum == 0)
2984
return (0);
2985
}
2986
else if (!_cups_strcasecmp(line, "<Policy") && value)
2987
{
2988
/*
2989
* <Policy name>
2990
*/
2991
2992
linenum = read_policy(fp, value, linenum);
2993
if (linenum == 0)
2994
return (0);
2995
}
2996
else if (!_cups_strcasecmp(line, "FaxRetryInterval") && value)
2997
{
2998
JobRetryInterval = atoi(value);
2999
cupsdLogMessage(CUPSD_LOG_WARN,
3000
"FaxRetryInterval is deprecated; use "
3001
"JobRetryInterval on line %d of %s.", linenum, ConfigurationFile);
3002
}
3003
else if (!_cups_strcasecmp(line, "FaxRetryLimit") && value)
3004
{
3005
JobRetryLimit = atoi(value);
3006
cupsdLogMessage(CUPSD_LOG_WARN,
3007
"FaxRetryLimit is deprecated; use "
3008
"JobRetryLimit on line %d of %s.", linenum, ConfigurationFile);
3009
}
3010
#ifdef HAVE_TLS
3011
else if (!_cups_strcasecmp(line, "SSLOptions"))
3012
{
3013
/*
3014
* SSLOptions [AllowRC4] [AllowSSL3] [AllowDH] [DenyCBC] [DenyTLS1.0] [None]
3015
*/
3016
3017
int options = _HTTP_TLS_NONE,/* SSL/TLS options */
3018
min_version = _HTTP_TLS_1_0,
3019
max_version = _HTTP_TLS_MAX;
3020
3021
if (value)
3022
{
3023
char *start, /* Start of option */
3024
*end; /* End of option */
3025
3026
for (start = value; *start; start = end)
3027
{
3028
/*
3029
* Find end of keyword...
3030
*/
3031
3032
end = start;
3033
while (*end && !_cups_isspace(*end))
3034
end ++;
3035
3036
if (*end)
3037
*end++ = '\0';
3038
3039
/*
3040
* Compare...
3041
*/
3042
3043
if (!_cups_strcasecmp(start, "AllowRC4"))
3044
options |= _HTTP_TLS_ALLOW_RC4;
3045
else if (!_cups_strcasecmp(start, "AllowSSL3"))
3046
min_version = _HTTP_TLS_SSL3;
3047
else if (!_cups_strcasecmp(start, "AllowDH"))
3048
options |= _HTTP_TLS_ALLOW_DH;
3049
else if (!_cups_strcasecmp(start, "DenyCBC"))
3050
options |= _HTTP_TLS_DENY_CBC;
3051
else if (!_cups_strcasecmp(start, "DenyTLS1.0"))
3052
min_version = _HTTP_TLS_1_1;
3053
else if (!_cups_strcasecmp(start, "MaxTLS1.0"))
3054
max_version = _HTTP_TLS_1_0;
3055
else if (!_cups_strcasecmp(start, "MaxTLS1.1"))
3056
max_version = _HTTP_TLS_1_1;
3057
else if (!_cups_strcasecmp(start, "MaxTLS1.2"))
3058
max_version = _HTTP_TLS_1_2;
3059
else if (!_cups_strcasecmp(start, "MaxTLS1.3"))
3060
max_version = _HTTP_TLS_1_3;
3061
else if (!_cups_strcasecmp(start, "MinTLS1.0"))
3062
min_version = _HTTP_TLS_1_0;
3063
else if (!_cups_strcasecmp(start, "MinTLS1.1"))
3064
min_version = _HTTP_TLS_1_1;
3065
else if (!_cups_strcasecmp(start, "MinTLS1.2"))
3066
min_version = _HTTP_TLS_1_2;
3067
else if (!_cups_strcasecmp(start, "MinTLS1.3"))
3068
min_version = _HTTP_TLS_1_3;
3069
else if (!_cups_strcasecmp(start, "None"))
3070
options = _HTTP_TLS_NONE;
3071
else if (_cups_strcasecmp(start, "NoEmptyFragments"))
3072
cupsdLogMessage(CUPSD_LOG_WARN, "Unknown SSL option %s at line %d.", start, linenum);
3073
}
3074
}
3075
3076
_httpTLSSetOptions(options, min_version, max_version);
3077
}
3078
#endif /* HAVE_TLS */
3079
else if ((!_cups_strcasecmp(line, "Port") || !_cups_strcasecmp(line, "Listen")
3080
#ifdef HAVE_TLS
3081
|| !_cups_strcasecmp(line, "SSLPort") || !_cups_strcasecmp(line, "SSLListen")
3082
#endif /* HAVE_TLS */
3083
) && value)
3084
{
3085
/*
3086
* Add listening address(es) to the list...
3087
*/
3088
3089
cupsd_listener_t *lis; /* New listeners array */
3090
3091
3092
/*
3093
* Get the address list...
3094
*/
3095
3096
addrlist = get_address(value, IPP_PORT);
3097
3098
if (!addrlist)
3099
{
3100
cupsdLogMessage(CUPSD_LOG_ERROR, "Bad %s address %s at line %d.", line,
3101
value, linenum);
3102
continue;
3103
}
3104
3105
/*
3106
* Add each address...
3107
*/
3108
3109
for (addr = addrlist; addr; addr = addr->next)
3110
{
3111
/*
3112
* See if this address is already present...
3113
*/
3114
3115
for (lis = (cupsd_listener_t *)cupsArrayFirst(Listeners);
3116
lis;
3117
lis = (cupsd_listener_t *)cupsArrayNext(Listeners))
3118
if (httpAddrEqual(&(addr->addr), &(lis->address)) &&
3119
httpAddrPort(&(addr->addr)) == httpAddrPort(&(lis->address)))
3120
break;
3121
3122
if (lis)
3123
{
3124
#ifdef HAVE_ONDEMAND
3125
if (!lis->on_demand)
3126
#endif /* HAVE_ONDEMAND */
3127
{
3128
httpAddrString(&lis->address, temp, sizeof(temp));
3129
cupsdLogMessage(CUPSD_LOG_WARN,
3130
"Duplicate listen address \"%s\" ignored.", temp);
3131
}
3132
3133
continue;
3134
}
3135
3136
/*
3137
* Allocate another listener...
3138
*/
3139
3140
if (!Listeners)
3141
Listeners = cupsArrayNew(NULL, NULL);
3142
3143
if (!Listeners)
3144
{
3145
cupsdLogMessage(CUPSD_LOG_ERROR,
3146
"Unable to allocate %s at line %d - %s.",
3147
line, linenum, strerror(errno));
3148
break;
3149
}
3150
3151
if ((lis = calloc(1, sizeof(cupsd_listener_t))) == NULL)
3152
{
3153
cupsdLogMessage(CUPSD_LOG_ERROR,
3154
"Unable to allocate %s at line %d - %s.",
3155
line, linenum, strerror(errno));
3156
break;
3157
}
3158
3159
cupsArrayAdd(Listeners, lis);
3160
3161
/*
3162
* Copy the current address and log it...
3163
*/
3164
3165
memcpy(&(lis->address), &(addr->addr), sizeof(lis->address));
3166
lis->fd = -1;
3167
3168
#ifdef HAVE_TLS
3169
if (!_cups_strcasecmp(line, "SSLPort") || !_cups_strcasecmp(line, "SSLListen"))
3170
lis->encryption = HTTP_ENCRYPT_ALWAYS;
3171
#endif /* HAVE_TLS */
3172
3173
httpAddrString(&lis->address, temp, sizeof(temp));
3174
3175
#ifdef AF_LOCAL
3176
if (lis->address.addr.sa_family == AF_LOCAL)
3177
cupsdLogMessage(CUPSD_LOG_INFO, "Listening to %s (Domain)", temp);
3178
else
3179
#endif /* AF_LOCAL */
3180
cupsdLogMessage(CUPSD_LOG_INFO, "Listening to %s:%d (IPv%d)", temp,
3181
httpAddrPort(&(lis->address)),
3182
httpAddrFamily(&(lis->address)) == AF_INET ? 4 : 6);
3183
3184
if (!httpAddrLocalhost(&(lis->address)))
3185
RemotePort = httpAddrPort(&(lis->address));
3186
}
3187
3188
/*
3189
* Free the list...
3190
*/
3191
3192
httpAddrFreeList(addrlist);
3193
}
3194
else if (!_cups_strcasecmp(line, "BrowseProtocols") ||
3195
!_cups_strcasecmp(line, "BrowseLocalProtocols"))
3196
{
3197
/*
3198
* "BrowseProtocols name [... name]"
3199
* "BrowseLocalProtocols name [... name]"
3200
*/
3201
3202
int protocols = parse_protocols(value);
3203
3204
if (protocols < 0)
3205
{
3206
cupsdLogMessage(CUPSD_LOG_ERROR,
3207
"Unknown browse protocol \"%s\" on line %d of %s.",
3208
value, linenum, ConfigurationFile);
3209
break;
3210
}
3211
3212
BrowseLocalProtocols = protocols;
3213
}
3214
else if (!_cups_strcasecmp(line, "DefaultAuthType") && value)
3215
{
3216
/*
3217
* DefaultAuthType {basic,digest,basicdigest,negotiate}
3218
*/
3219
3220
if (!_cups_strcasecmp(value, "none"))
3221
default_auth_type = CUPSD_AUTH_NONE;
3222
else if (!_cups_strcasecmp(value, "basic"))
3223
default_auth_type = CUPSD_AUTH_BASIC;
3224
else if (!_cups_strcasecmp(value, "negotiate"))
3225
default_auth_type = CUPSD_AUTH_NEGOTIATE;
3226
else if (!_cups_strcasecmp(value, "auto"))
3227
default_auth_type = CUPSD_AUTH_AUTO;
3228
else
3229
{
3230
cupsdLogMessage(CUPSD_LOG_WARN,
3231
"Unknown default authorization type %s on line %d of %s.",
3232
value, linenum, ConfigurationFile);
3233
if (FatalErrors & CUPSD_FATAL_CONFIG)
3234
return (0);
3235
}
3236
}
3237
#ifdef HAVE_TLS
3238
else if (!_cups_strcasecmp(line, "DefaultEncryption"))
3239
{
3240
/*
3241
* DefaultEncryption {Never,IfRequested,Required}
3242
*/
3243
3244
if (!value || !_cups_strcasecmp(value, "never"))
3245
DefaultEncryption = HTTP_ENCRYPT_NEVER;
3246
else if (!_cups_strcasecmp(value, "required"))
3247
DefaultEncryption = HTTP_ENCRYPT_REQUIRED;
3248
else if (!_cups_strcasecmp(value, "ifrequested"))
3249
DefaultEncryption = HTTP_ENCRYPT_IF_REQUESTED;
3250
else
3251
{
3252
cupsdLogMessage(CUPSD_LOG_WARN,
3253
"Unknown default encryption %s on line %d of %s.",
3254
value, linenum, ConfigurationFile);
3255
if (FatalErrors & CUPSD_FATAL_CONFIG)
3256
return (0);
3257
}
3258
}
3259
#endif /* HAVE_TLS */
3260
else if (!_cups_strcasecmp(line, "HostNameLookups") && value)
3261
{
3262
/*
3263
* Do hostname lookups?
3264
*/
3265
3266
if (!_cups_strcasecmp(value, "off") || !_cups_strcasecmp(value, "no") ||
3267
!_cups_strcasecmp(value, "false"))
3268
HostNameLookups = 0;
3269
else if (!_cups_strcasecmp(value, "on") || !_cups_strcasecmp(value, "yes") ||
3270
!_cups_strcasecmp(value, "true"))
3271
HostNameLookups = 1;
3272
else if (!_cups_strcasecmp(value, "double"))
3273
HostNameLookups = 2;
3274
else
3275
cupsdLogMessage(CUPSD_LOG_WARN, "Unknown HostNameLookups %s on line %d of %s.",
3276
value, linenum, ConfigurationFile);
3277
}
3278
else if (!_cups_strcasecmp(line, "AccessLogLevel") && value)
3279
{
3280
/*
3281
* Amount of logging to do to access log...
3282
*/
3283
3284
if (!_cups_strcasecmp(value, "all"))
3285
AccessLogLevel = CUPSD_ACCESSLOG_ALL;
3286
else if (!_cups_strcasecmp(value, "actions"))
3287
AccessLogLevel = CUPSD_ACCESSLOG_ACTIONS;
3288
else if (!_cups_strcasecmp(value, "config"))
3289
AccessLogLevel = CUPSD_ACCESSLOG_CONFIG;
3290
else if (!_cups_strcasecmp(value, "none"))
3291
AccessLogLevel = CUPSD_ACCESSLOG_NONE;
3292
else
3293
cupsdLogMessage(CUPSD_LOG_WARN, "Unknown AccessLogLevel %s on line %d of %s.",
3294
value, linenum, ConfigurationFile);
3295
}
3296
else if (!_cups_strcasecmp(line, "LogLevel") && value)
3297
{
3298
/*
3299
* Amount of logging to do to error log...
3300
*/
3301
3302
if (!_cups_strcasecmp(value, "debug2"))
3303
LogLevel = CUPSD_LOG_DEBUG2;
3304
else if (!_cups_strcasecmp(value, "debug"))
3305
LogLevel = CUPSD_LOG_DEBUG;
3306
else if (!_cups_strcasecmp(value, "info"))
3307
LogLevel = CUPSD_LOG_INFO;
3308
else if (!_cups_strcasecmp(value, "notice"))
3309
LogLevel = CUPSD_LOG_NOTICE;
3310
else if (!_cups_strcasecmp(value, "warn"))
3311
LogLevel = CUPSD_LOG_WARN;
3312
else if (!_cups_strcasecmp(value, "error"))
3313
LogLevel = CUPSD_LOG_ERROR;
3314
else if (!_cups_strcasecmp(value, "crit"))
3315
LogLevel = CUPSD_LOG_CRIT;
3316
else if (!_cups_strcasecmp(value, "alert"))
3317
LogLevel = CUPSD_LOG_ALERT;
3318
else if (!_cups_strcasecmp(value, "emerg"))
3319
LogLevel = CUPSD_LOG_EMERG;
3320
else if (!_cups_strcasecmp(value, "none"))
3321
LogLevel = CUPSD_LOG_NONE;
3322
else
3323
cupsdLogMessage(CUPSD_LOG_WARN, "Unknown LogLevel %s on line %d of %s.",
3324
value, linenum, ConfigurationFile);
3325
}
3326
else if (!_cups_strcasecmp(line, "LogTimeFormat") && value)
3327
{
3328
/*
3329
* Amount of logging to do to error log...
3330
*/
3331
3332
if (!_cups_strcasecmp(value, "standard"))
3333
LogTimeFormat = CUPSD_TIME_STANDARD;
3334
else if (!_cups_strcasecmp(value, "usecs"))
3335
LogTimeFormat = CUPSD_TIME_USECS;
3336
else
3337
cupsdLogMessage(CUPSD_LOG_WARN, "Unknown LogTimeFormat %s on line %d of %s.",
3338
value, linenum, ConfigurationFile);
3339
}
3340
else if (!_cups_strcasecmp(line, "ReadyPaperSizes") && value)
3341
{
3342
/*
3343
* ReadyPaperSizes sizename[,sizename,...]
3344
*/
3345
3346
if (ReadyPaperSizes)
3347
_cupsArrayAddStrings(ReadyPaperSizes, value, ',');
3348
else
3349
ReadyPaperSizes = _cupsArrayNewStrings(value, ',');
3350
}
3351
else if (!_cups_strcasecmp(line, "ServerTokens") && value)
3352
{
3353
/*
3354
* Set the string used for the Server header...
3355
*/
3356
3357
struct utsname plat; /* Platform info */
3358
3359
3360
uname(&plat);
3361
3362
if (!_cups_strcasecmp(value, "ProductOnly"))
3363
cupsdSetString(&ServerHeader, "CUPS IPP");
3364
else if (!_cups_strcasecmp(value, "Major"))
3365
cupsdSetStringf(&ServerHeader, "CUPS/%d IPP/2", CUPS_VERSION_MAJOR);
3366
else if (!_cups_strcasecmp(value, "Minor"))
3367
cupsdSetStringf(&ServerHeader, "CUPS/%d.%d IPP/2.1", CUPS_VERSION_MAJOR,
3368
CUPS_VERSION_MINOR);
3369
else if (!_cups_strcasecmp(value, "Minimal"))
3370
cupsdSetString(&ServerHeader, CUPS_MINIMAL " IPP/2.1");
3371
else if (!_cups_strcasecmp(value, "OS"))
3372
cupsdSetStringf(&ServerHeader, CUPS_MINIMAL " (%s %s) IPP/2.1",
3373
plat.sysname, plat.release);
3374
else if (!_cups_strcasecmp(value, "Full"))
3375
cupsdSetStringf(&ServerHeader, CUPS_MINIMAL " (%s %s; %s) IPP/2.1",
3376
plat.sysname, plat.release, plat.machine);
3377
else if (!_cups_strcasecmp(value, "None"))
3378
cupsdSetString(&ServerHeader, "");
3379
else
3380
cupsdLogMessage(CUPSD_LOG_WARN, "Unknown ServerTokens %s on line %d of %s.",
3381
value, linenum, ConfigurationFile);
3382
}
3383
else if (!_cups_strcasecmp(line, "ServerAlias") && value)
3384
{
3385
/*
3386
* ServerAlias name [... name]
3387
*/
3388
3389
if (!ServerAlias)
3390
ServerAlias = cupsArrayNew(NULL, NULL);
3391
3392
while (*value)
3393
{
3394
size_t valuelen; /* Length of value */
3395
3396
for (valuelen = 0; value[valuelen]; valuelen ++)
3397
if (_cups_isspace(value[valuelen]) || value[valuelen] == ',')
3398
{
3399
value[valuelen ++] = '\0';
3400
break;
3401
}
3402
3403
cupsdAddAlias(ServerAlias, value);
3404
3405
for (value += valuelen; *value; value ++)
3406
if (!_cups_isspace(*value) || *value != ',')
3407
break;
3408
}
3409
}
3410
else if (!_cups_strcasecmp(line, "AccessLog") ||
3411
!_cups_strcasecmp(line, "CacheDir") ||
3412
!_cups_strcasecmp(line, "ConfigFilePerm") ||
3413
!_cups_strcasecmp(line, "DataDir") ||
3414
!_cups_strcasecmp(line, "DocumentRoot") ||
3415
!_cups_strcasecmp(line, "ErrorLog") ||
3416
!_cups_strcasecmp(line, "FatalErrors") ||
3417
!_cups_strcasecmp(line, "FileDevice") ||
3418
!_cups_strcasecmp(line, "Group") ||
3419
!_cups_strcasecmp(line, "LogFilePerm") ||
3420
!_cups_strcasecmp(line, "PageLog") ||
3421
!_cups_strcasecmp(line, "PassEnv") ||
3422
!_cups_strcasecmp(line, "Printcap") ||
3423
!_cups_strcasecmp(line, "PrintcapFormat") ||
3424
!_cups_strcasecmp(line, "RemoteRoot") ||
3425
!_cups_strcasecmp(line, "RequestRoot") ||
3426
!_cups_strcasecmp(line, "ServerBin") ||
3427
!_cups_strcasecmp(line, "ServerCertificate") ||
3428
!_cups_strcasecmp(line, "ServerKey") ||
3429
!_cups_strcasecmp(line, "ServerKeychain") ||
3430
!_cups_strcasecmp(line, "ServerRoot") ||
3431
!_cups_strcasecmp(line, "SetEnv") ||
3432
!_cups_strcasecmp(line, "StateDir") ||
3433
!_cups_strcasecmp(line, "SystemGroup") ||
3434
!_cups_strcasecmp(line, "SystemGroupAuthKey") ||
3435
!_cups_strcasecmp(line, "TempDir") ||
3436
!_cups_strcasecmp(line, "User"))
3437
{
3438
cupsdLogMessage(CUPSD_LOG_INFO,
3439
"Please move \"%s%s%s\" on line %d of %s to the %s file; "
3440
"this will become an error in a future release.",
3441
line, value ? " " : "", value ? value : "", linenum,
3442
ConfigurationFile, CupsFilesFile);
3443
}
3444
else
3445
parse_variable(ConfigurationFile, linenum, line, value,
3446
sizeof(cupsd_vars) / sizeof(cupsd_vars[0]), cupsd_vars);
3447
}
3448
3449
return (1);
3450
}
3451
3452
3453
/*
3454
* 'read_cups_files_conf()' - Read the cups-files.conf configuration file.
3455
*/
3456
3457
static int /* O - 1 on success, 0 on failure */
3458
read_cups_files_conf(cups_file_t *fp) /* I - File to read from */
3459
{
3460
size_t i; /* Looping var */
3461
int linenum; /* Current line number */
3462
char line[HTTP_MAX_BUFFER], /* Line from file */
3463
*value; /* Value from line */
3464
struct group *group; /* Group */
3465
static const char * const prohibited_env[] =
3466
{ /* Prohibited environment variables */
3467
"APPLE_LANGUAGE",
3468
"AUTH_DOMAIN",
3469
"AUTH_INFO_REQUIRED",
3470
"AUTH_NEGOTIATE",
3471
"AUTH_PASSWORD",
3472
"AUTH_UID",
3473
"AUTH_USERNAME",
3474
"CHARSET",
3475
"CLASS",
3476
"CLASSIFICATION",
3477
"CONTENT_TYPE",
3478
"CUPS_CACHEDIR",
3479
"CUPS_DATADIR",
3480
"CUPS_DOCROOT",
3481
"CUPS_FILETYPE",
3482
"CUPS_FONTPATH",
3483
"CUPS_MAX_MESSAGE",
3484
"CUPS_REQUESTROOT",
3485
"CUPS_SERVERBIN",
3486
"CUPS_SERVERROOT",
3487
"CUPS_STATEDIR",
3488
"DEVICE_URI",
3489
"FINAL_CONTENT_TYPE",
3490
"HOME",
3491
"LANG",
3492
"PPD",
3493
"PRINTER",
3494
"PRINTER_INFO",
3495
"PRINTER_LOCATION",
3496
"PRINTER_STATE_REASONS",
3497
"RIP_CACHE",
3498
"SERVER_ADMIN",
3499
"SOFTWARE",
3500
"TMPDIR",
3501
"USER"
3502
};
3503
3504
3505
/*
3506
* Loop through each line in the file...
3507
*/
3508
3509
linenum = 0;
3510
3511
while (cupsFileGetConf(fp, line, sizeof(line), &value, &linenum))
3512
{
3513
if (!_cups_strcasecmp(line, "FatalErrors"))
3514
FatalErrors = parse_fatal_errors(value);
3515
else if (!_cups_strcasecmp(line, "Group") && value)
3516
{
3517
/*
3518
* Group ID to run as...
3519
*/
3520
3521
if (isdigit(value[0]))
3522
Group = (gid_t)strtoul(value, NULL, 10);
3523
else
3524
{
3525
endgrent();
3526
group = getgrnam(value);
3527
3528
if (group != NULL)
3529
Group = group->gr_gid;
3530
else
3531
{
3532
cupsdLogMessage(CUPSD_LOG_ERROR,
3533
"Unknown Group \"%s\" on line %d of %s.", value,
3534
linenum, CupsFilesFile);
3535
if (FatalErrors & CUPSD_FATAL_CONFIG)
3536
return (0);
3537
}
3538
}
3539
}
3540
else if (!_cups_strcasecmp(line, "LogFileGroup") && value)
3541
{
3542
/*
3543
* Group ID to log as...
3544
*/
3545
3546
if (isdigit(value[0]))
3547
LogFileGroup = (gid_t)strtoul(value, NULL, 10);
3548
else
3549
{
3550
endgrent();
3551
group = getgrnam(value);
3552
3553
if (group != NULL)
3554
LogFileGroup = group->gr_gid;
3555
else
3556
{
3557
cupsdLogMessage(CUPSD_LOG_ERROR,
3558
"Unknown LogFileGroup \"%s\" on line %d of %s.", value,
3559
linenum, CupsFilesFile);
3560
if (FatalErrors & CUPSD_FATAL_CONFIG)
3561
return (0);
3562
}
3563
}
3564
}
3565
else if (!_cups_strcasecmp(line, "PassEnv") && value)
3566
{
3567
/*
3568
* PassEnv variable [... variable]
3569
*/
3570
3571
size_t valuelen; /* Length of variable name */
3572
3573
while (*value)
3574
{
3575
for (valuelen = 0; value[valuelen]; valuelen ++)
3576
if (_cups_isspace(value[valuelen]) || value[valuelen] == ',')
3577
break;
3578
3579
if (value[valuelen])
3580
{
3581
value[valuelen ++] = '\0';
3582
}
3583
3584
for (i = 0; i < (sizeof(prohibited_env) / sizeof(prohibited_env[0])); i ++)
3585
{
3586
if (!strcmp(value, prohibited_env[i]))
3587
{
3588
cupsdLogMessage(CUPSD_LOG_ERROR, "Environment variable \"%s\" cannot be passed through on line %d of %s.", value, linenum, CupsFilesFile);
3589
3590
if (FatalErrors & CUPSD_FATAL_CONFIG)
3591
return (0);
3592
else
3593
break;
3594
}
3595
}
3596
3597
if (i >= sizeof(prohibited_env) / sizeof(prohibited_env[0]))
3598
cupsdSetEnv(value, NULL);
3599
3600
for (value += valuelen; *value; value ++)
3601
if (!_cups_isspace(*value) || *value != ',')
3602
break;
3603
}
3604
}
3605
else if (!_cups_strcasecmp(line, "PrintcapFormat") && value)
3606
{
3607
/*
3608
* Format of printcap file?
3609
*/
3610
3611
if (!_cups_strcasecmp(value, "bsd"))
3612
PrintcapFormat = PRINTCAP_BSD;
3613
else if (!_cups_strcasecmp(value, "plist"))
3614
PrintcapFormat = PRINTCAP_PLIST;
3615
else if (!_cups_strcasecmp(value, "solaris"))
3616
PrintcapFormat = PRINTCAP_SOLARIS;
3617
else
3618
{
3619
cupsdLogMessage(CUPSD_LOG_ERROR,
3620
"Unknown PrintcapFormat \"%s\" on line %d of %s.",
3621
value, linenum, CupsFilesFile);
3622
if (FatalErrors & CUPSD_FATAL_CONFIG)
3623
return (0);
3624
}
3625
}
3626
else if (!_cups_strcasecmp(line, "Sandboxing") && value)
3627
{
3628
/*
3629
* Level of sandboxing?
3630
*/
3631
3632
if (!_cups_strcasecmp(value, "off") && getuid())
3633
Sandboxing = CUPSD_SANDBOXING_OFF;
3634
else if (!_cups_strcasecmp(value, "relaxed"))
3635
Sandboxing = CUPSD_SANDBOXING_RELAXED;
3636
else if (!_cups_strcasecmp(value, "strict"))
3637
Sandboxing = CUPSD_SANDBOXING_STRICT;
3638
else
3639
{
3640
cupsdLogMessage(CUPSD_LOG_ERROR,
3641
"Unknown Sandboxing \"%s\" on line %d of %s.",
3642
value, linenum, CupsFilesFile);
3643
if (FatalErrors & CUPSD_FATAL_CONFIG)
3644
return (0);
3645
}
3646
}
3647
else if (!_cups_strcasecmp(line, "SetEnv") && value)
3648
{
3649
/*
3650
* SetEnv variable value
3651
*/
3652
3653
char *valueptr; /* Pointer to environment variable value */
3654
3655
for (valueptr = value; *valueptr && !isspace(*valueptr & 255); valueptr ++);
3656
3657
if (*valueptr)
3658
{
3659
/*
3660
* Found a value...
3661
*/
3662
3663
while (isspace(*valueptr & 255))
3664
*valueptr++ = '\0';
3665
3666
for (i = 0; i < (sizeof(prohibited_env) / sizeof(prohibited_env[0])); i ++)
3667
{
3668
if (!strcmp(value, prohibited_env[i]))
3669
{
3670
cupsdLogMessage(CUPSD_LOG_ERROR, "Environment variable \"%s\" cannot be set on line %d of %s.", value, linenum, CupsFilesFile);
3671
3672
if (FatalErrors & CUPSD_FATAL_CONFIG)
3673
return (0);
3674
else
3675
break;
3676
}
3677
}
3678
3679
if (i >= (sizeof(prohibited_env) / sizeof(prohibited_env[0])))
3680
cupsdSetEnv(value, valueptr);
3681
}
3682
else
3683
cupsdLogMessage(CUPSD_LOG_ERROR,
3684
"Missing value for SetEnv directive on line %d of %s.",
3685
linenum, ConfigurationFile);
3686
}
3687
else if (!_cups_strcasecmp(line, "SystemGroup") && value)
3688
{
3689
/*
3690
* SystemGroup (admin) group(s)...
3691
*/
3692
3693
if (!parse_groups(value, linenum))
3694
{
3695
if (FatalErrors & CUPSD_FATAL_CONFIG)
3696
return (0);
3697
}
3698
}
3699
else if (!_cups_strcasecmp(line, "User") && value)
3700
{
3701
/*
3702
* User ID to run as...
3703
*/
3704
3705
if (isdigit(value[0] & 255))
3706
{
3707
uid_t uid = (uid_t)strtoul(value, NULL, 10);
3708
3709
if (!uid)
3710
{
3711
cupsdLogMessage(CUPSD_LOG_ERROR,
3712
"Will not use User 0 as specified on line %d of %s "
3713
"for security reasons. You must use a non-"
3714
"privileged account instead.",
3715
linenum, CupsFilesFile);
3716
if (FatalErrors & CUPSD_FATAL_CONFIG)
3717
return (0);
3718
}
3719
else
3720
User = uid;
3721
}
3722
else
3723
{
3724
struct passwd *p; /* Password information */
3725
3726
endpwent();
3727
p = getpwnam(value);
3728
3729
if (p)
3730
{
3731
if (!p->pw_uid)
3732
{
3733
cupsdLogMessage(CUPSD_LOG_ERROR,
3734
"Will not use User %s (UID=0) as specified on line "
3735
"%d of %s for security reasons. You must use a "
3736
"non-privileged account instead.",
3737
value, linenum, CupsFilesFile);
3738
if (FatalErrors & CUPSD_FATAL_CONFIG)
3739
return (0);
3740
}
3741
else
3742
User = p->pw_uid;
3743
}
3744
else
3745
{
3746
cupsdLogMessage(CUPSD_LOG_ERROR,
3747
"Unknown User \"%s\" on line %d of %s.",
3748
value, linenum, CupsFilesFile);
3749
if (FatalErrors & CUPSD_FATAL_CONFIG)
3750
return (0);
3751
}
3752
}
3753
}
3754
else if (!_cups_strcasecmp(line, "ServerCertificate") ||
3755
!_cups_strcasecmp(line, "ServerKey"))
3756
{
3757
cupsdLogMessage(CUPSD_LOG_INFO,
3758
"The \"%s\" directive on line %d of %s is no longer "
3759
"supported; this will become an error in a future "
3760
"release.",
3761
line, linenum, CupsFilesFile);
3762
}
3763
else if (!parse_variable(CupsFilesFile, linenum, line, value,
3764
sizeof(cupsfiles_vars) / sizeof(cupsfiles_vars[0]),
3765
cupsfiles_vars) &&
3766
(FatalErrors & CUPSD_FATAL_CONFIG))
3767
return (0);
3768
}
3769
3770
return (1);
3771
}
3772
3773
3774
/*
3775
* 'read_location()' - Read a <Location path> definition.
3776
*/
3777
3778
static int /* O - New line number or 0 on error */
3779
read_location(cups_file_t *fp, /* I - Configuration file */
3780
char *location, /* I - Location name/path */
3781
int linenum) /* I - Current line number */
3782
{
3783
cupsd_location_t *loc, /* New location */
3784
*parent; /* Parent location */
3785
char line[HTTP_MAX_BUFFER],
3786
/* Line buffer */
3787
*value, /* Value for directive */
3788
*valptr; /* Pointer into value */
3789
3790
3791
if ((parent = cupsdFindLocation(location)) != NULL)
3792
cupsdLogMessage(CUPSD_LOG_WARN, "Duplicate <Location %s> on line %d of %s.",
3793
location, linenum, ConfigurationFile);
3794
else if ((parent = cupsdNewLocation(location)) == NULL)
3795
return (0);
3796
else
3797
{
3798
cupsdAddLocation(parent);
3799
3800
parent->limit = CUPSD_AUTH_LIMIT_ALL;
3801
}
3802
3803
loc = parent;
3804
3805
while (cupsFileGetConf(fp, line, sizeof(line), &value, &linenum))
3806
{
3807
/*
3808
* Decode the directive...
3809
*/
3810
3811
if (!_cups_strcasecmp(line, "</Location>"))
3812
return (linenum);
3813
else if (!_cups_strcasecmp(line, "<Limit") ||
3814
!_cups_strcasecmp(line, "<LimitExcept"))
3815
{
3816
if (!value)
3817
{
3818
cupsdLogMessage(CUPSD_LOG_ERROR, "Syntax error on line %d of %s.", linenum, ConfigurationFile);
3819
if (FatalErrors & CUPSD_FATAL_CONFIG)
3820
return (0);
3821
else
3822
continue;
3823
}
3824
3825
if ((loc = cupsdCopyLocation(parent)) == NULL)
3826
return (0);
3827
3828
cupsdAddLocation(loc);
3829
3830
loc->limit = 0;
3831
while (*value)
3832
{
3833
for (valptr = value; !isspace(*valptr & 255) && *valptr; valptr ++);
3834
3835
if (*valptr)
3836
*valptr++ = '\0';
3837
3838
if (!strcmp(value, "ALL"))
3839
loc->limit = CUPSD_AUTH_LIMIT_ALL;
3840
else if (!strcmp(value, "GET"))
3841
loc->limit |= CUPSD_AUTH_LIMIT_GET;
3842
else if (!strcmp(value, "HEAD"))
3843
loc->limit |= CUPSD_AUTH_LIMIT_HEAD;
3844
else if (!strcmp(value, "OPTIONS"))
3845
loc->limit |= CUPSD_AUTH_LIMIT_OPTIONS;
3846
else if (!strcmp(value, "POST"))
3847
loc->limit |= CUPSD_AUTH_LIMIT_POST;
3848
else if (!strcmp(value, "PUT"))
3849
loc->limit |= CUPSD_AUTH_LIMIT_PUT;
3850
else if (!strcmp(value, "TRACE"))
3851
loc->limit |= CUPSD_AUTH_LIMIT_TRACE;
3852
else
3853
cupsdLogMessage(CUPSD_LOG_WARN, "Unknown request type %s on line %d of %s.",
3854
value, linenum, ConfigurationFile);
3855
3856
for (value = valptr; isspace(*value & 255); value ++);
3857
}
3858
3859
if (!_cups_strcasecmp(line, "<LimitExcept"))
3860
loc->limit = CUPSD_AUTH_LIMIT_ALL ^ loc->limit;
3861
3862
parent->limit &= ~loc->limit;
3863
}
3864
else if (!_cups_strcasecmp(line, "</Limit>") ||
3865
!_cups_strcasecmp(line, "</LimitExcept>"))
3866
loc = parent;
3867
else if (!value)
3868
{
3869
cupsdLogMessage(CUPSD_LOG_ERROR, "Missing value on line %d of %s.", linenum, ConfigurationFile);
3870
if (FatalErrors & CUPSD_FATAL_CONFIG)
3871
return (0);
3872
}
3873
else if (!parse_aaa(loc, line, value, linenum))
3874
{
3875
cupsdLogMessage(CUPSD_LOG_ERROR,
3876
"Unknown Location directive %s on line %d of %s.",
3877
line, linenum, ConfigurationFile);
3878
if (FatalErrors & CUPSD_FATAL_CONFIG)
3879
return (0);
3880
}
3881
}
3882
3883
cupsdLogMessage(CUPSD_LOG_ERROR,
3884
"Unexpected end-of-file at line %d while reading location.",
3885
linenum);
3886
3887
return ((FatalErrors & CUPSD_FATAL_CONFIG) ? 0 : linenum);
3888
}
3889
3890
3891
/*
3892
* 'read_policy()' - Read a <Policy name> definition.
3893
*/
3894
3895
static int /* O - New line number or 0 on error */
3896
read_policy(cups_file_t *fp, /* I - Configuration file */
3897
char *policy, /* I - Location name/path */
3898
int linenum) /* I - Current line number */
3899
{
3900
int i; /* Looping var */
3901
cupsd_policy_t *pol; /* Policy */
3902
cupsd_location_t *op; /* Policy operation */
3903
int num_ops; /* Number of IPP operations */
3904
ipp_op_t ops[100]; /* Operations */
3905
char line[HTTP_MAX_BUFFER],
3906
/* Line buffer */
3907
*value, /* Value for directive */
3908
*valptr; /* Pointer into value */
3909
3910
3911
/*
3912
* Create the policy...
3913
*/
3914
3915
if ((pol = cupsdFindPolicy(policy)) != NULL)
3916
cupsdLogMessage(CUPSD_LOG_WARN, "Duplicate <Policy %s> on line %d of %s.",
3917
policy, linenum, ConfigurationFile);
3918
else if ((pol = cupsdAddPolicy(policy)) == NULL)
3919
return (0);
3920
3921
/*
3922
* Read from the file...
3923
*/
3924
3925
op = NULL;
3926
num_ops = 0;
3927
3928
while (cupsFileGetConf(fp, line, sizeof(line), &value, &linenum))
3929
{
3930
/*
3931
* Decode the directive...
3932
*/
3933
3934
if (!_cups_strcasecmp(line, "</Policy>"))
3935
{
3936
if (op)
3937
cupsdLogMessage(CUPSD_LOG_WARN,
3938
"Missing </Limit> before </Policy> on line %d of %s.",
3939
linenum, ConfigurationFile);
3940
3941
set_policy_defaults(pol);
3942
3943
return (linenum);
3944
}
3945
else if (!_cups_strcasecmp(line, "<Limit") && !op)
3946
{
3947
if (!value)
3948
{
3949
cupsdLogMessage(CUPSD_LOG_ERROR, "Syntax error on line %d of %s.", linenum, ConfigurationFile);
3950
if (FatalErrors & CUPSD_FATAL_CONFIG)
3951
return (0);
3952
else
3953
continue;
3954
}
3955
3956
/*
3957
* Scan for IPP operation names...
3958
*/
3959
3960
num_ops = 0;
3961
3962
while (*value)
3963
{
3964
for (valptr = value; !isspace(*valptr & 255) && *valptr; valptr ++);
3965
3966
if (*valptr)
3967
*valptr++ = '\0';
3968
3969
if (num_ops < (int)(sizeof(ops) / sizeof(ops[0])))
3970
{
3971
if (!_cups_strcasecmp(value, "All"))
3972
ops[num_ops ++] = IPP_ANY_OPERATION;
3973
else if ((ops[num_ops] = ippOpValue(value)) == IPP_BAD_OPERATION)
3974
cupsdLogMessage(CUPSD_LOG_ERROR, "Bad IPP operation name \"%s\" on line %d of %s.", value, linenum, ConfigurationFile);
3975
else
3976
num_ops ++;
3977
}
3978
else
3979
cupsdLogMessage(CUPSD_LOG_ERROR,
3980
"Too many operations listed on line %d of %s.",
3981
linenum, ConfigurationFile);
3982
3983
for (value = valptr; isspace(*value & 255); value ++);
3984
}
3985
3986
/*
3987
* If none are specified, apply the policy to all operations...
3988
*/
3989
3990
if (num_ops == 0)
3991
{
3992
ops[0] = IPP_ANY_OPERATION;
3993
num_ops = 1;
3994
}
3995
3996
/*
3997
* Add a new policy for the first operation...
3998
*/
3999
4000
op = cupsdAddPolicyOp(pol, NULL, ops[0]);
4001
}
4002
else if (!_cups_strcasecmp(line, "</Limit>") && op)
4003
{
4004
/*
4005
* Finish the current operation limit...
4006
*/
4007
4008
if (num_ops > 1)
4009
{
4010
/*
4011
* Copy the policy to the other operations...
4012
*/
4013
4014
for (i = 1; i < num_ops; i ++)
4015
cupsdAddPolicyOp(pol, op, ops[i]);
4016
}
4017
4018
op = NULL;
4019
}
4020
else if (!value)
4021
{
4022
cupsdLogMessage(CUPSD_LOG_ERROR, "Missing value on line %d of %s.", linenum, ConfigurationFile);
4023
if (FatalErrors & CUPSD_FATAL_CONFIG)
4024
return (0);
4025
}
4026
else if (!_cups_strcasecmp(line, "JobPrivateAccess") ||
4027
!_cups_strcasecmp(line, "JobPrivateValues") ||
4028
!_cups_strcasecmp(line, "SubscriptionPrivateAccess") ||
4029
!_cups_strcasecmp(line, "SubscriptionPrivateValues"))
4030
{
4031
if (op)
4032
{
4033
cupsdLogMessage(CUPSD_LOG_ERROR,
4034
"%s directive must appear outside <Limit>...</Limit> "
4035
"on line %d of %s.", line, linenum, ConfigurationFile);
4036
if (FatalErrors & CUPSD_FATAL_CONFIG)
4037
return (0);
4038
}
4039
else
4040
{
4041
/*
4042
* Pull out whitespace-delimited values...
4043
*/
4044
4045
while (*value)
4046
{
4047
/*
4048
* Find the end of the current value...
4049
*/
4050
4051
for (valptr = value; !isspace(*valptr & 255) && *valptr; valptr ++);
4052
4053
if (*valptr)
4054
*valptr++ = '\0';
4055
4056
/*
4057
* Save it appropriately...
4058
*/
4059
4060
if (!_cups_strcasecmp(line, "JobPrivateAccess"))
4061
{
4062
/*
4063
* JobPrivateAccess {all|default|user/group list|@@ACL}
4064
*/
4065
4066
if (!_cups_strcasecmp(value, "default"))
4067
{
4068
cupsdAddString(&(pol->job_access), "@OWNER");
4069
cupsdAddString(&(pol->job_access), "@SYSTEM");
4070
}
4071
else
4072
cupsdAddString(&(pol->job_access), value);
4073
}
4074
else if (!_cups_strcasecmp(line, "JobPrivateValues"))
4075
{
4076
/*
4077
* JobPrivateValues {all|none|default|attribute list}
4078
*/
4079
4080
if (!_cups_strcasecmp(value, "default"))
4081
{
4082
cupsdAddString(&(pol->job_attrs), "job-name");
4083
cupsdAddString(&(pol->job_attrs), "job-originating-host-name");
4084
cupsdAddString(&(pol->job_attrs), "job-originating-user-name");
4085
cupsdAddString(&(pol->job_attrs), "phone");
4086
}
4087
else
4088
cupsdAddString(&(pol->job_attrs), value);
4089
}
4090
else if (!_cups_strcasecmp(line, "SubscriptionPrivateAccess"))
4091
{
4092
/*
4093
* SubscriptionPrivateAccess {all|default|user/group list|@@ACL}
4094
*/
4095
4096
if (!_cups_strcasecmp(value, "default"))
4097
{
4098
cupsdAddString(&(pol->sub_access), "@OWNER");
4099
cupsdAddString(&(pol->sub_access), "@SYSTEM");
4100
}
4101
else
4102
cupsdAddString(&(pol->sub_access), value);
4103
}
4104
else /* if (!_cups_strcasecmp(line, "SubscriptionPrivateValues")) */
4105
{
4106
/*
4107
* SubscriptionPrivateValues {all|none|default|attribute list}
4108
*/
4109
4110
if (!_cups_strcasecmp(value, "default"))
4111
{
4112
cupsdAddString(&(pol->sub_attrs), "notify-events");
4113
cupsdAddString(&(pol->sub_attrs), "notify-pull-method");
4114
cupsdAddString(&(pol->sub_attrs), "notify-recipient-uri");
4115
cupsdAddString(&(pol->sub_attrs), "notify-subscriber-user-name");
4116
cupsdAddString(&(pol->sub_attrs), "notify-user-data");
4117
}
4118
else
4119
cupsdAddString(&(pol->sub_attrs), value);
4120
}
4121
4122
/*
4123
* Find the next string on the line...
4124
*/
4125
4126
for (value = valptr; isspace(*value & 255); value ++);
4127
}
4128
}
4129
}
4130
else if (!op)
4131
{
4132
cupsdLogMessage(CUPSD_LOG_ERROR,
4133
"Missing <Limit ops> directive before %s on line %d of %s.",
4134
line, linenum, ConfigurationFile);
4135
if (FatalErrors & CUPSD_FATAL_CONFIG)
4136
return (0);
4137
}
4138
else if (!parse_aaa(op, line, value, linenum))
4139
{
4140
cupsdLogMessage(CUPSD_LOG_ERROR,
4141
"Unknown Policy Limit directive %s on line %d of %s.",
4142
line, linenum, ConfigurationFile);
4143
4144
if (FatalErrors & CUPSD_FATAL_CONFIG)
4145
return (0);
4146
}
4147
}
4148
4149
cupsdLogMessage(CUPSD_LOG_ERROR,
4150
"Unexpected end-of-file at line %d while reading policy "
4151
"\"%s\".", linenum, policy);
4152
4153
return ((FatalErrors & CUPSD_FATAL_CONFIG) ? 0 : linenum);
4154
}
4155
4156
4157
/*
4158
* 'set_policy_defaults()' - Set default policy values as needed.
4159
*/
4160
4161
static void
4162
set_policy_defaults(cupsd_policy_t *pol)/* I - Policy */
4163
{
4164
cupsd_location_t *op; /* Policy operation */
4165
4166
4167
/*
4168
* Verify that we have an explicit policy for Validate-Job, Cancel-Jobs,
4169
* Cancel-My-Jobs, Close-Job, and CUPS-Get-Document, which ensures that
4170
* upgrades do not introduce new security issues...
4171
*
4172
* CUPS STR #4659: Allow a lone <Limit All> policy.
4173
*/
4174
4175
if (cupsArrayCount(pol->ops) > 1)
4176
{
4177
if ((op = cupsdFindPolicyOp(pol, IPP_VALIDATE_JOB)) == NULL ||
4178
op->op == IPP_ANY_OPERATION)
4179
{
4180
if ((op = cupsdFindPolicyOp(pol, IPP_PRINT_JOB)) != NULL &&
4181
op->op != IPP_ANY_OPERATION)
4182
{
4183
/*
4184
* Add a new limit for Validate-Job using the Print-Job limit as a
4185
* template...
4186
*/
4187
4188
cupsdLogMessage(CUPSD_LOG_WARN, "No limit for Validate-Job defined in policy %s - using Print-Job's policy.", pol->name);
4189
4190
cupsdAddPolicyOp(pol, op, IPP_VALIDATE_JOB);
4191
}
4192
else
4193
cupsdLogMessage(CUPSD_LOG_WARN, "No limit for Validate-Job defined in policy %s and no suitable template found.", pol->name);
4194
}
4195
4196
if ((op = cupsdFindPolicyOp(pol, IPP_CANCEL_JOBS)) == NULL ||
4197
op->op == IPP_ANY_OPERATION)
4198
{
4199
if ((op = cupsdFindPolicyOp(pol, IPP_PAUSE_PRINTER)) != NULL &&
4200
op->op != IPP_ANY_OPERATION)
4201
{
4202
/*
4203
* Add a new limit for Cancel-Jobs using the Pause-Printer limit as a
4204
* template...
4205
*/
4206
4207
cupsdLogMessage(CUPSD_LOG_WARN, "No limit for Cancel-Jobs defined in policy %s - using Pause-Printer's policy.", pol->name);
4208
4209
cupsdAddPolicyOp(pol, op, IPP_CANCEL_JOBS);
4210
}
4211
else
4212
cupsdLogMessage(CUPSD_LOG_WARN, "No limit for Cancel-Jobs defined in policy %s and no suitable template found.", pol->name);
4213
}
4214
4215
if ((op = cupsdFindPolicyOp(pol, IPP_CANCEL_MY_JOBS)) == NULL ||
4216
op->op == IPP_ANY_OPERATION)
4217
{
4218
if ((op = cupsdFindPolicyOp(pol, IPP_SEND_DOCUMENT)) != NULL &&
4219
op->op != IPP_ANY_OPERATION)
4220
{
4221
/*
4222
* Add a new limit for Cancel-My-Jobs using the Send-Document limit as
4223
* a template...
4224
*/
4225
4226
cupsdLogMessage(CUPSD_LOG_WARN, "No limit for Cancel-My-Jobs defined in policy %s - using Send-Document's policy.", pol->name);
4227
4228
cupsdAddPolicyOp(pol, op, IPP_CANCEL_MY_JOBS);
4229
}
4230
else
4231
cupsdLogMessage(CUPSD_LOG_WARN, "No limit for Cancel-My-Jobs defined in policy %s and no suitable template found.", pol->name);
4232
}
4233
4234
if ((op = cupsdFindPolicyOp(pol, IPP_CLOSE_JOB)) == NULL ||
4235
op->op == IPP_ANY_OPERATION)
4236
{
4237
if ((op = cupsdFindPolicyOp(pol, IPP_SEND_DOCUMENT)) != NULL &&
4238
op->op != IPP_ANY_OPERATION)
4239
{
4240
/*
4241
* Add a new limit for Close-Job using the Send-Document limit as a
4242
* template...
4243
*/
4244
4245
cupsdLogMessage(CUPSD_LOG_WARN, "No limit for Close-Job defined in policy %s - using Send-Document's policy.", pol->name);
4246
4247
cupsdAddPolicyOp(pol, op, IPP_CLOSE_JOB);
4248
}
4249
else
4250
cupsdLogMessage(CUPSD_LOG_WARN, "No limit for Close-Job defined in policy %s and no suitable template found.", pol->name);
4251
}
4252
4253
if ((op = cupsdFindPolicyOp(pol, CUPS_GET_DOCUMENT)) == NULL ||
4254
op->op == IPP_ANY_OPERATION)
4255
{
4256
if ((op = cupsdFindPolicyOp(pol, IPP_SEND_DOCUMENT)) != NULL &&
4257
op->op != IPP_ANY_OPERATION)
4258
{
4259
/*
4260
* Add a new limit for CUPS-Get-Document using the Send-Document
4261
* limit as a template...
4262
*/
4263
4264
cupsdLogMessage(CUPSD_LOG_WARN, "No limit for CUPS-Get-Document defined in policy %s - using Send-Document's policy.", pol->name);
4265
4266
cupsdAddPolicyOp(pol, op, CUPS_GET_DOCUMENT);
4267
}
4268
else
4269
cupsdLogMessage(CUPSD_LOG_WARN, "No limit for CUPS-Get-Document defined in policy %s and no suitable template found.", pol->name);
4270
}
4271
}
4272
4273
/*
4274
* Verify we have JobPrivateAccess, JobPrivateValues,
4275
* SubscriptionPrivateAccess, and SubscriptionPrivateValues in the policy.
4276
*/
4277
4278
if (!pol->job_access)
4279
{
4280
cupsdLogMessage(CUPSD_LOG_WARN, "No JobPrivateAccess defined in policy %s - using defaults.", pol->name);
4281
cupsdAddString(&(pol->job_access), "@OWNER");
4282
cupsdAddString(&(pol->job_access), "@SYSTEM");
4283
}
4284
4285
if (!pol->job_attrs)
4286
{
4287
cupsdLogMessage(CUPSD_LOG_WARN, "No JobPrivateValues defined in policy %s - using defaults.", pol->name);
4288
cupsdAddString(&(pol->job_attrs), "job-name");
4289
cupsdAddString(&(pol->job_attrs), "job-originating-host-name");
4290
cupsdAddString(&(pol->job_attrs), "job-originating-user-name");
4291
cupsdAddString(&(pol->job_attrs), "phone");
4292
}
4293
4294
if (!pol->sub_access)
4295
{
4296
cupsdLogMessage(CUPSD_LOG_WARN, "No SubscriptionPrivateAccess defined in policy %s - using defaults.", pol->name);
4297
cupsdAddString(&(pol->sub_access), "@OWNER");
4298
cupsdAddString(&(pol->sub_access), "@SYSTEM");
4299
}
4300
4301
if (!pol->sub_attrs)
4302
{
4303
cupsdLogMessage(CUPSD_LOG_WARN, "No SubscriptionPrivateValues defined in policy %s - using defaults.", pol->name);
4304
cupsdAddString(&(pol->sub_attrs), "notify-events");
4305
cupsdAddString(&(pol->sub_attrs), "notify-pull-method");
4306
cupsdAddString(&(pol->sub_attrs), "notify-recipient-uri");
4307
cupsdAddString(&(pol->sub_attrs), "notify-subscriber-user-name");
4308
cupsdAddString(&(pol->sub_attrs), "notify-user-data");
4309
}
4310
}
4311
4312