~ubuntu-branches/ubuntu/utopic/cups/utopic

« back to all changes in this revision

Viewing changes to .pc/cupsd-set-default-for-SyncOnClose-to-Yes.patch/scheduler/conf.c

  • Committer: Package Import Robot
  • Author(s): Didier Raboud, Till Kamppeter, Steve Langasek, Didier Raboud
  • Date: 2014-01-03 18:42:39 UTC
  • mfrom: (99.2.3 sid)
  • Revision ID: package-import@ubuntu.com-20140103184239-85wju2l7weie4dgo
Tags: 1.7.0-1
* New 1.7.0 upstream release

[ Till Kamppeter ]
* Refresh most patches with quilt
* Removed usb-backend-do-not-crash-if-usb-disabled-in-bios and
  cupsd-no-crash-on-avahi-threaded-poll-shutdown patches as they got
  applied upstream
* Removed drop-arch-specifics-from-doc patch as it is not needed
  anymore
* Updated drop_unnecessary_dependencies, manpage-hyphen-minus,
  manpage-translations and ppd-poll-with-client-conf patches manually
  to apply to the new CUPS version
* Added error counting exception from
  usb-backend-do-not-crash-if-usb-disabled-in-bios to
  tests-ignore-warnings
* Install the newly added ippfind utility and its manpage in
  cups-client
* Added pwg.h to libcups2-dev package
* Call dh_auto_clean only if the file Makedefs is present, to avoid a
  FTBFS
* Added color management extensions from Joe Simon's GSoC 2013
  project.
* Patch cups-files.conf to activate CUPS daemon syncing of files when
  closing, so that config files (like printers.conf) do not
  mysteriously disappear (LP: #1157972)
* In the AppArmor profile, allow execution of programs in
  /etc/cups/interfaces/, needed to make CUPS working with queues based
  on System V interface scripts, especially PPD-less queues
  auto-generated by cups-browsed from cups-filters 1.0.41 on.
* Silenced AppArmor noise from udev.conf in syslog (LP: #1229766)

[ Steve Langasek ]
* Add cups-filters (>= 1.0.42) as alternative to foomatic-filters
  (which is deprecated) in package relationships

[ Didier Raboud ]
* Remove Roger Leigh from uploaders on his request with thanks for his
  past work!
* Switch avahi LSB Should-Start dependency to be avahi-daemon; also
  bump package relationship to >= 0.6.31-3~ (Closes: #731608)
* Refresh the manpage translation files
* Move the USB backend quirk rules file to cups-server-common
* Add 38 new 1.7.0 libcups2 symbols
* Mark one C++ libcupsppdc1 symbol as optional as it isn't exported in
  1.7.0 anymore
* Import Fedora patches:
  - to avoid sign-extending CRCs in gz decompression
  - to build with full read-only relocations
  - to fix job history logging (upstream patch)
  - to set the internal default for SyncOnClose to Yes, instead of
    only configuring it to Yes
  - to fix a stringpool corruption issue
  - to prevent USB timeouts causing incorrect print output
* Import Fedora patch updates:
  - to dont-use-dbus-from-two-threads patch so it removes a call to
    avahi_threaded_poll_stop()
  - to avoid_stale_lockfile_in_dbus_notifier patch to call _exit when
    handling SIGTERM
* Move manpage-translations patch at the very end of the patch series
  to have it include all our patches

Show diffs side-by-side

added added

removed removed

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