options: Add wide_links config option.
In some environments, it makes sense to validate that symlink destinations remain inside user-defined media_dirs. Make this behavior configurable.
This commit is contained in:
79
upnphttp.c
79
upnphttp.c
@ -477,6 +477,21 @@ Send400(struct upnphttp * h)
|
||||
CloseSocket_upnphttp(h);
|
||||
}
|
||||
|
||||
/* very minimalistic 403 error message */
|
||||
static void
|
||||
Send403(struct upnphttp * h)
|
||||
{
|
||||
static const char body403[] =
|
||||
"<HTML><HEAD><TITLE>403 Forbidden</TITLE></HEAD>"
|
||||
"<BODY><H1>Forbidden</H1>You don't have permission to access this resource."
|
||||
"</BODY></HTML>\r\n";
|
||||
h->respflags = FLAG_HTML;
|
||||
BuildResp2_upnphttp(h, 403, "Forbidden",
|
||||
body403, sizeof(body403) - 1);
|
||||
SendResp_upnphttp(h);
|
||||
CloseSocket_upnphttp(h);
|
||||
}
|
||||
|
||||
/* very minimalistic 404 error message */
|
||||
static void
|
||||
Send404(struct upnphttp * h)
|
||||
@ -1328,6 +1343,46 @@ start_dlna_header(struct string_s *str, int respcode, const char *tmode, const c
|
||||
respcode, date, tmode, mime);
|
||||
}
|
||||
|
||||
static int
|
||||
_open_file(const char *orig_path)
|
||||
{
|
||||
struct media_dir_s *media_path;
|
||||
char buf[PATH_MAX];
|
||||
const char *path;
|
||||
int fd;
|
||||
|
||||
if (!GETFLAG(WIDE_LINKS_MASK))
|
||||
{
|
||||
path = realpath(orig_path, buf);
|
||||
if (!path)
|
||||
{
|
||||
DPRINTF(E_ERROR, L_HTTP, "Error resolving path %s: %s\n",
|
||||
orig_path, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (media_path = media_dirs; media_path; media_path = media_path->next)
|
||||
{
|
||||
if (strncmp(path, media_path->path, strlen(media_path->path)) == 0)
|
||||
break;
|
||||
}
|
||||
if (!media_path && strncmp(path, db_path, strlen(db_path)))
|
||||
{
|
||||
DPRINTF(E_ERROR, L_HTTP, "Rejecting wide link %s -> %s\n",
|
||||
orig_path, path);
|
||||
return -403;
|
||||
}
|
||||
}
|
||||
else
|
||||
path = orig_path;
|
||||
|
||||
fd = open(path, O_RDONLY);
|
||||
if (fd < 0)
|
||||
DPRINTF(E_ERROR, L_HTTP, "Error opening %s\n", path);
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
static void
|
||||
SendResp_icon(struct upnphttp * h, char * icon)
|
||||
{
|
||||
@ -1413,11 +1468,13 @@ SendResp_albumArt(struct upnphttp * h, char * object)
|
||||
}
|
||||
DPRINTF(E_INFO, L_HTTP, "Serving album art ID: %lld [%s]\n", id, path);
|
||||
|
||||
fd = open(path, O_RDONLY);
|
||||
fd = _open_file(path);
|
||||
if( fd < 0 ) {
|
||||
DPRINTF(E_ERROR, L_HTTP, "Error opening %s\n", path);
|
||||
sqlite3_free(path);
|
||||
Send404(h);
|
||||
if (fd == -403)
|
||||
Send403(h);
|
||||
else
|
||||
Send404(h);
|
||||
return;
|
||||
}
|
||||
sqlite3_free(path);
|
||||
@ -1461,11 +1518,13 @@ SendResp_caption(struct upnphttp * h, char * object)
|
||||
}
|
||||
DPRINTF(E_INFO, L_HTTP, "Serving caption ID: %lld [%s]\n", id, path);
|
||||
|
||||
fd = open(path, O_RDONLY);
|
||||
fd = _open_file(path);
|
||||
if( fd < 0 ) {
|
||||
DPRINTF(E_ERROR, L_HTTP, "Error opening %s\n", path);
|
||||
sqlite3_free(path);
|
||||
Send404(h);
|
||||
if (fd == -403)
|
||||
Send403(h);
|
||||
else
|
||||
Send404(h);
|
||||
return;
|
||||
}
|
||||
sqlite3_free(path);
|
||||
@ -1914,10 +1973,12 @@ SendResp_dlnafile(struct upnphttp *h, char *object)
|
||||
}
|
||||
|
||||
offset = h->req_RangeStart;
|
||||
sendfh = open(last_file.path, O_RDONLY);
|
||||
sendfh = _open_file(last_file.path);
|
||||
if( sendfh < 0 ) {
|
||||
DPRINTF(E_ERROR, L_HTTP, "Error opening %s\n", last_file.path);
|
||||
Send404(h);
|
||||
if (sendfh == -403)
|
||||
Send403(h);
|
||||
else
|
||||
Send404(h);
|
||||
goto error;
|
||||
}
|
||||
size = lseek(sendfh, 0, SEEK_END);
|
||||
|
Reference in New Issue
Block a user