From 8fe0183a710b1daacad419e617ddd3601085bfcf Mon Sep 17 00:00:00 2001 From: msweet Date: Tue, 11 Feb 2014 15:06:01 +0000 Subject: [PATCH] Improve CUPS sandboxing - Use separate profiles for filters and backends. - Add Sandboxing configuration directive to control whether a strict or relaxed profile is used. - The new strict profile is a whitelist profile that does not allow unlimited networking, among other things. git-svn-id: svn+ssh://src.apple.com/svn/cups/cups.org/trunk@11576 a1ca3aef-8c08-0410-bb20-df032aa958be --- doc/help/man-cups-files.conf.html | 21 +- doc/help/ref-cups-files-conf.html.in | 47 ++--- man/cups-files.conf.man.in | 35 ++-- scheduler/conf.c | 27 ++- scheduler/conf.h | 11 + scheduler/cups-exec.c | 46 ++-- scheduler/cupsd.h | 22 +- scheduler/job.c | 15 +- scheduler/job.h | 3 +- scheduler/main.c | 5 +- scheduler/process.c | 197 +++++++++++++---- scheduler/server.c | 2 +- test/run-stp-tests.sh | 303 ++++++++++++++------------- xcode/CUPS.xcodeproj/project.pbxproj | 2 + 14 files changed, 453 insertions(+), 283 deletions(-) diff --git a/doc/help/man-cups-files.conf.html b/doc/help/man-cups-files.conf.html index 3e30a9d98..b6d3afecd 100644 --- a/doc/help/man-cups-files.conf.html +++ b/doc/help/man-cups-files.conf.html @@ -119,21 +119,26 @@ accesses.
Specifies the directory to store print jobs and other HTTP request data.
-
ServerBin directory +
Sandboxing off
-
Specifies the directory where backends, CGIs, daemons, and filters may -be found. +
Sandboxing relaxed +
+
+
Sandboxing strict +
+
Specifies the level of security sandboxing that is applied to print filters, backends, and other child processes of the scheduler. The default is "strict". (OS X only)
-
ServerCertificate filename +
ServerBin directory
-
Specifies the encryption certificate to use. +
Specifies the directory where backends, CGIs, daemons, and filters may +be found.
-
ServerKey filename +
ServerKeychain path
-
Specifies the encryption key to use. +
Specifies the location of TLS certificates and private keys.
ServerRoot directory
@@ -171,7 +176,7 @@ or state files. The default is No.
http://localhost:631/help

Copyright

-Copyright 2007-2013 by Apple Inc. +Copyright 2007-2014 by Apple Inc. diff --git a/doc/help/ref-cups-files-conf.html.in b/doc/help/ref-cups-files-conf.html.in index 70c996f4a..4b7003a51 100644 --- a/doc/help/ref-cups-files-conf.html.in +++ b/doc/help/ref-cups-files-conf.html.in @@ -354,62 +354,55 @@ HREF="#ServerRoot">ServerRoot directory. The default request directory is /var/spool/cups.

-

ServerBin

+

CUPS 2.0Sandboxing (OS X Only)

Examples

-ServerBin /usr/lib/cups
-ServerBin /foo/bar/lib/cups
+Sandboxing off
+Sandboxing relaxed
+Sandboxing strict
 

Description

-

The ServerBin directive sets the directory for -server-run executables. If an absolute path is not provided then -it is assumed to be relative to the ServerRoot directory. The -default executable directory is /usr/lib/cups, -/usr/lib32/cups, or /usr/libexec/cups -depending on the operating system.

+

The Sandboxing directive sets the default level of security sandboxing that is applied to print filters, backend, and other child processes. The default value is strict. Sandboxing is currently only supported on OS X.

-

ServerCertificate

+

ServerBin

Examples

-ServerCertificate /etc/cups/ssl/server.crt
+ServerBin /usr/lib/cups
+ServerBin /foo/bar/lib/cups
 

Description

-

The ServerCertificate directive specifies the -location of the SSL certificate file used by the server when -negotiating encrypted connections. The certificate must not be -encrypted (password protected) since the scheduler normally runs -in the background and will be unable to ask for a password.

- -

The default certificate file is -/etc/cups/ssl/server.crt.

+

The ServerBin directive sets the directory for +server-run executables. If an absolute path is not provided then +it is assumed to be relative to the ServerRoot directory. The +default executable directory is /usr/lib/cups, +/usr/lib32/cups, or /usr/libexec/cups +depending on the operating system.

-

ServerKey

+

CUPS 2.0ServerKeychain

Examples

-ServerKey /etc/cups/ssl/server.key
+ServerKeychain /etc/cups/ssl
+ServerKeychain /Library/Keychains/system.keychain
 

Description

-

The ServerKey directive specifies the location of -the SSL private key file used by the server when negotiating -encrypted connections.

+

The ServerKeychain directive specifies the location of TLS certificates and private keys used when negotiating encrypted connections.

-

The default key file is -/etc/cups/ssl/server.crt.

+

The default keychain is system-specific.

ServerRoot

