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:
Justin Maggard
2015-12-21 14:31:52 -08:00
parent 4ec6cd0053
commit c4166b3e77
7 changed files with 86 additions and 11 deletions

View File

@ -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);