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