]>
Commit | Line | Data |
---|---|---|
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 | ||
36 | static void usage(void) __attribute__((noreturn)); | |
37 | ||
38 | ||
0268488e MS |
39 | /* |
40 | * 'main()' - Apply sandbox profile and execute program. | |
41 | */ | |
42 | ||
43 | int /* O - Exit status */ | |
44 | main(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 | ||
190 | static void | |
191 | usage(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 | } |