diff --git a/man/cups-files.conf.man.in b/man/cups-files.conf.man.in index c17490cf1..054227f27 100644 --- a/man/cups-files.conf.man.in +++ b/man/cups-files.conf.man.in @@ -1,18 +1,18 @@ .\" .\" "$Id$" .\" -.\" cupsd.conf man page for CUPS. +.\" cupsd.conf man page for CUPS. .\" -.\" Copyright 2007-2013 by Apple Inc. -.\" Copyright 1997-2006 by Easy Software Products. +.\" Copyright 2007-2014 by Apple Inc. +.\" Copyright 1997-2006 by Easy Software Products. .\" -.\" These coded instructions, statements, and computer programs are the -.\" property of Apple Inc. and are protected by Federal copyright -.\" law. Distribution and use rights are outlined in the file "LICENSE.txt" -.\" which should have been included with this file. If this file is -.\" file is missing or damaged, see the license at "http://www.cups.org/". +.\" These coded instructions, statements, and computer programs are the +.\" property of Apple Inc. and are protected by Federal copyright +.\" law. Distribution and use rights are outlined in the file "LICENSE.txt" +.\" which should have been included with this file. If this file is +.\" file is missing or damaged, see the license at "http://www.cups.org/". .\" -.TH cups-files.conf 5 "CUPS" "26 July 2013" "Apple Inc." +.TH cups-files.conf 5 "CUPS" "6 February 2014" "Apple Inc." .SH NAME cups-files.conf \- file and directory configuration file for cups .SH DESCRIPTION @@ -105,18 +105,21 @@ RequestRoot directory Specifies the directory to store print jobs and other HTTP request data. .TP 5 +Sandboxing off +.TP 5 +Sandboxing relaxed +.TP 5 +Sandboxing strict +Specifies the level of security sandboxing that is applied to print filters, backends, and other child processes of the scheduler. The default is "strict". (OS X only) +.TP 5 ServerBin directory .br Specifies the directory where backends, CGIs, daemons, and filters may be found. .TP 5 -ServerCertificate filename -.br -Specifies the encryption certificate to use. -.TP 5 -ServerKey filename +ServerKeychain path .br -Specifies the encryption key to use. +Specifies the location of TLS certificates and private keys. .TP 5 ServerRoot directory .br @@ -146,7 +149,7 @@ Specifies the user name or ID that is used when running external programs. .br http://localhost:631/help .SH COPYRIGHT -Copyright 2007-2013 by Apple Inc. +Copyright 2007-2014 by Apple Inc. .\" .\" End of "$Id$". .\" diff --git a/scheduler/conf.c b/scheduler/conf.c index ebd065b76..123f775d6 100644 --- a/scheduler/conf.c +++ b/scheduler/conf.c @@ -3,7 +3,7 @@ * * Configuration routines for the CUPS scheduler. * - * Copyright 2007-2013 by Apple Inc. + * Copyright 2007-2014 by Apple Inc. * Copyright 1997-2007 by Easy Software Products, all rights reserved. * * These coded instructions, statements, and computer programs are the @@ -707,6 +707,7 @@ cupsdReadConfiguration(void) NumSystemGroups = 0; ReloadTimeout = DEFAULT_KEEPALIVE; RootCertDuration = 300; + Sandboxing = CUPSD_SANDBOXING_STRICT; StrictConformance = FALSE; SyncOnClose = FALSE; Timeout = DEFAULT_TIMEOUT; @@ -3419,6 +3420,30 @@ read_cups_files_conf(cups_file_t *fp) /* I - File to read from */ return (0); } } + else if (!_cups_strcasecmp(line, "Sandboxing") && value) + { + /* + * Level of sandboxing? + */ + + if (!_cups_strcasecmp(value, "off")) + { + Sandboxing = CUPSD_SANDBOXING_OFF; + cupsdLogMessage(CUPSD_LOG_WARN, "Disabling sandboxing is not recommended (line %d of %s)", linenum, CupsFilesFile); + } + else if (!_cups_strcasecmp(value, "relaxed")) + Sandboxing = CUPSD_SANDBOXING_RELAXED; + else if (!_cups_strcasecmp(value, "strict")) + Sandboxing = CUPSD_SANDBOXING_STRICT; + else + { + cupsdLogMessage(CUPSD_LOG_ERROR, + "Unknown Sandboxing \"%s\" on line %d of %s.", + value, linenum, CupsFilesFile); + if (FatalErrors & CUPSD_FATAL_CONFIG) + return (0); + } + } else if (!_cups_strcasecmp(line, "SystemGroup") && value) { /* diff --git a/scheduler/conf.h b/scheduler/conf.h index 949eb8bbe..9d3caa2c4 100644 --- a/scheduler/conf.h +++ b/scheduler/conf.h @@ -50,6 +50,13 @@ typedef enum CUPSD_TIME_USECS /* Standard format with microseconds */ } cupsd_time_t; +typedef enum +{ + CUPSD_SANDBOXING_OFF, /* No sandboxing */ + CUPSD_SANDBOXING_RELAXED, /* Relaxed sandboxing */ + CUPSD_SANDBOXING_STRICT /* Strict sandboxing */ +} cupsd_sandboxing_t; + /* * FatalErrors flags... @@ -174,6 +181,10 @@ VAR cupsd_loglevel_t LogLevel VALUE(CUPSD_LOG_WARN); /* Error log level */ VAR cupsd_time_t LogTimeFormat VALUE(CUPSD_TIME_STANDARD); /* Log file time format */ +VAR cupsd_sandboxing_t Sandboxing VALUE(CUPSD_SANDBOXING_STRICT); + /* Sandboxing level */ +VAR int UseSandboxing VALUE(1); + /* Use sandboxing for child procs? */ VAR int MaxClients VALUE(100), /* Maximum number of clients */ MaxClientsPerHost VALUE(0), diff --git a/scheduler/cups-exec.c b/scheduler/cups-exec.c index 0d8a764d7..ecbc6bbc6 100644 --- a/scheduler/cups-exec.c +++ b/scheduler/cups-exec.c @@ -21,6 +21,7 @@ */ #include +#include #include #include #include @@ -66,21 +67,6 @@ main(int argc, /* I - Number of command-line args */ fcntl(3, F_SETFL, O_NDELAY); fcntl(4, F_SETFL, O_NDELAY); -#ifdef HAVE_SANDBOX_H - /* - * Run in a separate security profile... - */ - - if (strcmp(argv[1], "none") && - sandbox_init(argv[1], SANDBOX_NAMED_EXTERNAL, &sandbox_error)) - { - fprintf(stderr, "DEBUG: sandbox_init failed: %s (%s)\n", sandbox_error, - strerror(errno)); - sandbox_free_error(sandbox_error); - return (1); - } -#endif /* HAVE_SANDBOX_H */ - /* * Change UID, GID, and nice value... */ @@ -106,18 +92,42 @@ main(int argc, /* I - Number of command-line args */ umask(077); +#ifdef HAVE_SANDBOX_H /* - * Execute the program... + * Run in a separate security profile... */ - execv(argv[5], argv + 6); + if (strcmp(argv[1], "none") && + sandbox_init(argv[1], SANDBOX_NAMED_EXTERNAL, &sandbox_error)) + { + cups_file_t *fp; /* File */ + char line[1024]; /* Line from file */ + int linenum = 0; /* Line number in file */ + + fprintf(stderr, "DEBUG: sandbox_init failed: %s (%s)\n", sandbox_error, + strerror(errno)); + sandbox_free_error(sandbox_error); + + if ((fp = cupsFileOpen(argv[1], "r")) != NULL) + { + while (cupsFileGets(fp, line, sizeof(line))) + { + linenum ++; + fprintf(stderr, "DEBUG: %4d %s\n", linenum, line); + } + cupsFileClose(fp); + } + + return (100 + EINVAL); + } +#endif /* HAVE_SANDBOX_H */ /* * If we get here, execv() failed... */ fprintf(stderr, "DEBUG: execv failed: %s\n", strerror(errno)); - return (1); + return (errno + 100); } diff --git a/scheduler/cupsd.h b/scheduler/cupsd.h index ddd642b8d..128066246 100644 --- a/scheduler/cupsd.h +++ b/scheduler/cupsd.h @@ -1,16 +1,16 @@ /* * "$Id$" * - * Main header file for the CUPS scheduler. + * Main header file for the CUPS scheduler. * - * Copyright 2007-2013 by Apple Inc. - * Copyright 1997-2007 by Easy Software Products, all rights reserved. + * Copyright 2007-2014 by Apple Inc. + * Copyright 1997-2007 by Easy Software Products, all rights reserved. * - * These coded instructions, statements, and computer programs are the - * property of Apple Inc. and are protected by Federal copyright - * law. Distribution and use rights are outlined in the file "LICENSE.txt" - * "LICENSE" which should have been included with this file. If this - * file is missing or damaged, see the license at "http://www.cups.org/". + * These coded instructions, statements, and computer programs are the + * property of Apple Inc. and are protected by Federal copyright + * law. Distribution and use rights are outlined in the file "LICENSE.txt" + * "LICENSE" which should have been included with this file. If this + * file is missing or damaged, see the license at "http://www.cups.org/". */ @@ -144,10 +144,8 @@ typedef void (*cupsd_selfunc_t)(void *data); * Globals... */ -VAR int TestConfigFile VALUE(0), +VAR int TestConfigFile VALUE(0); /* Test the cupsd.conf file? */ - UseProfiles VALUE(1); - /* Use security profiles for child procs? */ VAR int MaxFDs VALUE(0); /* Maximum number of files */ @@ -203,7 +201,7 @@ extern void cupsdSetStringf(char **s, const char *f, ...) __attribute__ ((__format__ (__printf__, 2, 3))); /* process.c */ -extern void *cupsdCreateProfile(int job_id); +extern void *cupsdCreateProfile(int job_id, int allow_networking); extern void cupsdDestroyProfile(void *profile); extern int cupsdEndProcess(int pid, int force); extern const char *cupsdFinishProcess(int pid, char *name, int namelen, diff --git a/scheduler/job.c b/scheduler/job.c index 42a39bf65..2af8785ce 100644 --- a/scheduler/job.c +++ b/scheduler/job.c @@ -1218,7 +1218,7 @@ cupsdContinueJob(cupsd_job_t *job) /* I - Job */ pid = cupsdStartProcess(command, argv, envp, filterfds[!slot][0], filterfds[slot][1], job->status_pipes[1], job->back_pipes[1], job->side_pipes[1], - backroot, job->profile, job, &(job->backend)); + backroot, job->bprofile, job, &(job->backend)); if (pid == 0) { @@ -2963,6 +2963,8 @@ finalize_job(cupsd_job_t *job, /* I - Job */ cupsdDestroyProfile(job->profile); job->profile = NULL; + cupsdDestroyProfile(job->bprofile); + job->bprofile = NULL; /* * Clear the unresponsive job watchdog timers... @@ -4504,8 +4506,9 @@ start_job(cupsd_job_t *job, /* I - Job ID */ * Setup the last exit status and security profiles... */ - job->status = 0; - job->profile = cupsdCreateProfile(job->id); + job->status = 0; + job->profile = cupsdCreateProfile(job->id, 0); + job->bprofile = cupsdCreateProfile(job->id, 1); /* * Create the status pipes and buffer... @@ -4522,6 +4525,8 @@ start_job(cupsd_job_t *job, /* I - Job ID */ cupsdDestroyProfile(job->profile); job->profile = NULL; + cupsdDestroyProfile(job->bprofile); + job->bprofile = NULL; return; } @@ -4547,6 +4552,8 @@ start_job(cupsd_job_t *job, /* I - Job ID */ cupsdDestroyProfile(job->profile); job->profile = NULL; + cupsdDestroyProfile(job->bprofile); + job->bprofile = NULL; return; } @@ -4576,6 +4583,8 @@ start_job(cupsd_job_t *job, /* I - Job ID */ cupsdDestroyProfile(job->profile); job->profile = NULL; + cupsdDestroyProfile(job->bprofile); + job->bprofile = NULL; return; } diff --git a/scheduler/job.h b/scheduler/job.h index 29032263b..d13bb97b3 100644 --- a/scheduler/job.h +++ b/scheduler/job.h @@ -78,7 +78,8 @@ struct cupsd_job_s /**** Job request ****/ char *auth_env[3], /* AUTH_xxx environment variables, * if any */ *auth_uid; /* AUTH_UID environment variable */ - void *profile; /* Security profile */ + void *profile, /* Security profile for filters */ + *bprofile; /* Security profile for backend */ cups_array_t *history; /* Debug log history */ int progress; /* Printing progress */ int num_keywords; /* Number of PPD keywords */ diff --git a/scheduler/main.c b/scheduler/main.c index 162c4df48..2cd89c996 100644 --- a/scheduler/main.c +++ b/scheduler/main.c @@ -243,9 +243,8 @@ main(int argc, /* I - Number of command-line args */ break; case 'P' : /* Disable security profiles */ - fputs("cupsd: -P (disable security profiles) is for internal " - "testing use only!\n", stderr); - UseProfiles = 0; + fputs("cupsd: -P (disable sandboxing) is for internal testing use only.\n", stderr); + UseSandboxing = 0; break; case 's' : /* Set cups-files.conf location */ diff --git a/scheduler/process.c b/scheduler/process.c index 97da1eaa2..e01f639c8 100644 --- a/scheduler/process.c +++ b/scheduler/process.c @@ -62,34 +62,36 @@ static char *cupsd_requote(char *dst, const char *src, size_t dstsize); */ void * /* O - Profile or NULL on error */ -cupsdCreateProfile(int job_id) /* I - Job ID or 0 for none */ +cupsdCreateProfile(int job_id, /* I - Job ID or 0 for none */ + int allow_networking)/* I - Allow networking off machine? */ { #ifdef HAVE_SANDBOX_H - cups_file_t *fp; /* File pointer */ - char profile[1024], /* File containing the profile */ - cache[1024], /* Quoted CacheDir */ - request[1024], /* Quoted RequestRoot */ - root[1024], /* Quoted ServerRoot */ - temp[1024]; /* Quoted TempDir */ - const char *nodebug; /* " (with no-log)" for no debug */ - - - if (!UseProfiles) + cups_file_t *fp; /* File pointer */ + char profile[1024], /* File containing the profile */ + bin[1024], /* Quoted ServerBin */ + cache[1024], /* Quoted CacheDir */ + domain[1024], /* Domain socket, if any */ + request[1024], /* Quoted RequestRoot */ + root[1024], /* Quoted ServerRoot */ + temp[1024]; /* Quoted TempDir */ + const char *nodebug; /* " (with no-log)" for no debug */ + cupsd_listener_t *lis; /* Current listening socket */ + + + if (!UseSandboxing || Sandboxing == CUPSD_SANDBOXING_OFF) { /* * Only use sandbox profiles as root... */ - cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdCreateProfile(job_id=%d) = NULL", - job_id); + cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdCreateProfile(job_id=%d, allow_networking=%d) = NULL", job_id, allow_networking); return (NULL); } if ((fp = cupsTempFile2(profile, sizeof(profile))) == NULL) { - cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdCreateProfile(job_id=%d) = NULL", - job_id); + cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdCreateProfile(job_id=%d, allow_networking=%d) = NULL", job_id, allow_networking); cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to create security profile: %s", strerror(errno)); return (NULL); @@ -98,6 +100,7 @@ cupsdCreateProfile(int job_id) /* I - Job ID or 0 for none */ fchown(cupsFileNumber(fp), RunUser, Group); fchmod(cupsFileNumber(fp), 0640); + cupsd_requote(bin, ServerBin, sizeof(bin)); cupsd_requote(cache, CacheDir, sizeof(cache)); cupsd_requote(request, RequestRoot, sizeof(request)); cupsd_requote(root, ServerRoot, sizeof(root)); @@ -106,10 +109,22 @@ cupsdCreateProfile(int job_id) /* I - Job ID or 0 for none */ nodebug = LogLevel < CUPSD_LOG_DEBUG ? " (with no-log)" : ""; cupsFilePuts(fp, "(version 1)\n"); - cupsFilePuts(fp, "(allow default)\n"); + if (Sandboxing == CUPSD_SANDBOXING_STRICT) + cupsFilePuts(fp, "(deny default)\n"); + else + cupsFilePuts(fp, "(allow default)\n"); + if (LogLevel >= CUPSD_LOG_DEBUG) + cupsFilePuts(fp, "(debug deny)\n"); + cupsFilePuts(fp, "(import \"system.sb\")\n"); + cupsFilePuts(fp, "(system-network)\n"); + cupsFilePuts(fp, "(allow mach-per-user-lookup)\n"); + cupsFilePuts(fp, "(allow ipc-posix-sem)\n"); + cupsFilePuts(fp, "(allow ipc-posix-shm)\n"); + cupsFilePuts(fp, "(allow ipc-sysv-shm)\n"); + cupsFilePuts(fp, "(allow mach-lookup)\n"); cupsFilePrintf(fp, - "(deny file-write* file-read-data file-read-metadata\n" - " (regex" + "(deny file-write* file-read-data file-read-metadata\n" + " (regex" " #\"^%s$\"" /* RequestRoot */ " #\"^%s/\"" /* RequestRoot/... */ ")%s)\n", @@ -136,13 +151,18 @@ cupsdCreateProfile(int job_id) /* I - Job ID or 0 for none */ " #\"^/System/\"" ")%s)\n", root, root, nodebug); - /* Specifically allow applications to stat RequestRoot */ + /* Specifically allow applications to stat RequestRoot and some other system folders */ cupsFilePrintf(fp, "(allow file-read-metadata\n" " (regex" + " #\"^/$\"" /* / */ + " #\"^/usr$\"" /* /usr */ + " #\"^/Library$\"" /* /Library */ + " #\"^/Library/Printers$\"" /* /Library/Printers */ " #\"^%s$\"" /* RequestRoot */ "))\n", request); + /* Read and write TempDir, CacheDir, and other common folders */ cupsFilePrintf(fp, "(allow file-write* file-read-data file-read-metadata\n" " (regex" @@ -150,29 +170,93 @@ cupsdCreateProfile(int job_id) /* I - Job ID or 0 for none */ " #\"^%s/\"" /* TempDir/... */ " #\"^%s$\"" /* CacheDir */ " #\"^%s/\"" /* CacheDir/... */ - " #\"^%s/Library$\"" /* RequestRoot/Library */ - " #\"^%s/Library/\"" /* RequestRoot/Library/... */ + " #\"^/private/var/folders/\"" " #\"^/Library/Application Support/\"" " #\"^/Library/Caches/\"" " #\"^/Library/Preferences/\"" - " #\"^/Library/Printers/.*/\"" " #\"^/Users/Shared/\"" "))\n", - temp, temp, cache, cache, request, request); + temp, temp, cache, cache); + /* Read common folders */ cupsFilePrintf(fp, - "(deny file-write*\n" + "(allow file-read-data file-read-metadata\n" + " (literal \"/private/etc/services\")\n" + " (regex" + " #\"^/bin$\"" /* /bin */ + " #\"^/bin/\"" /* /bin/... */ + " #\"^/usr/bin$\"" /* /usr/bin */ + " #\"^/usr/bin/\"" /* /usr/bin/... */ + " #\"^/usr/libexec/cups$\"" /* /usr/libexec/cups */ + " #\"^/usr/libexec/cups/\"" /* /usr/libexec/cups/... */ + " #\"^/usr/sbin$\"" /* /usr/sbin */ + " #\"^/usr/sbin/\"" /* /usr/sbin/... */ + " #\"^/Library/Caches$\"" + " #\"^/Library/Fonts$\"" + " #\"^/Library/Fonts/\"" + " #\"^/Library/Printers$\"" + " #\"^/Library/Printers/.*$\"" + " #\"^%s/Library$\"" /* RequestRoot/Library */ + " #\"^%s/Library/\"" /* RequestRoot/Library/... */ + " #\"^%s$\"" /* ServerBin */ + " #\"^%s/\"" /* ServerBin/... */ + " #\"^%s$\"" /* ServerRoot */ + " #\"^%s/\"" /* ServerRoot/... */ + "))\n", + request, request, bin, bin, root, root); + if (Sandboxing == CUPSD_SANDBOXING_RELAXED) + { + /* Limited write access to /Library/Printers/... */ + cupsFilePuts(fp, + "(allow file-write*\n" " (regex" - " #\"^/Library/Printers/PPDs$\"" - " #\"^/Library/Printers/PPDs/\"" - " #\"^/Library/Printers/PPD Plugins$\"" - " #\"^/Library/Printers/PPD Plugins/\"" - ")%s)\n", nodebug); - if (job_id) + " #\"^/Library/Printers/.*/\"" + "))\n"); + cupsFilePrintf(fp, + "(deny file-write*\n" + " (regex" + " #\"^/Library/Printers/PPDs$\"" + " #\"^/Library/Printers/PPDs/\"" + " #\"^/Library/Printers/PPD Plugins$\"" + " #\"^/Library/Printers/PPD Plugins/\"" + ")%s)\n", nodebug); + } + /* Allow execution of child processes */ + cupsFilePuts(fp, "(allow process-fork)\n"); + cupsFilePrintf(fp, + "(allow process-exec\n" + " (regex" + " #\"^/bin/\"" /* /bin/... */ + " #\"^/usr/bin/\"" /* /usr/bin/... */ + " #\"^/usr/libexec/cups/\"" /* /usr/libexec/cups/... */ + " #\"^/usr/sbin/\"" /* /usr/sbin/... */ + " #\"^%s/\"" /* ServerBin/... */ + " #\"^/Library/Printers/.*/\"" + "))\n", + bin); + if (RunUser && getenv("CUPS_TESTROOT")) { - /* - * Allow job filters to read the spool file(s)... - */ + /* Allow source directory access in "make test" environment */ + char testroot[1024]; /* Root directory of test files */ + cupsd_requote(testroot, getenv("CUPS_TESTROOT"), sizeof(testroot)); + + cupsFilePrintf(fp, + "(allow file-write* file-read-data file-read-metadata\n" + " (regex" + " #\"^%s$\"" /* CUPS_TESTROOT */ + " #\"^%s/\"" /* CUPS_TESTROOT/... */ + "))\n", + testroot, testroot); + cupsFilePrintf(fp, + "(allow process-exec\n" + " (regex" + " #\"^%s/\"" /* CUPS_TESTROOT/... */ + "))\n", + testroot); + } + if (job_id) + { + /* Allow job filters to read the current job files... */ cupsFilePrintf(fp, "(allow file-read-data file-read-metadata\n" " (regex #\"^%s/([ac]%05d|d%05d-[0-9][0-9][0-9])$\"))\n", @@ -180,26 +264,49 @@ cupsdCreateProfile(int job_id) /* I - Job ID or 0 for none */ } else { - /* - * Allow email notifications from notifiers... - */ - + /* Allow email notifications from notifiers... */ cupsFilePuts(fp, "(allow process-exec\n" " (literal \"/usr/sbin/sendmail\")\n" - " (with no-sandbox)\n" - ")\n"); + " (with no-sandbox))\n"); + } + /* Allow outbound networking to local mDNSResponder and cupsd */ + cupsFilePuts(fp, "(allow network-outbound" + "\n (literal \"/private/var/run/mDNSResponder\")"); + for (lis = (cupsd_listener_t *)cupsArrayFirst(Listeners); + lis; + lis = (cupsd_listener_t *)cupsArrayNext(Listeners)) + { + if (httpAddrFamily(&(lis->address)) == AF_LOCAL) + { + httpAddrString(&(lis->address), domain, sizeof(domain)); + cupsFilePrintf(fp, "\n (literal \"%s\")", domain); + } + } + if (allow_networking) + { + /* Allow TCP and UDP networking off the machine... */ + cupsFilePuts(fp, "\n (remote tcp))\n"); + cupsFilePuts(fp, "(allow network*\n" + " (local udp \"*:*\")\n" + " (remote udp \"*:*\"))\n"); + } + else + { + /* Only allow SNMP (UDP) off the machine... */ + cupsFilePuts(fp, ")\n"); + cupsFilePuts(fp, "(allow network-outbound\n" + " (remote udp \"*:161\"))\n"); + cupsFilePuts(fp, "(allow network-inbound\n" + " (local udp \"localhost:*\"))\n"); } - cupsFileClose(fp); - cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdCreateProfile(job_id=%d) = \"%s\"", - job_id, profile); + cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdCreateProfile(job_id=%d,allow_networking=%d) = \"%s\"", job_id, allow_networking, profile); return ((void *)strdup(profile)); #else - cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdCreateProfile(job_id=%d) = NULL", - job_id); + cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdCreateProfile(job_id=%d, allow_networking=%d) = NULL", job_id, allow_networking); return (NULL); #endif /* HAVE_SANDBOX_H */ @@ -402,7 +509,7 @@ cupsdStartProcess( #endif /* !HAVE_POSIX_SPAWN */ { snprintf(cups_exec, sizeof(cups_exec), "%s/daemon/cups-exec", ServerBin); - snprintf(user_str, sizeof(user_str), "%d", User); + snprintf(user_str, sizeof(user_str), "%d", user); snprintf(group_str, sizeof(group_str), "%d", Group); snprintf(nice_str, sizeof(nice_str), "%d", FilterNice); diff --git a/scheduler/server.c b/scheduler/server.c index 3dc580e53..a83e7c40d 100644 --- a/scheduler/server.c +++ b/scheduler/server.c @@ -54,7 +54,7 @@ cupsdStartServer(void) * Create the default security profile... */ - DefaultProfile = cupsdCreateProfile(0); + DefaultProfile = cupsdCreateProfile(0, 1); /* * Startup all the networking stuff... diff --git a/test/run-stp-tests.sh b/test/run-stp-tests.sh index af8d59467..8569bf45f 100755 --- a/test/run-stp-tests.sh +++ b/test/run-stp-tests.sh @@ -2,17 +2,17 @@ # # "$Id$" # -# Perform the complete set of IPP compliance tests specified in the -# CUPS Software Test Plan. +# Perform the complete set of IPP compliance tests specified in the +# CUPS Software Test Plan. # -# Copyright 2007-2013 by Apple Inc. -# Copyright 1997-2007 by Easy Software Products, all rights reserved. +# Copyright 2007-2014 by Apple Inc. +# Copyright 1997-2007 by Easy Software Products, all rights reserved. # -# These coded instructions, statements, and computer programs are the -# property of Apple Inc. and are protected by Federal copyright -# law. Distribution and use rights are outlined in the file "LICENSE.txt" -# which should have been included with this file. If this file is -# file is missing or damaged, see the license at "http://www.cups.org/". +# These coded instructions, statements, and computer programs are the +# property of Apple Inc. and are protected by Federal copyright +# law. Distribution and use rights are outlined in the file "LICENSE.txt" +# which should have been included with this file. If this file is +# file is missing or damaged, see the license at "http://www.cups.org/". # argcount=$# @@ -192,6 +192,13 @@ fi port=8631 cwd=`pwd` root=`dirname $cwd` +CUPS_TESTROOT="$root"; export CUPS_TESTROOT + +if test -d /private/tmp; then + BASE=/private/tmp/cups-$user +else + BASE=/tmp/cups-$user +fi # # Make sure that the LPDEST and PRINTER environment variables are @@ -223,12 +230,12 @@ echo "" case "$usevalgrind" in Y* | y*) - VALGRIND="valgrind --tool=memcheck --log-file=/tmp/cups-$user/log/valgrind.%p --error-limit=no --leak-check=yes --trace-children=yes --read-var-info=yes" + VALGRIND="valgrind --tool=memcheck --log-file=$BASE/log/valgrind.%p --error-limit=no --leak-check=yes --trace-children=yes --read-var-info=yes" if test `uname` = Darwin; then VALGRIND="$VALGRIND --dsymutil=yes" fi export VALGRIND - echo "Using Valgrind; log files can be found in /tmp/cups-$user/log..." + echo "Using Valgrind; log files can be found in $BASE/log..." ;; *) @@ -257,15 +264,15 @@ echo "" case "$usedebugprintfs" in Y* | y*) - echo "Enabling debug printfs (level 5); log files can be found in /tmp/cups-$user/log..." - CUPS_DEBUG_LOG="/tmp/cups-$user/log/debug_printfs.%d"; export CUPS_DEBUG_LOG + echo "Enabling debug printfs (level 5); log files can be found in $BASE/log..." + CUPS_DEBUG_LOG="$BASE/log/debug_printfs.%d"; export CUPS_DEBUG_LOG CUPS_DEBUG_LEVEL=5; export CUPS_DEBUG_LEVEL CUPS_DEBUG_FILTER='^(http|_http|ipp|_ipp|cups.*Request|cupsGetResponse|cupsSend).*$'; export CUPS_DEBUG_FILTER ;; 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9) - echo "Enabling debug printfs (level $usedebugprintfs); log files can be found in /tmp/cups-$user/log..." - CUPS_DEBUG_LOG="/tmp/cups-$user/log/debug_printfs.%d"; export CUPS_DEBUG_LOG + echo "Enabling debug printfs (level $usedebugprintfs); log files can be found in $BASE/log..." + CUPS_DEBUG_LOG="$BASE/log/debug_printfs.%d"; export CUPS_DEBUG_LOG CUPS_DEBUG_LEVEL="$usedebugprintfs"; export CUPS_DEBUG_LEVEL CUPS_DEBUG_FILTER='^(http|_http|ipp|_ipp|cups.*Request|cupsGetResponse|cupsSend).*$'; export CUPS_DEBUG_FILTER ;; @@ -280,67 +287,67 @@ esac echo "Creating directories for test..." -rm -rf /tmp/cups-$user -mkdir /tmp/cups-$user -mkdir /tmp/cups-$user/bin -mkdir /tmp/cups-$user/bin/backend -mkdir /tmp/cups-$user/bin/driver -mkdir /tmp/cups-$user/bin/filter -mkdir /tmp/cups-$user/certs -mkdir /tmp/cups-$user/share -mkdir /tmp/cups-$user/share/banners -mkdir /tmp/cups-$user/share/drv -mkdir /tmp/cups-$user/share/locale +rm -rf $BASE +mkdir $BASE +mkdir $BASE/bin +mkdir $BASE/bin/backend +mkdir $BASE/bin/driver +mkdir $BASE/bin/filter +mkdir $BASE/certs +mkdir $BASE/share +mkdir $BASE/share/banners +mkdir $BASE/share/drv +mkdir $BASE/share/locale for file in ../locale/cups_*.po; do loc=`basename $file .po | cut -c 6-` - mkdir /tmp/cups-$user/share/locale/$loc - ln -s $root/locale/cups_$loc.po /tmp/cups-$user/share/locale/$loc - ln -s $root/locale/ppdc_$loc.po /tmp/cups-$user/share/locale/$loc + mkdir $BASE/share/locale/$loc + ln -s $root/locale/cups_$loc.po $BASE/share/locale/$loc + ln -s $root/locale/ppdc_$loc.po $BASE/share/locale/$loc done -mkdir /tmp/cups-$user/share/mime -mkdir /tmp/cups-$user/share/model -mkdir /tmp/cups-$user/share/ppdc -mkdir /tmp/cups-$user/interfaces -mkdir /tmp/cups-$user/log -mkdir /tmp/cups-$user/ppd -mkdir /tmp/cups-$user/spool -mkdir /tmp/cups-$user/spool/temp -mkdir /tmp/cups-$user/ssl - -ln -s $root/backend/dnssd /tmp/cups-$user/bin/backend -ln -s $root/backend/http /tmp/cups-$user/bin/backend -ln -s $root/backend/ipp /tmp/cups-$user/bin/backend -ln -s $root/backend/lpd /tmp/cups-$user/bin/backend -ln -s $root/backend/mdns /tmp/cups-$user/bin/backend -ln -s $root/backend/pseudo /tmp/cups-$user/bin/backend -ln -s $root/backend/snmp /tmp/cups-$user/bin/backend -ln -s $root/backend/socket /tmp/cups-$user/bin/backend -ln -s $root/backend/usb /tmp/cups-$user/bin/backend -ln -s $root/cgi-bin /tmp/cups-$user/bin -ln -s $root/monitor /tmp/cups-$user/bin -ln -s $root/notifier /tmp/cups-$user/bin -ln -s $root/scheduler /tmp/cups-$user/bin/daemon -ln -s $root/filter/commandtops /tmp/cups-$user/bin/filter -ln -s $root/filter/gziptoany /tmp/cups-$user/bin/filter -ln -s $root/filter/pstops /tmp/cups-$user/bin/filter -ln -s $root/filter/rastertoepson /tmp/cups-$user/bin/filter -ln -s $root/filter/rastertohp /tmp/cups-$user/bin/filter -ln -s $root/filter/rastertolabel /tmp/cups-$user/bin/filter -ln -s $root/filter/rastertopwg /tmp/cups-$user/bin/filter - -ln -s $root/data/classified /tmp/cups-$user/share/banners -ln -s $root/data/confidential /tmp/cups-$user/share/banners -ln -s $root/data/secret /tmp/cups-$user/share/banners -ln -s $root/data/standard /tmp/cups-$user/share/banners -ln -s $root/data/topsecret /tmp/cups-$user/share/banners -ln -s $root/data/unclassified /tmp/cups-$user/share/banners -ln -s $root/data /tmp/cups-$user/share -ln -s $root/ppdc/sample.drv /tmp/cups-$user/share/drv -ln -s $root/conf/mime.types /tmp/cups-$user/share/mime -ln -s $root/conf/mime.convs /tmp/cups-$user/share/mime -ln -s $root/data/*.h /tmp/cups-$user/share/ppdc -ln -s $root/data/*.defs /tmp/cups-$user/share/ppdc -ln -s $root/templates /tmp/cups-$user/share +mkdir $BASE/share/mime +mkdir $BASE/share/model +mkdir $BASE/share/ppdc +mkdir $BASE/interfaces +mkdir $BASE/log +mkdir $BASE/ppd +mkdir $BASE/spool +mkdir $BASE/spool/temp +mkdir $BASE/ssl + +ln -s $root/backend/dnssd $BASE/bin/backend +ln -s $root/backend/http $BASE/bin/backend +ln -s $root/backend/ipp $BASE/bin/backend +ln -s $root/backend/lpd $BASE/bin/backend +ln -s $root/backend/mdns $BASE/bin/backend +ln -s $root/backend/pseudo $BASE/bin/backend +ln -s $root/backend/snmp $BASE/bin/backend +ln -s $root/backend/socket $BASE/bin/backend +ln -s $root/backend/usb $BASE/bin/backend +ln -s $root/cgi-bin $BASE/bin +ln -s $root/monitor $BASE/bin +ln -s $root/notifier $BASE/bin +ln -s $root/scheduler $BASE/bin/daemon +ln -s $root/filter/commandtops $BASE/bin/filter +ln -s $root/filter/gziptoany $BASE/bin/filter +ln -s $root/filter/pstops $BASE/bin/filter +ln -s $root/filter/rastertoepson $BASE/bin/filter +ln -s $root/filter/rastertohp $BASE/bin/filter +ln -s $root/filter/rastertolabel $BASE/bin/filter +ln -s $root/filter/rastertopwg $BASE/bin/filter + +ln -s $root/data/classified $BASE/share/banners +ln -s $root/data/confidential $BASE/share/banners +ln -s $root/data/secret $BASE/share/banners +ln -s $root/data/standard $BASE/share/banners +ln -s $root/data/topsecret $BASE/share/banners +ln -s $root/data/unclassified $BASE/share/banners +ln -s $root/data $BASE/share +ln -s $root/ppdc/sample.drv $BASE/share/drv +ln -s $root/conf/mime.types $BASE/share/mime +ln -s $root/conf/mime.convs $BASE/share/mime +ln -s $root/data/*.h $BASE/share/ppdc +ln -s $root/data/*.defs $BASE/share/ppdc +ln -s $root/templates $BASE/share # # Local filters and configuration files... @@ -358,7 +365,7 @@ instfilter() { for dir in /usr/libexec/cups/filter /usr/lib/cups/filter; do if test -x "$dir/$src"; then - ln -s "$dir/$src" "/tmp/cups-$user/bin/filter/$dst" + ln -s "$dir/$src" "$BASE/bin/filter/$dst" return fi done @@ -366,10 +373,10 @@ instfilter() { # Source filter not present, create a dummy filter case $format in passthru) - ln -s gziptoany "/tmp/cups-$user/bin/filter/$dst" + ln -s gziptoany "$BASE/bin/filter/$dst" ;; pdf) - cat >"/tmp/cups-$user/bin/filter/$dst" <"$BASE/bin/filter/$dst" <"/tmp/cups-$user/bin/filter/$dst" <"$BASE/bin/filter/$dst" <"/tmp/cups-$user/bin/filter/$dst" <"$BASE/bin/filter/$dst" </tmp/cups-$user/cupsd.conf <$BASE/cupsd.conf <>/tmp/cups-$user/cupsd.conf + echo WebInterface yes >>$BASE/cupsd.conf fi -cat >/tmp/cups-$user/cups-files.conf <$BASE/cups-files.conf <> /tmp/cups-$user/cups-files.conf + echo "ServerKeychain $HOME/Library/Keychains/login.keychain" >> $BASE/cups-files.conf fi # @@ -507,7 +514,7 @@ echo "Creating printers.conf for test..." i=1 while test $i -le $nprinters1; do - cat >>/tmp/cups-$user/printers.conf <>$BASE/printers.conf < Accepting Yes DeviceURI file:/dev/null @@ -519,13 +526,13 @@ StateMessage Printer $1 is idle. EOF - cp testps.ppd /tmp/cups-$user/ppd/test-$i.ppd + cp testps.ppd $BASE/ppd/test-$i.ppd i=`expr $i + 1` done while test $i -le $nprinters2; do - cat >>/tmp/cups-$user/printers.conf <>$BASE/printers.conf < Accepting Yes DeviceURI file:/dev/null @@ -540,10 +547,10 @@ EOF i=`expr $i + 1` done -if test -f /tmp/cups-$user/printers.conf; then - cp /tmp/cups-$user/printers.conf /tmp/cups-$user/printers.conf.orig +if test -f $BASE/printers.conf; then + cp $BASE/printers.conf $BASE/printers.conf.orig else - touch /tmp/cups-$user/printers.conf.orig + touch $BASE/printers.conf.orig fi # @@ -584,16 +591,16 @@ export SHLIB_PATH CUPS_DISABLE_APPLE_DEFAULT=yes; export CUPS_DISABLE_APPLE_DEFAULT CUPS_SERVER=localhost:8631; export CUPS_SERVER -CUPS_SERVERROOT=/tmp/cups-$user; export CUPS_SERVERROOT -CUPS_STATEDIR=/tmp/cups-$user; export CUPS_STATEDIR -CUPS_DATADIR=/tmp/cups-$user/share; export CUPS_DATADIR -LOCALEDIR=/tmp/cups-$user/share/locale; export LOCALEDIR +CUPS_SERVERROOT=$BASE; export CUPS_SERVERROOT +CUPS_STATEDIR=$BASE; export CUPS_STATEDIR +CUPS_DATADIR=$BASE/share; export CUPS_DATADIR +LOCALEDIR=$BASE/share/locale; export LOCALEDIR # # Set a new home directory to avoid getting user options mixed in... # -HOME=/tmp/cups-$user +HOME=$BASE export HOME # @@ -611,14 +618,14 @@ export LC_MESSAGES # echo "Starting scheduler:" -echo " $VALGRIND ../scheduler/cupsd -c /tmp/cups-$user/cupsd.conf -f >/tmp/cups-$user/log/debug_log 2>&1 &" +echo " $VALGRIND ../scheduler/cupsd -c $BASE/cupsd.conf -f >$BASE/log/debug_log 2>&1 &" echo "" if test `uname` = Darwin -a "x$VALGRIND" = x; then DYLD_INSERT_LIBRARIES=/usr/lib/libgmalloc.dylib - ../scheduler/cupsd -c /tmp/cups-$user/cupsd.conf -f >/tmp/cups-$user/log/debug_log 2>&1 & + ../scheduler/cupsd -c $BASE/cupsd.conf -f >$BASE/log/debug_log 2>&1 & else - $VALGRIND ../scheduler/cupsd -c /tmp/cups-$user/cupsd.conf -f >/tmp/cups-$user/log/debug_log 2>&1 & + $VALGRIND ../scheduler/cupsd -c $BASE/cupsd.conf -f >$BASE/log/debug_log 2>&1 & fi cupsd=$! @@ -629,7 +636,7 @@ if test "x$testtype" = x0; then echo "" # Create a helper script to run programs with... - runcups="/tmp/cups-$user/runcups" + runcups="$BASE/runcups" echo "#!/bin/sh" >$runcups echo "# Helper script for running CUPS test instance." >>$runcups @@ -687,7 +694,7 @@ done # date=`date "+%Y-%m-%d"` -strfile=/tmp/cups-$user/cups-str-2.0-$date-$user.html +strfile=$BASE/cups-str-2.0-$date-$user.html rm -f $strfile cat str-header.html >$strfile @@ -782,7 +789,7 @@ echo "" echo "

