diff options
author | Jeremy Allison <jra@samba.org> | 2000-03-16 20:55:37 +0000 |
---|---|---|
committer | Jeremy Allison <jra@samba.org> | 2000-03-16 20:55:37 +0000 |
commit | e601c0259e9e6a48e04ce3e0ff793cb564a89716 (patch) | |
tree | 43bd810549c4ecaff98bb9853750de16af73d554 /source3/lib/system.c | |
parent | a36d737c88b002787014b04788460ca65b4dcbe5 (diff) | |
download | samba-e601c0259e9e6a48e04ce3e0ff793cb564a89716.tar.gz samba-e601c0259e9e6a48e04ce3e0ff793cb564a89716.tar.bz2 samba-e601c0259e9e6a48e04ce3e0ff793cb564a89716.zip |
Fixes to add "paranoid" option to popen. Checks some basic things.
Jeremy
(This used to be commit 3b8cbb10de322fd7a1063fb5b681790b10d24ab0)
Diffstat (limited to 'source3/lib/system.c')
-rw-r--r-- | source3/lib/system.c | 57 |
1 files changed, 56 insertions, 1 deletions
diff --git a/source3/lib/system.c b/source3/lib/system.c index 9ef0af494f..8ac07e26a5 100644 --- a/source3/lib/system.c +++ b/source3/lib/system.c @@ -963,7 +963,7 @@ typedef struct _popen_list static popen_list *popen_chain; -FILE *sys_popen(const char *command, const char *mode) +FILE *sys_popen(const char *command, const char *mode, BOOL paranoid) { int parent_end, child_end; int pipe_fds[2]; @@ -999,6 +999,61 @@ FILE *sys_popen(const char *command, const char *mode) if(!(argl = extract_args(command))) goto err_exit; + if(paranoid) { + /* + * Do some basic paranioa checks. Do a stat on the parent + * directory and ensure it's not world writable. Do a stat + * on the file itself and ensure it's owned by root and not + * world writable. Note this does *not* prevent symlink races, + * but is a generic "don't let the admin screw themselves" + * check. + */ + + SMB_STRUCT_STAT st; + pstring dir_name; + char *ptr = strrchr(argl[0], '/'); + + if(sys_stat(argl[0], &st) != 0) + goto err_exit; + + if((st.st_uid != (uid_t)0) || (st.st_mode & S_IWOTH)) { + errno = EACCES; + goto err_exit; + } + + if(!ptr) { + /* + * No '/' in name - use current directory. + */ + pstrcpy(dir_name, "."); + } else { + + /* + * Copy into a pstring and do the checks + * again (in case we were length tuncated). + */ + + pstrcpy(dir_name, argl[0]); + ptr = strrchr(dir_name, '/'); + if(!ptr) { + errno = EINVAL; + goto err_exit; + } + if(strcmp(dir_name, "/") != 0) + *ptr = '\0'; + if(!dir_name[0]) + pstrcpy(dir_name, "."); + } + + if(sys_stat(argl[0], &st) != 0) + goto err_exit; + + if(!S_ISDIR(st.st_mode) || (st.st_mode & S_IWOTH)) { + errno = EACCES; + goto err_exit; + } + } + entry->child_pid = fork(); if (entry->child_pid == -1) { |