/*
- * "$Id$"
+ * "$Id: process.c 7256 2008-01-25 00:48:54Z mike $"
*
* Process management routines for the Common UNIX Printing System (CUPS).
*
- * Copyright 1997-2006 by Easy Software Products, all rights reserved.
+ * Copyright 2007 by Apple Inc.
+ * Copyright 1997-2007 by Easy Software Products, all rights reserved.
*
* These coded instructions, statements, and computer programs are the
- * property of Easy Software Products 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 missing or damaged please contact Easy Software Products
- * at:
- *
- * Attn: CUPS Licensing Information
- * Easy Software Products
- * 44141 Airport View Drive, Suite 204
- * Hollywood, Maryland 20636 USA
- *
- * Voice: (301) 373-9600
- * EMail: cups-info@cups.org
- * WWW: http://www.cups.org
+ * 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/".
*
* Contents:
*
- * cupsdEndProcess() - End a process.
- * cupsdFinishProcess() - Finish a process and get its name.
- * cupsdStartProcess() - Start a process.
- * compare_procs() - Compare two processes.
+ * cupsdCreateProfile() - Create an execution profile for a subprocess.
+ * cupsdDestroyProfile() - Delete an execution profile.
+ * cupsdEndProcess() - End a process.
+ * cupsdFinishProcess() - Finish a process and get its name.
+ * cupsdStartProcess() - Start a process.
+ * compare_procs() - Compare two processes.
+ * cupsd_requote() - Make a regular-expression version of a string.
*/
/*
#include "cupsd.h"
#include <grp.h>
-#if defined(__APPLE__)
+#ifdef __APPLE__
# include <libgen.h>
#endif /* __APPLE__ */
+#ifdef HAVE_SANDBOX_H
+# define __APPLE_API_PRIVATE
+# include <sandbox.h>
+#endif /* HAVE_SANDBOX_H */
/*
*/
static int compare_procs(cupsd_proc_t *a, cupsd_proc_t *b);
+#ifdef HAVE_SANDBOX_H
+static char *cupsd_requote(char *dst, const char *src, size_t dstsize);
+#endif /* HAVE_SANDBOX_H */
+
+
+/*
+ * 'cupsdCreateProfile()' - Create an execution profile for a subprocess.
+ */
+
+void * /* O - Profile or NULL on error */
+cupsdCreateProfile(int job_id) /* I - Job ID or 0 for none */
+{
+#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 */
+
+
+ if ((fp = cupsTempFile2(profile, sizeof(profile))) == NULL)
+ {
+ cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to create security profile: %s",
+ strerror(errno));
+ return (NULL);
+ }
+
+ cupsd_requote(cache, CacheDir, sizeof(cache));
+ cupsd_requote(request, RequestRoot, sizeof(request));
+ cupsd_requote(root, ServerRoot, sizeof(root));
+ cupsd_requote(temp, TempDir, sizeof(temp));
+
+ cupsFilePuts(fp, "(version 1)\n");
+ cupsFilePuts(fp, "(debug deny)\n");
+ cupsFilePuts(fp, "(allow default)\n");
+ cupsFilePrintf(fp,
+ "(deny file-write* file-read-data file-read-metadata\n"
+ " (regex #\"^%s/\"))\n", request);
+ cupsFilePrintf(fp,
+ "(deny file-write*\n"
+ " (regex #\"^%s\" #\"^/private/etc\" #\"^/usr/local/etc\" "
+ "#\"^/Library\" #\"^/System\" #\"^/Users\"))\n", root);
+ cupsFilePrintf(fp,
+ "(allow file-write* file-read-data file-read-metadata\n"
+ " (regex #\"^%s$\" #\"^%s/\" #\"^%s$\" #\"^%s/\" "
+ "#\"^/Library/Caches/\"))\n",
+ temp, temp, cache, cache);
+ if (job_id)
+ cupsFilePrintf(fp,
+ "(allow file-read-data file-read-metadata\n"
+ " (regex #\"^%s/([ac]%05d|d%05d-[0-9][0-9][0-9])$\"))\n",
+ request, job_id, job_id);
+
+ cupsFileClose(fp);
+
+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdCreateProfile(job_id=%d) = \"%s\"",
+ job_id, profile);
+ return ((void *)strdup(profile));
+#else
+
+ return (NULL);
+#endif /* HAVE_SANDBOX_H */
+}
+
+
+/*
+ * 'cupsdDestroyProfile()' - Delete an execution profile.
+ */
+
+void
+cupsdDestroyProfile(void *profile) /* I - Profile */
+{
+#ifdef HAVE_SANDBOX_H
+ if (profile)
+ {
+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdDeleteProfile(profile=\"%s\")",
+ (char *)profile);
+ unlink((char *)profile);
+ free(profile);
+ }
+#endif /* HAVE_SANDBOX_H */
+}
/*
int outfd, /* I - Standard output file descriptor */
int errfd, /* I - Standard error file descriptor */
int backfd, /* I - Backchannel file descriptor */
+ int sidefd, /* I - Sidechannel file descriptor */
int root, /* I - Run as root? */
+ void *profile, /* I - Security profile to use */
int *pid) /* O - Process ID */
{
cupsd_proc_t *proc; /* New process record */
"cupsdStartProcess(\"%s\", %p, %p, %d, %d, %d)",
command, argv, envp, infd, outfd, errfd);
+ if (access(command, X_OK))
+ {
+ cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to execute %s: %s", command,
+ strerror(errno));
+ *pid = 0;
+ return (0);
+ }
+
#if defined(__APPLE__)
if (envp)
{
linkpath);
else
snprintf(processPath, sizeof(processPath), "CFProcessPath=%s/%s",
- dirname(command), linkpath);
+ dirname((char *)command), linkpath);
}
else
snprintf(processPath, sizeof(processPath), "CFProcessPath=%s", command);
open("/dev/null", O_RDWR);
fcntl(3, F_SETFL, O_NDELAY);
}
+ if (sidefd != 4 && sidefd > 0)
+ {
+ close(4);
+ dup(sidefd);
+ fcntl(4, F_SETFL, O_NDELAY);
+ }
/*
* Change the priority of the process based on the FilterNice setting.
- * (this is not done for backends...)
+ * (this is not done for root processes...)
*/
if (!root)
nice(FilterNice);
+#ifdef HAVE_SANDBOX_H
+ /*
+ * Run in a separate security profile...
+ */
+
+ if (profile)
+ {
+ char *error = NULL; /* Sandbox error, if any */
+
+ if (sandbox_init((char *)profile, SANDBOX_NAMED_EXTERNAL, &error))
+ {
+ fprintf(stderr, "ERROR: sandbox_init failed: %s (%s)\n", error,
+ strerror(errno));
+ sandbox_free_error(error);
+ }
+ }
+#endif /* HAVE_SANDBOX_H */
+
/*
* Change user to something "safe"...
*/
}
+#ifdef HAVE_SANDBOX_H
+/*
+ * 'cupsd_requote()' - Make a regular-expression version of a string.
+ */
+
+static char * /* O - Quoted string */
+cupsd_requote(char *dst, /* I - Destination buffer */
+ const char *src, /* I - Source string */
+ size_t dstsize) /* I - Size of destination buffer */
+{
+ int ch; /* Current character */
+ char *dstptr, /* Current position in buffer */
+ *dstend; /* End of destination buffer */
+
+
+ dstptr = dst;
+ dstend = dst + dstsize - 2;
+
+ while (*src && dstptr < dstend)
+ {
+ ch = *src++;
+
+ if (strchr(".?*()[]^$\\", ch))
+ *dstptr++ = '\\';
+
+ *dstptr++ = ch;
+ }
+
+ *dstptr = '\0';
+
+ return (dst);
+}
+#endif /* HAVE_SANDBOX_H */
+
+
/*
- * End of "$Id$".
+ * End of "$Id: process.c 7256 2008-01-25 00:48:54Z mike $".
*/