From e601c0259e9e6a48e04ce3e0ff793cb564a89716 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 16 Mar 2000 20:55:37 +0000 Subject: Fixes to add "paranoid" option to popen. Checks some basic things. Jeremy (This used to be commit 3b8cbb10de322fd7a1063fb5b681790b10d24ab0) --- source3/lib/system.c | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 56 insertions(+), 1 deletion(-) (limited to 'source3/lib/system.c') 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) { -- cgit