Summary

" >>$strfile # Job control files -count=`ls -1 /tmp/cups-$user/spool | wc -l` +count=`ls -1 $BASE/spool | wc -l` count=`expr $count - 1` if test $count != 0; then echo "FAIL: $count job control files were not purged." @@ -794,7 +801,7 @@ else fi # Pages printed on Test1 (within 1 page for timing-dependent cancel issues) -count=`$GREP '^Test1 ' /tmp/cups-$user/log/page_log | awk 'BEGIN{count=0}{count=count+$7}END{print count}'` +count=`$GREP '^Test1 ' $BASE/log/page_log | awk 'BEGIN{count=0}{count=count+$7}END{print count}'` expected=`expr $pjobs \* 2 + 34` expected2=`expr $expected + 2` if test $count -lt $expected -a $count -gt $expected2; then @@ -807,7 +814,7 @@ else fi # Paged printed on Test2 -count=`$GREP '^Test2 ' /tmp/cups-$user/log/page_log | awk 'BEGIN{count=0}{count=count+$7}END{print count}'` +count=`$GREP '^Test2 ' $BASE/log/page_log | awk 'BEGIN{count=0}{count=count+$7}END{print count}'` expected=`expr $pjobs \* 2 + 3` if test $count != $expected; then echo "FAIL: Printer 'Test2' produced $count page(s), expected $expected." @@ -819,7 +826,7 @@ else fi # Paged printed on Test3 -count=`$GREP '^Test3 ' /tmp/cups-$user/log/page_log | grep -v total | awk 'BEGIN{count=0}{count=count+$7}END{print count}'` +count=`$GREP '^Test3 ' $BASE/log/page_log | grep -v total | awk 'BEGIN{count=0}{count=count+$7}END{print count}'` expected=2 if test $count != $expected; then echo "FAIL: Printer 'Test3' produced $count page(s), expected $expected." @@ -831,7 +838,7 @@ else fi # Requests logged -count=`wc -l /tmp/cups-$user/log/access_log | awk '{print $1}'` +count=`wc -l $BASE/log/access_log | awk '{print $1}'` expected=`expr 37 + 18 + 28 + $pjobs \* 8 + $pprinters \* $pjobs \* 4` if test $count != $expected; then echo "FAIL: $count requests logged, expected $expected." @@ -843,11 +850,11 @@ else fi # Did CUPS-Get-Default get logged? -if $GREP -q CUPS-Get-Default /tmp/cups-$user/log/access_log; then +if $GREP -q CUPS-Get-Default $BASE/log/access_log; then echo "FAIL: CUPS-Get-Default logged with 'AccessLogLevel actions'" echo "

