/[path-sandbox]/trunk/sandbox_futils.c
Gentoo

Contents of /trunk/sandbox_futils.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 30 - (hide annotations) (download) (as text)
Wed Mar 2 09:04:45 2005 UTC (13 years, 5 months ago) by azarah
File MIME type: text/x-csrc
File size: 11655 byte(s)
White space fixes.

1 ferringb 2 /*
2     * Copyright (C) 2002 Brad House <brad@mainstreetsoftworks.com>
3     * Distributed under the terms of the GNU General Public License, v2 or later
4     * Author: Brad House <brad@mainstreetsoftworks.com>
5     *
6     * $Header$
7     *
8     */
9    
10     #include <errno.h>
11     #include <fcntl.h>
12     #include <signal.h>
13     #include <stdio.h>
14     #include <stdlib.h>
15     #include <limits.h>
16     #include <string.h>
17     #include <stdarg.h>
18     #include <sys/file.h>
19     #include <sys/stat.h>
20     #include <sys/time.h>
21     #include <sys/types.h>
22     #include <sys/resource.h>
23     #include <sys/wait.h>
24     #include <unistd.h>
25     #include <fcntl.h>
26    
27     #include <grp.h>
28     #include <pwd.h>
29    
30     #include "sandbox.h"
31 ferringb 13 #include "config.h"
32 ferringb 2
33     /* BEGIN Prototypes */
34     int file_security_check(char *filename);
35     /* END Prototypes */
36    
37     /* glibc modified getcwd() functions */
38     char *egetcwd(char *, size_t);
39    
40 azarah 30 char *get_sandbox_path(char *argv0)
41 ferringb 2 {
42     char path[255];
43     char *cwd = NULL;
44    
45     memset(path, 0, sizeof(path));
46     /* ARGV[0] specifies full path */
47     if (argv0[0] == '/') {
48 azarah 30 strncpy(path, argv0, sizeof(path) - 1);
49 ferringb 2
50     /* ARGV[0] specifies relative path */
51     } else {
52 azarah 30 egetcwd(cwd, sizeof(path) - 2);
53 ferringb 2 snprintf(path, sizeof(path), "%s/%s", cwd, argv0);
54     if (cwd)
55     free(cwd);
56     cwd = NULL;
57     }
58    
59     /* Return just directory */
60     return (sb_dirname(path));
61     }
62    
63 azarah 30 char *get_sandbox_lib(char *sb_path)
64 ferringb 2 {
65     char path[255];
66    
67     #ifdef SB_HAVE_64BIT_ARCH
68 azarah 30 snprintf(path, sizeof(path), "%s", LIB_NAME);
69 ferringb 2 #else
70 azarah 30 snprintf(path, sizeof(path), "%s/%s", LIBSANDBOX_PATH, LIB_NAME);
71 ferringb 2 if (file_exist(path, 0) <= 0) {
72     snprintf(path, sizeof(path), "%s%s", sb_path, LIB_NAME);
73     }
74     #endif
75     return (strdup(path));
76     }
77    
78 azarah 30 char *get_sandbox_pids_file(void)
79 ferringb 2 {
80     if (0 < getenv("SANDBOX_PIDS_FILE")) {
81     return (strdup(getenv("SANDBOX_PIDS_FILE")));
82     }
83     return (strdup(PIDS_FILE));
84     }
85    
86 azarah 30 char *get_sandbox_rc(char *sb_path)
87 ferringb 2 {
88     char path[255];
89    
90 ferringb 13 snprintf(path, sizeof(path), "%s/%s", SANDBOX_BASHRC_PATH, BASHRC_NAME);
91 ferringb 2 if (file_exist(path, 0) <= 0) {
92     snprintf(path, sizeof(path), "%s%s", sb_path, BASHRC_NAME);
93     }
94     return (strdup(path));
95     }
96    
97 azarah 30 char *get_sandbox_log()
98 ferringb 2 {
99     char path[255];
100     char *sandbox_log_env = NULL;
101    
102     /* THIS CHUNK BREAK THINGS BY DOING THIS:
103     * SANDBOX_LOG=/tmp/sandbox-app-admin/superadduser-1.0.7-11063.log
104     */
105    
106     sandbox_log_env = getenv(ENV_SANDBOX_LOG);
107 azarah 30 snprintf(path, sizeof(path) - 1, "%s%s%s%d%s", LOG_FILE_PREFIX,
108     (sandbox_log_env == NULL ? "" : sandbox_log_env),
109     (sandbox_log_env == NULL ? "" : "-"), getpid(), LOG_FILE_EXT);
110 ferringb 2 return (strdup(path));
111     }
112    
113     /* Obtain base directory name. Do not allow trailing / */
114 azarah 30 char *sb_dirname(const char *path)
115 ferringb 2 {
116     char *ret = NULL;
117     char *ptr = NULL;
118     int loc = 0, i;
119     int cut_len = -1;
120    
121     /* don't think NULL will ever be passed, but just in case */
122     if (NULL == path)
123     return (strdup("."));
124    
125     /* Grab pointer to last slash */
126     ptr = strrchr(path, '/');
127     if (NULL == ptr) {
128     return (strdup("."));
129     }
130    
131     /* decimal location of pointer */
132     loc = ptr - path;
133    
134     /* Remove any trailing slash */
135     for (i = loc - 1; i >= 0; i--) {
136     if (path[i] != '/') {
137 azarah 30 cut_len = i + 1; /* make cut_len the length of the string to keep */
138 ferringb 2 break;
139     }
140     }
141    
142     /* It could have been just a plain /, return a 1byte 0 filled string */
143     if (-1 == cut_len)
144     return (strdup(""));
145    
146     /* Allocate memory, and return the directory */
147 azarah 30 ret = (char *)malloc((cut_len + 1) * sizeof(char));
148 ferringb 2 memcpy(ret, path, cut_len);
149     ret[cut_len] = 0;
150    
151     return (ret);
152     }
153    
154     /*
155     char* dirname(const char* path)
156     {
157     char* base = NULL;
158     unsigned int length = 0;
159    
160     base = strrchr(path, '/');
161     if (NULL == base)
162     {
163     return strdup(".");
164     }
165     while (base > path && *base == '/')
166     {
167     base--;
168     }
169     length = (unsigned int) 1 + base - path;
170    
171     base = malloc(sizeof(char)*(length+1));
172     memmove(base, path, length);
173     base[length] = 0;
174    
175     return base;
176     }*/
177    
178     /* Convert text (string) modes to integer values */
179 azarah 30 int file_getmode(char *mode)
180 ferringb 2 {
181     int mde = 0;
182     if (0 == strcasecmp(mode, "r+")) {
183     mde = O_RDWR | O_CREAT;
184     } else if (0 == strcasecmp(mode, "w+")) {
185     mde = O_RDWR | O_CREAT | O_TRUNC;
186     } else if (0 == strcasecmp(mode, "a+")) {
187     mde = O_RDWR | O_CREAT | O_APPEND;
188     } else if (0 == strcasecmp(mode, "r")) {
189     mde = O_RDONLY;
190     } else if (0 == strcasecmp(mode, "w")) {
191     mde = O_WRONLY | O_CREAT | O_TRUNC;
192     } else if (0 == strcasecmp(mode, "a")) {
193     mde = O_WRONLY | O_APPEND | O_CREAT;
194     } else {
195     mde = O_RDONLY;
196     }
197     return (mde);
198     }
199    
200     /* Get current position in file */
201 azarah 30 long file_tell(int fp)
202 ferringb 2 {
203     return (lseek(fp, 0L, SEEK_CUR));
204     }
205    
206     /* lock the file, preferrably the POSIX way */
207 azarah 30 int file_lock(int fd, int lock, char *filename)
208 ferringb 2 {
209     int err;
210     #ifdef USE_FLOCK
211     if (flock(fd, lock) < 0) {
212     err = errno;
213     fprintf(stderr, ">>> %s flock file lock: %s\n", filename, strerror(err));
214     return 0;
215     }
216     #else
217     struct flock fl;
218     fl.l_type = lock;
219     fl.l_whence = SEEK_SET;
220     fl.l_start = 0L;
221     fl.l_len = 0L;
222     fl.l_pid = getpid();
223     if (fcntl(fd, F_SETLKW, &fl) < 0) {
224     err = errno;
225     fprintf(stderr, ">>> %s fcntl file lock: %s\n", filename, strerror(err));
226     return 0;
227     }
228     #endif
229     return 1;
230     }
231    
232     /* unlock the file, preferrably the POSIX way */
233 azarah 30 int file_unlock(int fd)
234 ferringb 2 {
235     #ifdef USE_FLOCK
236     if (flock(fd, LOCK_UN) < 0) {
237     perror(">>> flock file unlock");
238     return 0;
239     }
240     #else
241     struct flock fl;
242     fl.l_type = F_UNLCK;
243     fl.l_whence = SEEK_SET;
244     fl.l_start = 0L;
245     fl.l_len = 0L;
246     fl.l_pid = getpid();
247     if (fcntl(fd, F_SETLKW, &fl) < 0) {
248     perror(">>> fcntl file unlock");
249     return 0;
250     }
251     #endif
252     return 1;
253     }
254    
255     /* Auto-determine from how the file was opened, what kind of lock to lock
256     * the file with
257     */
258 azarah 30 int file_locktype(char *mode)
259 ferringb 2 {
260     #ifdef USE_FLOCK
261     if (NULL != (strchr(mode, 'w')) || (NULL != strchr(mode, '+'))
262 azarah 30 || (NULL != strchr(mode, 'a')))
263 ferringb 2 return (LOCK_EX);
264     return (LOCK_SH);
265     #else
266     if (NULL != (strchr(mode, 'w')) || (NULL != strchr(mode, '+'))
267 azarah 30 || (NULL != strchr(mode, 'a')))
268 ferringb 2 return (F_WRLCK);
269     return (F_RDLCK);
270     #endif
271     }
272    
273     /* Use standard fopen style modes to open the specified file. Also auto-determines and
274     * locks the file either in shared or exclusive mode depending on opening mode
275     */
276 azarah 30 int file_open(char *filename, char *mode, int perm_specified, ...)
277 ferringb 2 {
278     int fd;
279     char error[250];
280     va_list ap;
281     int perm;
282     char *group = NULL;
283     struct group *group_struct;
284 azarah 30
285 ferringb 2 file_security_check(filename);
286    
287     if (perm_specified) {
288     va_start(ap, perm_specified);
289     perm = va_arg(ap, int);
290     group = va_arg(ap, char *);
291     va_end(ap);
292     }
293     fd = open(filename, file_getmode(mode));
294     file_security_check(filename);
295     if (-1 == fd) {
296     snprintf(error, sizeof(error), ">>> %s file mode: %s open", filename, mode);
297     perror(error);
298     return (fd);
299     }
300     if (perm_specified) {
301     if (fchmod(fd, 0664) && (0 == getuid())) {
302     snprintf(error, sizeof(error), ">>> Could not set mode: %s", filename);
303     perror(error);
304     }
305     }
306     if (NULL != group) {
307     group_struct = getgrnam(group);
308     if (NULL == group) {
309     snprintf(error, sizeof(error), ">>> Could not get grp number: %s", group);
310     perror(error);
311     } else {
312     if (fchown(fd, -1, group_struct->gr_gid) && (0 == getuid())) {
313     snprintf(error, sizeof(error), ">>> Could not set group: %s", filename);
314     perror(error);
315     }
316     }
317     }
318     /* Only lock the file if opening succeeded */
319     if (-1 != fd) {
320 azarah 30 if (file_security_check(filename) != 0) {
321     /* Security violation occured between the last check and the */
322 ferringb 2 /* creation of the file. As SpanKY pointed out there is a race */
323     /* condition here, so if there is a problem here we'll mesg and */
324     /* bail out to avoid it until we can work and test a better fix. */
325     fprintf(stderr, "\n\nSECURITY RACE CONDITION: Problem recurred after creation!\nBAILING OUT\n\n");
326     exit(127);
327     }
328    
329     if (0 == file_lock(fd, file_locktype(mode), filename)) {
330     close(fd);
331     return -1;
332     }
333     } else {
334     snprintf(error, sizeof(error), ">>> %s file mode:%s open", filename, mode);
335     perror(error);
336     }
337     return (fd);
338     }
339    
340     /* Close and unlock file */
341 azarah 30 void file_close(int fd)
342 ferringb 2 {
343     if (-1 != fd) {
344     file_unlock(fd);
345     close(fd);
346     }
347     }
348    
349     /* Return length of file */
350 azarah 30 long file_length(int fd)
351 ferringb 2 {
352     long pos, len;
353     pos = file_tell(fd);
354     len = lseek(fd, 0L, SEEK_END);
355     lseek(fd, pos, SEEK_SET);
356     return (len);
357     }
358    
359     /* Zero out file */
360 azarah 30 int file_truncate(int fd)
361 ferringb 2 {
362     lseek(fd, 0L, SEEK_SET);
363     if (ftruncate(fd, 0) < 0) {
364     perror(">>> file truncate");
365     return 0;
366     }
367     return 1;
368     }
369    
370     /* Check to see if a file exists Return: 1 success, 0 file not found, -1 error */
371 azarah 30 int file_exist(char *filename, int checkmode)
372 ferringb 2 {
373     struct stat mystat;
374    
375     /* Verify file exists and is regular file (not sym link) */
376     if (checkmode) {
377     if (-1 == lstat(filename, &mystat)) {
378     /* file doesn't exist */
379     if (ENOENT == errno) {
380     return 0;
381 azarah 30 } else { /* permission denied or other error */
382 ferringb 2 perror(">>> stat file");
383     return -1;
384     }
385     }
386     if (!S_ISREG(mystat.st_mode))
387     return -1;
388    
389     /* Just plain verify the file exists */
390     } else {
391     if (-1 == stat(filename, &mystat)) {
392     /* file does not exist */
393     if (ENOENT == errno) {
394     return 0;
395 azarah 30 } else { /* permission denied or other error */
396 ferringb 2 perror(">>> stat file");
397     return -1;
398     }
399     }
400     }
401    
402     return 1;
403     }
404    
405 azarah 30 int file_security_check(char *filename)
406     { /* 0 == fine, >0 == problem */
407 ferringb 2 struct stat stat_buf;
408     struct group *group_buf;
409     struct passwd *passwd_buf;
410 azarah 30
411 ferringb 2 passwd_buf = getpwnam("portage");
412     group_buf = getgrnam("portage");
413    
414 azarah 30 if ((lstat(filename, &stat_buf) == -1) && (errno == ENOENT)) {
415 ferringb 2 /* Doesn't exist. */
416     return 0;
417 azarah 30 } else {
418     if ((stat_buf.st_nlink) > 1) { /* Security: We are handlinked... */
419     if (unlink(filename)) {
420     fprintf(stderr, "Unable to delete file in security violation (hardlinked): %s\n", filename);
421 ferringb 2 exit(127);
422     }
423 azarah 30 fprintf(stderr, "File in security violation (hardlinked): %s\n", filename);
424 ferringb 2 return 1;
425 azarah 30 } else if (S_ISLNK(stat_buf.st_mode)) { /* Security: We are a symlink? */
426     fprintf(stderr, "File in security violation (symlink): %s\n", filename);
427 ferringb 2 exit(127);
428 azarah 30 } else if (0 == S_ISREG(stat_buf.st_mode)) { /* Security: special file */
429     fprintf(stderr, "File in security violation (not regular): %s\n", filename);
430 ferringb 2 exit(127);
431 azarah 30 } else if (stat_buf.st_mode & S_IWOTH) { /* Security: We are o+w? */
432     if (unlink(filename)) {
433     fprintf(stderr, "Unable to delete file in security violation (world write): %s\n", filename);
434 ferringb 2 exit(127);
435     }
436 azarah 30 fprintf(stderr, "File in security violation (world write): %s\n", filename);
437 ferringb 2 return 1;
438 azarah 30 } else
439     if (!((stat_buf.st_uid == 0) || (stat_buf.st_uid == getuid()) ||
440     ((passwd_buf != NULL) && (stat_buf.st_uid == passwd_buf->pw_uid))) ||
441     !((stat_buf.st_gid == 0) || (stat_buf.st_gid == getgid()) ||
442     ((group_buf != NULL) && (stat_buf.st_gid == group_buf->gr_gid)))) {
443     /* Security: Owner/Group isn't right. */
444    
445 ferringb 2 /* uid = 0 or myuid or portage */
446     /* gid = 0 or mygid or portage */
447 azarah 30
448     if (0) {
449 ferringb 2 fprintf(stderr, "--1: %d,%d,%d,%d\n--2: %d,%d,%d,%d\n",
450     (stat_buf.st_uid == 0),
451     (stat_buf.st_uid == getuid()),
452 azarah 30 (passwd_buf != NULL),
453     (passwd_buf != NULL) ? (stat_buf.st_uid == passwd_buf->pw_uid) : -1,
454     (stat_buf.st_gid == 0),
455 ferringb 2 (stat_buf.st_gid == getgid()),
456 azarah 30 (group_buf != NULL),
457     (group_buf != NULL) ? (stat_buf.st_gid == group_buf->gr_gid) : -1);
458 ferringb 2 }
459 azarah 30
460 ferringb 2 /* manpage: "The return value may point to static area" */
461     /* DO NOT ACTUALLY FREE THIS... It'll segfault. */
462     /* if(passwd_buf != NULL) { free(passwd_buf); } */
463     /* if(group_buf != NULL) { free(group_buf); } */
464 azarah 30
465     if (unlink(filename)) {
466     fprintf(stderr, "Unable to delete file in security violation (bad owner/group): %s\n", filename);
467 ferringb 2 exit(127);
468     }
469 azarah 30 fprintf(stderr, "File in security violation (bad owner/group): %s\n", filename);
470 ferringb 2 return 1;
471     }
472 azarah 30 } /* Stat */
473 ferringb 2 return 0;
474     }
475    
476 azarah 30 // vim:noexpandtab noai:cindent ai

Properties

Name Value
svn:eol-style native
svn:keywords Author Date Id Revision

  ViewVC Help
Powered by ViewVC 1.1.20