#ifdef HAVE_CONFIG_H # include "config.h" #endif /* HAVE_CONFIG_H */ #ifdef HAVE_ERRNO_H #include #endif /* HAVE_ERRNO_H */ #include /* See NOTES */ #include #include #include #include #include #include #include #include #include "Escape.h" char * escape_realpath(const char *path, char *resolved_path) { char *real = lrealpath (path); if (real) { if (resolved_path) { memcpy (resolved_path, real, PATH_MAX); free (real); return resolved_path; } else { return real; } } return NULL; } int escape_access(const char *pathname, int mode) { struct stat stat_buf; if (stat(pathname, &stat_buf) != 0) return -1; if (mode == F_OK) return 0; if (mode == R_OK) { if (stat_buf.st_mode & S_IRUSR) return 0; errno = EACCES; return -1; } if (mode == W_OK) { if (stat_buf.st_mode & S_IWUSR) return 0; errno = EROFS; return -1; } if (mode == X_OK) { if (stat_buf.st_mode & S_IXUSR) return 0; errno = EACCES; return -1; } return 0; } EAPI ssize_t escape_readlink(const char *path, char *buf, size_t bufsize) { errno = EINVAL; return -1; } EAPI int escape_symlink(const char *path1, const char *path2) { errno = EINVAL; return -1; } /* * The code of the following functions has been kindly offered * by Tor Lillqvist. */ int escape_pipe(int *fds) { struct sockaddr_in saddr; int temp; int socket1 = -1; int socket2 = -1; fd_set read_set; fd_set write_set; int len; temp = socket (AF_INET, SOCK_STREAM, 0); if (temp == -1) goto out0; memset (&saddr, 0, sizeof (saddr)); saddr.sin_family = AF_INET; saddr.sin_port = 0; saddr.sin_addr.s_addr = htonl (INADDR_LOOPBACK); if (bind (temp, (struct sockaddr *)&saddr, sizeof (saddr))) goto out0; if (listen (temp, 1) == -1) goto out0; len = sizeof (saddr); if (getsockname (temp, (struct sockaddr *)&saddr, &len)) goto out0; socket1 = socket (AF_INET, SOCK_STREAM, 0); if (socket1 == -1) goto out0; if ((connect (socket1, (struct sockaddr *)&saddr, len) == -1) && (errno != EAGAIN)) goto out1; FD_ZERO (&read_set); FD_SET (temp, &read_set); if (select (0, &read_set, NULL, NULL, NULL) == -1) goto out1; if (!FD_ISSET (temp, &read_set)) goto out1; socket2 = accept (temp, (struct sockaddr *)&saddr, &len); if (socket2 == -1) goto out1; FD_ZERO (&write_set); FD_SET (socket1, &write_set); if (select (0, NULL, &write_set, NULL, NULL) == -1) goto out2; if (!FD_ISSET (socket1, &write_set)) goto out2; fds[0] = socket1; fds[1] = socket2; closesocket (temp); return 0; out2: closesocket (socket2); out1: closesocket (socket1); out0: closesocket (temp); fds[0] = -1; fds[1] = -1; return -1; } #undef access int access(const char *pathname, int mode) { return escape_access (pathname, mode); }