FAIL: CUPS-Get-Default logged with 'AccessLogLevel actions'

" >>$strfile echo "
" >>$strfile
-	$GREP CUPS-Get-Default /tmp/cups-$user/log/access_log | sed -e '1,$s/&/&/g' -e '1,$s/>$strfile
+	$GREP CUPS-Get-Default $BASE/log/access_log | sed -e '1,$s/&/&/g' -e '1,$s/>$strfile
 	echo "
" >>$strfile fail=`expr $fail + 1` else @@ -856,13 +863,13 @@ else fi # Emergency log messages -count=`$GREP '^X ' /tmp/cups-$user/log/error_log | wc -l | awk '{print $1}'` +count=`$GREP '^X ' $BASE/log/error_log | wc -l | awk '{print $1}'` if test $count != 0; then echo "FAIL: $count emergency messages, expected 0." - $GREP '^X ' /tmp/cups-$user/log/error_log + $GREP '^X ' $BASE/log/error_log echo "

FAIL: $count emergency messages, expected 0.

" >>$strfile echo "
" >>$strfile
-	$GREP '^X ' /tmp/cups-$user/log/error_log | sed -e '1,$s/&/&/g' -e '1,$s/>$strfile
+	$GREP '^X ' $BASE/log/error_log | sed -e '1,$s/&/&/g' -e '1,$s/>$strfile
 	echo "
