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