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

« back to all changes in this revision

Viewing changes to .pc/default-ripcache-size-auto.patch/scheduler/conf.c

  • Committer: Bazaar Package Importer
  • Author(s): Martin Pitt, Till Kamppeter, Martin Pitt
  • Date: 2011-07-14 15:02:36 UTC
  • mfrom: (1.2.11 upstream)
  • Revision ID: james.westby@ubuntu.com-20110714150236-skkf0p5m6ccu5usu
Tags: 1.4.7-1
* New upstream version.

[ Till Kamppeter ]
* debian/patches/ubuntu-upstart.dpatch: Updated the patch to add support
  to the new device enumeration functionality of udev-configure-printer.
  This way we do not need to retrigger the printers. Retriggering is only
  needed if udev rules change. A fallback to the old bahavior is provided
  so that this CUPS package continues to work with older versions of
  udev-configure-printer.

[ Martin Pitt ]
* Update patches for new upstream release.
* Drop fix-broken-ipv6-uris.patch, applied upstream.
* debian/local/apparmor-profile: /var/run → /run transition. (LP: #810270)
* Drop debian/patches/ubuntu-upstart.dpatch and move the upstart script to
  debian/local/cups.upstart. In debian/rules, copy it to debian/, and remove
  that again during clean. This is a slightly easier workaround for a
  nonexisting "dh_installinit --sysvinit-only" option than the previous
  creation of the upstart file with an ubuntu specific dpatch.
* debian/patches/, debian/rules, debian/control, debian/source/format: Move
  to source format "3.0 (quilt)" and convert our dpatches to quilt patches.
  Drop dpatch build dependency.
* Move Ubuntu specific patches to debian/patches/ubuntu. In debian/rules,
  apply them when building on Ubuntu. Add "patch" build dependency.

Show diffs side-by-side

added added

removed removed

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