" >>$strfile fail=`expr $fail + 1` else @@ -871,13 +878,13 @@ else fi # Alert log messages -count=`$GREP '^A ' /tmp/cups-$user/log/error_log | wc -l | awk '{print $1}'` +count=`$GREP '^A ' $BASE/log/error_log | wc -l | awk '{print $1}'` if test $count != 0; then echo "FAIL: $count alert messages, expected 0." - $GREP '^A ' /tmp/cups-$user/log/error_log + $GREP '^A ' $BASE/log/error_log echo "

FAIL: $count alert messages, expected 0.

" >>$strfile echo "
" >>$strfile
-	$GREP '^A ' /tmp/cups-$user/log/error_log | sed -e '1,$s/&/&/g' -e '1,$s/>$strfile
+	$GREP '^A ' $BASE/log/error_log | sed -e '1,$s/&/&/g' -e '1,$s/>$strfile
 	echo "
" >>$strfile fail=`expr $fail + 1` else @@ -886,13 +893,13 @@ else fi # Critical log messages -count=`$GREP '^C ' /tmp/cups-$user/log/error_log | wc -l | awk '{print $1}'` +count=`$GREP '^C ' $BASE/log/error_log | wc -l | awk '{print $1}'` if test $count != 0; then echo "FAIL: $count critical messages, expected 0." - $GREP '^C ' /tmp/cups-$user/log/error_log + $GREP '^C ' $BASE/log/error_log echo "

