diff options
Diffstat (limited to 'scheduler/cups-exec.c')
-rw-r--r-- | scheduler/cups-exec.c | 160 |
1 files changed, 136 insertions, 24 deletions
diff --git a/scheduler/cups-exec.c b/scheduler/cups-exec.c index 3474c6e39..e63b163b3 100644 --- a/scheduler/cups-exec.c +++ b/scheduler/cups-exec.c @@ -1,23 +1,19 @@ /* - * "$Id: cups-exec.c 11144 2013-07-17 02:45:55Z msweet $" + * "$Id: cups-exec.c 11817 2014-04-15 16:31:11Z msweet $" * - * Sandbox helper for CUPS. + * Sandbox helper for CUPS. * - * Copyright 2007-2013 by Apple Inc. + * Copyright 2007-2014 by Apple Inc. * - * 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/". * * Usage: * - * cups-exec /path/to/profile /path/to/program argv0 argv1 ... argvN - * - * Contents: - * - * main() - Apply sandbox profile and execute program. + * cups-exec /path/to/profile [-u UID] [-g GID] [-n NICE] /path/to/program argv0 argv1 ... argvN */ /* @@ -25,7 +21,11 @@ */ #include <cups/string-private.h> +#include <cups/file.h> #include <unistd.h> +#include <fcntl.h> +#include <grp.h> +#include <sys/stat.h> #ifdef HAVE_SANDBOX_H # include <sandbox.h> # ifndef SANDBOX_NAMED_EXTERNAL @@ -36,6 +36,13 @@ /* + * Local functions... + */ + +static void usage(void) __attribute__((noreturn)); + + +/* * 'main()' - Apply sandbox profile and execute program. */ @@ -43,34 +50,127 @@ int /* O - Exit status */ main(int argc, /* I - Number of command-line args */ char *argv[]) /* I - Command-line arguments */ { + int i; /* Looping var */ + const char *opt; /* Current option character */ + uid_t uid = getuid(); /* UID */ + gid_t gid = getgid(); /* GID */ + int niceval = 0; /* Nice value */ #ifdef HAVE_SANDBOX_H - char *sandbox_error = NULL; /* Sandbox error, if any */ + char *sandbox_error = NULL; /* Sandbox error, if any */ #endif /* HAVE_SANDBOX_H */ /* + * Parse command-line... + */ + + for (i = 1; i < argc; i ++) + { + if (argv[i][0] == '-') + { + for (opt = argv[i] + 1; *opt; opt ++) + { + switch (*opt) + { + case 'g' : /* -g gid */ + i ++; + if (i >= argc) + usage(); + + gid = (gid_t)atoi(argv[i]); + break; + + case 'n' : /* -n nice-value */ + i ++; + if (i >= argc) + usage(); + + niceval = atoi(argv[i]); + break; + + case 'u' : /* -g gid */ + i ++; + if (i >= argc) + usage(); + + uid = (uid_t)atoi(argv[i]); + break; + + default : + fprintf(stderr, "cups-exec: Unknown option '-%c'.\n", *opt); + usage(); + } + } + } + else + break; + } + + /* * Check that we have enough arguments... */ - if (argc < 4) + if ((i + 3) > argc) + { + fputs("cups-exec: Insufficient arguments.\n", stderr); + usage(); + } + + /* + * Make sure side and back channel FDs are non-blocking... + */ + + fcntl(3, F_SETFL, O_NDELAY); + fcntl(4, F_SETFL, O_NDELAY); + + /* + * Change UID, GID, and nice value... + */ + + if (uid) + nice(niceval); + + if (!getuid()) { - puts("Usage: cups-exec /path/to/profile /path/to/program argv0 argv1 ... " - "argvN"); - return (1); + if (setgid(gid)) + exit(errno + 100); + + if (setgroups(1, &gid)) + exit(errno + 100); + + if (uid && setuid(uid)) + exit(errno + 100); } + umask(077); + #ifdef HAVE_SANDBOX_H /* * Run in a separate security profile... */ - if (strcmp(argv[1], "none") && - sandbox_init(argv[1], SANDBOX_NAMED_EXTERNAL, &sandbox_error)) + if (strcmp(argv[i], "none") && + sandbox_init(argv[i], 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); - return (1); + + if ((fp = cupsFileOpen(argv[i], "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 */ @@ -78,17 +178,29 @@ main(int argc, /* I - Number of command-line args */ * Execute the program... */ - execv(argv[2], argv + 3); + execv(argv[i + 1], argv + i + 2); /* * If we get here, execv() failed... */ fprintf(stderr, "DEBUG: execv failed: %s\n", strerror(errno)); - return (1); + return (errno + 100); +} + + +/* + * 'usage()' - Show program usage. + */ + +static void +usage(void) +{ + fputs("Usage: cups-exec [-g gid] [-n nice-value] [-u uid] /path/to/profile /path/to/program argv0 argv1 ... argvN\n", stderr); + exit(1); } /* - * End of "$Id: cups-exec.c 11144 2013-07-17 02:45:55Z msweet $". + * End of "$Id: cups-exec.c 11817 2014-04-15 16:31:11Z msweet $". */ |