~ubuntu-branches/ubuntu/wily/cups/wily

« back to all changes in this revision

Viewing changes to .pc/airprint-support.patch/scheduler/conf.c

  • Committer: Package Import Robot
  • Author(s): Till Kamppeter
  • Date: 2013-03-25 10:13:01 UTC
  • Revision ID: package-import@ubuntu.com-20130325101301-ygjpzd4cwpgc98j2
Tags: 1.6.2-1ubuntu3
debian/patches/airprint-support.patch: Let the DNS-SD subtype "_universal"
get added to the printer's DNS-SD registration. It is needed for iOS to
find the printers.

Show diffs side-by-side

added added

removed removed

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