FAIL: $count critical messages, expected 0.

" >>$strfile echo "
" >>$strfile
-	$GREP '^C ' /tmp/cups-$user/log/error_log | sed -e '1,$s/&/&/g' -e '1,$s/>$strfile
+	$GREP '^C ' $BASE/log/error_log | sed -e '1,$s/&/&/g' -e '1,$s/>$strfile
 	echo "
" >>$strfile fail=`expr $fail + 1` else @@ -901,13 +908,13 @@ else fi # Error log messages -count=`$GREP '^E ' /tmp/cups-$user/log/error_log | wc -l | awk '{print $1}'` +count=`$GREP '^E ' $BASE/log/error_log | wc -l | awk '{print $1}'` if test $count != 33; then echo "FAIL: $count error messages, expected 33." - $GREP '^E ' /tmp/cups-$user/log/error_log + $GREP '^E ' $BASE/log/error_log echo "

FAIL: $count error messages, expected 33.

" >>$strfile echo "
" >>$strfile
-	$GREP '^E ' /tmp/cups-$user/log/error_log | sed -e '1,$s/&/&/g' -e '1,$s/>$strfile
+	$GREP '^E ' $BASE/log/error_log | sed -e '1,$s/&/&/g' -e '1,$s/>$strfile
 	echo "
