]> git.ipfire.org Git - thirdparty/cups.git/blame - scheduler/cups-exec.c
License change: Apache License, Version 2.0.
[thirdparty/cups.git] / scheduler / cups-exec.c
CommitLineData
0268488e 1/*
c82f05ea 2 * Sandbox helper for CUPS.
0268488e 3 *
c82f05ea 4 * Copyright 2007-2014 by Apple Inc.
0268488e 5 *
e3101897 6 * Licensed under Apache License v2.0. See the file "LICENSE" for more information.
0268488e
MS
7 *
8 * Usage:
9 *
7131e285 10 * cups-exec /path/to/profile [-u UID] [-g GID] [-n NICE] /path/to/program argv0 argv1 ... argvN
0268488e
MS
11 */
12
13/*
14 * Include necessary headers...
15 */
16
17#include <cups/string-private.h>
8fe0183a 18#include <cups/file.h>
0268488e 19#include <unistd.h>
c82f05ea 20#include <fcntl.h>
07623986 21#include <grp.h>
c82f05ea 22#include <sys/stat.h>
0268488e 23#ifdef HAVE_SANDBOX_H
0268488e 24# include <sandbox.h>
a4845881
MS
25# ifndef SANDBOX_NAMED_EXTERNAL
26# define SANDBOX_NAMED_EXTERNAL 0x0003
27# endif /* !SANDBOX_NAMED_EXTERNAL */
6961465f 28# pragma GCC diagnostic ignored "-Wdeprecated-declarations"
0268488e
MS
29#endif /* HAVE_SANDBOX_H */
30
31
28c194b0
MS
32/*
33 * Local functions...
34 */
35
36static void usage(void) __attribute__((noreturn));
37
38
0268488e
MS
39/*
40 * 'main()' - Apply sandbox profile and execute program.
41 */
42
43int /* O - Exit status */
44main(int argc, /* I - Number of command-line args */
45 char *argv[]) /* I - Command-line arguments */
46{
28c194b0
MS
47 int i; /* Looping var */
48 const char *opt; /* Current option character */
49 uid_t uid = getuid(); /* UID */
50 gid_t gid = getgid(); /* GID */
51 int niceval = 0; /* Nice value */
0268488e 52#ifdef HAVE_SANDBOX_H
28c194b0 53 char *sandbox_error = NULL; /* Sandbox error, if any */
0268488e
MS
54#endif /* HAVE_SANDBOX_H */
55
56
28c194b0
MS
57 /*
58 * Parse command-line...
59 */
60
61 for (i = 1; i < argc; i ++)
62 {
63 if (argv[i][0] == '-')
64 {
65 for (opt = argv[i] + 1; *opt; opt ++)
66 {
67 switch (*opt)
68 {
69 case 'g' : /* -g gid */
70 i ++;
71 if (i >= argc)
72 usage();
73
74 gid = (gid_t)atoi(argv[i]);
75 break;
76
77 case 'n' : /* -n nice-value */
78 i ++;
79 if (i >= argc)
80 usage();
81
82 niceval = atoi(argv[i]);
83 break;
84
85 case 'u' : /* -g gid */
86 i ++;
87 if (i >= argc)
88 usage();
89
90 uid = (uid_t)atoi(argv[i]);
91 break;
92
93 default :
94 fprintf(stderr, "cups-exec: Unknown option '-%c'.\n", *opt);
95 usage();
96 }
97 }
98 }
99 else
100 break;
101 }
102
0268488e
MS
103 /*
104 * Check that we have enough arguments...
105 */
106
28c194b0 107 if ((i + 3) > argc)
0268488e 108 {
28c194b0
MS
109 fputs("cups-exec: Insufficient arguments.\n", stderr);
110 usage();
0268488e
MS
111 }
112
c82f05ea
MS
113 /*
114 * Make sure side and back channel FDs are non-blocking...
115 */
116
117 fcntl(3, F_SETFL, O_NDELAY);
118 fcntl(4, F_SETFL, O_NDELAY);
119
c82f05ea
MS
120 /*
121 * Change UID, GID, and nice value...
122 */
123
c82f05ea
MS
124 if (uid)
125 nice(niceval);
126
127 if (!getuid())
128 {
129 if (setgid(gid))
130 exit(errno + 100);
131
132 if (setgroups(1, &gid))
133 exit(errno + 100);
134
135 if (uid && setuid(uid))
136 exit(errno + 100);
137 }
138
139 umask(077);
140
8fe0183a 141#ifdef HAVE_SANDBOX_H
0268488e 142 /*
8fe0183a 143 * Run in a separate security profile...
0268488e
MS
144 */
145
28c194b0
MS
146 if (strcmp(argv[i], "none") &&
147 sandbox_init(argv[i], SANDBOX_NAMED_EXTERNAL, &sandbox_error))
8fe0183a
MS
148 {
149 cups_file_t *fp; /* File */
150 char line[1024]; /* Line from file */
151 int linenum = 0; /* Line number in file */
152
153 fprintf(stderr, "DEBUG: sandbox_init failed: %s (%s)\n", sandbox_error,
154 strerror(errno));
155 sandbox_free_error(sandbox_error);
156
28c194b0 157 if ((fp = cupsFileOpen(argv[i], "r")) != NULL)
8fe0183a
MS
158 {
159 while (cupsFileGets(fp, line, sizeof(line)))
160 {
161 linenum ++;
162 fprintf(stderr, "DEBUG: %4d %s\n", linenum, line);
163 }
164 cupsFileClose(fp);
165 }
166
167 return (100 + EINVAL);
168 }
169#endif /* HAVE_SANDBOX_H */
0268488e 170
28c194b0
MS
171 /*
172 * Execute the program...
173 */
174
175 execv(argv[i + 1], argv + i + 2);
176
0268488e
MS
177 /*
178 * If we get here, execv() failed...
179 */
180
181 fprintf(stderr, "DEBUG: execv failed: %s\n", strerror(errno));
8fe0183a 182 return (errno + 100);
0268488e
MS
183}
184
185
28c194b0
MS
186/*
187 * 'usage()' - Show program usage.
188 */
189
190static void
191usage(void)
192{
193 fputs("Usage: cups-exec [-g gid] [-n nice-value] [-u uid] /path/to/profile /path/to/program argv0 argv1 ... argvN\n", stderr);
194 exit(1);
195}