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