/[path-sandbox]/trunk/libsbutil/get_sandbox_lib.c
Gentoo

Contents of /trunk/libsbutil/get_sandbox_lib.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2 - (hide annotations) (download) (as text)
Fri Nov 19 22:03:42 2004 UTC (13 years, 7 months ago) by ferringb
Original Path: trunk/sandbox_futils.c
File MIME type: text/x-csrc
File size: 11733 byte(s)
Initial revision

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

Properties

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

  ViewVC Help
Powered by ViewVC 1.1.20