" >>$strfile fail=`expr $fail + 1` else @@ -916,13 +923,13 @@ else fi # Warning log messages -count=`$GREP '^W ' /tmp/cups-$user/log/error_log | $GREP -v CreateProfile | wc -l | awk '{print $1}'` +count=`$GREP '^W ' $BASE/log/error_log | $GREP -v CreateProfile | wc -l | awk '{print $1}'` if test $count != 9; then echo "FAIL: $count warning messages, expected 9." - $GREP '^W ' /tmp/cups-$user/log/error_log + $GREP '^W ' $BASE/log/error_log echo "

FAIL: $count warning messages, expected 9.

" >>$strfile echo "
" >>$strfile
-	$GREP '^W ' /tmp/cups-$user/log/error_log | sed -e '1,$s/&/&/g' -e '1,$s/>$strfile
+	$GREP '^W ' $BASE/log/error_log | sed -e '1,$s/&/&/g' -e '1,$s/>$strfile
 	echo "
" >>$strfile fail=`expr $fail + 1` else @@ -931,13 +938,13 @@ else fi # Notice log messages -count=`$GREP '^N ' /tmp/cups-$user/log/error_log | wc -l | awk '{print $1}'` +count=`$GREP '^N ' $BASE/log/error_log | wc -l | awk '{print $1}'` if test $count != 0; then echo "FAIL: $count notice messages, expected 0." - $GREP '^N ' /tmp/cups-$user/log/error_log + $GREP '^N ' $BASE/log/error_log echo "

