1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-05-04 17:49:45 +02:00
Carlo Bramini 717ceb6525
[NYQUIST] Fix build on CYGWIN. (#557)
* [NYQUIST] Fix build on CYGWIN

Cygwin requires to include unistd.h for building without errors.

* [NYQUIST] Fix build on CYGWIN.

Cygwin requires to include endian.h to build without errors.
2020-06-03 13:13:41 -05:00

178 lines
5.1 KiB
C

/* security.c -- manage access to files and audio */
/* Roger B. Dannenberg
* July 2014
*/
#include <stdlib.h>
#if defined(UNIX) || defined(__APPLE__) || defined(__CYGWIN__)
#include <unistd.h>
#endif
#ifdef WIN32
#include <direct.h>
#endif
#include <string.h>
#include <xlisp.h>
static void find_full_path(const char *filename, char *fullname);
static int in_tree(const char *fullname, char *secure_read_path);
static int full_name(const char *filename);
static int file_sep(char c);
/* run_time_limit is a feature to shut down infinite loops
* calls to oscheck are counted. These occur at around 66Hz
* on a 2010 vintage laptop, so a value of 66 is roughly 1 CPU
* second of computation. The rate fluctuates depending on
* the computation, so it is a very rough guide, but then if
* you are restricting CPU time, you'll probably want to pad
* the expected time by a factor of at least 2, so hopefully
* exact numbers are not important. The default is 0, meaning
* no limit. Set the limit from the command line with -L.
* Read the current run time by calling (GET-RUN-TIME)
*/
int run_time_limit = 0;
/* memory_limit is a feature to shut down rampant memory
* allocation which tends to lead to thrashing on a virtual
* (memory) machine. The number is roughly the number of
* megabytes of sample and cons cell memory that can be
* allocated. The default is 0 which means no limit.
*/
int memory_limit = 0;
/* run_time is the current run time -- incremented by oscheck() */
int run_time = 0;
/* secure_read_path is NULL if reading any file is permitted
* o.w. secure_read_path is a semicolon-separated list of
* paths to directory trees that are readable
*/
char *secure_read_path = NULL;
/* safe_write_path is NULL if writing any file is permitted
* o.w. safe_write_path is a semicolon-separated list of
* paths to directory tress that are writeable
*/
char *safe_write_path = NULL;
/* ok_to_open - true if it is OK to open the file under
* the security model implied by secure_read_path
* and safe_write_path
*/
int ok_to_open(const char *filename, const char *mode)
{
char fullname[STRMAX];
if (strchr(mode, 'r')) { /* asking for read permission */
if (secure_read_path) { /* filename must be in path */
find_full_path(filename, fullname);
if (!in_tree(fullname, secure_read_path)) return FALSE;
}
}
if (strchr(mode, 'w')) { /* asking for write permission */
if (safe_write_path) { /* filename must be in path */
find_full_path(filename, fullname);
if (!in_tree(fullname, safe_write_path)) return FALSE;
}
}
return TRUE;
}
/* find_full_path - find full path corresponding to filename */
/**/
void find_full_path(const char *filename, char *fullname)
{
if (full_name(filename)) {
strncpy(fullname, filename, STRMAX);
fullname[STRMAX - 1] = 0;
return;
}
if (!getcwd(fullname, STRMAX)) {
/* something is really wrong. Pretend we found a
cwd that will not match anything */
goto error;
}
/* see if we need a separator (probably) */
int len = strlen(fullname);
if (!file_sep(fullname[len - 1])) {
fullname[len++] = '/';
if (len >= STRMAX) goto error;
}
/* append filename to fullname */
strncpy(fullname + len, filename, STRMAX - len);
fullname[STRMAX - 1] = 0; /* just in case of overflow */
/* if windows, replace \ with / to simplify the rest */
char *loc = fullname;
if (os_pathchar != '/') {
while ((loc = strchr(loc, os_pathchar))) {
*loc = '/';
}
}
/* strip out .. and . */
while ((loc = strstr(fullname, "/.."))) {
/* back up to separator */
if (loc == fullname) goto error;
char *loc2 = loc - 1;
while (*loc2 != '/') {
loc2--;
if (loc2 <= fullname) goto error;
}
/* now loc2 points to /parent/.., and loc points to /.. */
/* copy from beyond /.. to loc2 */
memmove(loc2, loc, strlen(loc) + 1);
}
return;
error:
strcpy(fullname, "//////");
return;
}
static int file_sep(char c)
{
return (c == os_pathchar || c == '/');
}
/* full_name - test if filename is a full path */
/**/
static int full_name(const char *filename)
{
if (!filename) return FALSE;
if (filename[0] == os_pathchar) return TRUE;
/* windows allows '/' instead of '\' */
if (filename[0] == '/') return TRUE;
if (strlen(filename) > 2 &&
isalpha(filename[0]) &&
filename[1] == ':') return TRUE;
return FALSE;
}
static int in_tree(const char *fullname, char *secure_read_path)
{
/* fullname is in a tree if a path in secure_read_path
is a prefix of fullname
Algorithm: extract each path, check for prefix
*/
char path[STRMAX];
while (secure_read_path && *secure_read_path) {
/* skip over separator */
while (*secure_read_path == os_sepchar ||
*secure_read_path == ';') secure_read_path++;
/* find next directory and copy into path*/
path[0] = 0;
int i = 0;
while (*secure_read_path && (*secure_read_path != os_sepchar &&
*secure_read_path != ';')) {
path[i++] = *secure_read_path++;
}
path[i] = 0;
/* see if directory is a prefix of fullname */
if (strstr(fullname, path) == fullname) {
return TRUE;
}
}
return FALSE;
}