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