FAIL: $count notice messages, expected 0.

" >>$strfile echo "
" >>$strfile
-	$GREP '^N ' /tmp/cups-$user/log/error_log | sed -e '1,$s/&/&/g' -e '1,$s/>$strfile
+	$GREP '^N ' $BASE/log/error_log | sed -e '1,$s/&/&/g' -e '1,$s/>$strfile
 	echo "
" >>$strfile fail=`expr $fail + 1` else @@ -946,7 +953,7 @@ else fi # Info log messages -count=`$GREP '^I ' /tmp/cups-$user/log/error_log | wc -l | awk '{print $1}'` +count=`$GREP '^I ' $BASE/log/error_log | wc -l | awk '{print $1}'` if test $count = 0; then echo "FAIL: $count info messages, expected more than 0." echo "

FAIL: $count info messages, expected more than 0.

" >>$strfile @@ -957,7 +964,7 @@ else fi # Debug log messages -count=`$GREP '^D ' /tmp/cups-$user/log/error_log | wc -l | awk '{print $1}'` +count=`$GREP '^D ' $BASE/log/error_log | wc -l | awk '{print $1}'` if test $count = 0; then echo "FAIL: $count debug messages, expected more than 0." echo "

FAIL: $count debug messages, expected more than 0.

" >>$strfile @@ -968,7 +975,7 @@ else fi # Debug2 log messages -count=`$GREP '^d ' /tmp/cups-$user/log/error_log | wc -l | awk '{print $1}'` +count=`$GREP '^d ' $BASE/log/error_log | wc -l | awk '{print $1}'` if test $count = 0; then echo "FAIL: $count debug2 messages, expected more than 0." echo "

FAIL: $count debug2 messages, expected more than 0.

" >>$strfile @@ -981,17 +988,17 @@ fi # Log files... echo "

access_log

" >>$strfile echo "
" >>$strfile
-sed -e '1,$s/&/&/g' -e '1,$s/>$strfile
+sed -e '1,$s/&/&/g' -e '1,$s/>$strfile
 echo "
" >>$strfile echo "

error_log

" >>$strfile echo "
" >>$strfile
-$GREP -v '^d' /tmp/cups-$user/log/error_log | sed -e '1,$s/&/&/g' -e '1,$s/>$strfile
+$GREP -v '^d' $BASE/log/error_log | sed -e '1,$s/&/&/g' -e '1,$s/>$strfile
 echo "
" >>$strfile echo "

page_log

" >>$strfile echo "
" >>$strfile
-sed -e '1,$s/&/&/g' -e '1,$s/>$strfile
+sed -e '1,$s/&/&/g' -e '1,$s/>$strfile
 echo "
" >>$strfile # @@ -1004,13 +1011,13 @@ echo "" if test $fail != 0; then echo "$fail tests failed." - cp /tmp/cups-$user/log/error_log error_log-$date-$user + cp $BASE/log/error_log error_log-$date-$user cp $strfile . else echo "All tests were successful." fi -echo "Log files can be found in /tmp/cups-$user/log." +echo "Log files can be found in $BASE/log." echo "A HTML report was created in $strfile." echo "" diff --git a/xcode/CUPS.xcodeproj/project.pbxproj b/xcode/CUPS.xcodeproj/project.pbxproj index ed3354a19..ef3689cc1 100644 --- a/xcode/CUPS.xcodeproj/project.pbxproj +++ b/xcode/CUPS.xcodeproj/project.pbxproj @@ -337,6 +337,7 @@ 728FB7F11536167A005426E1 /* libiconv.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 728FB7EF1536167A005426E1 /* libiconv.dylib */; }; 728FB7F21536167A005426E1 /* libresolv.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 728FB7F01536167A005426E1 /* libresolv.dylib */; }; 72C16CB9137B195D007E4BF4 /* file.c in Sources */ = {isa = PBXBuildFile; fileRef = 72C16CB8137B195D007E4BF4 /* file.c */; }; + 72CEF95618A966E000FA9B81 /* libcups.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 72220EAE1333047D00FCA411 /* libcups.dylib */; }; 72CF95E318A13543000FCAE4 /* dest-job.c in Sources */ = {isa = PBXBuildFile; fileRef = 72CF95E018A13543000FCAE4 /* dest-job.c */; }; 72CF95E418A13543000FCAE4 /* dest-localization.c in Sources */ = {isa = PBXBuildFile; fileRef = 72CF95E118A13543000FCAE4 /* dest-localization.c */; }; 72CF95E518A13543000FCAE4 /* dest-options.c in Sources */ = {isa = PBXBuildFile; fileRef = 72CF95E218A13543000FCAE4 /* dest-options.c */; }; @@ -1404,6 +1405,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 72CEF95618A966E000FA9B81 /* libcups.dylib in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; -- 2.39.5