The UPnP protocol specification mandates that subscribers can request a
callback to an arbitrary URL. This recently resulted in CVE-2020-12695
(CallStranger) outlining the risk of information disclosure and DoS
attacks.
This commit ensures that the callback URL sent in a SUBSCRIBE request
points to the same IP address that made the request.
The idea is taken from the nginx web server, but much simplified and
almost no copypaste left. This will allow minidlna to use different
event dispatcher APIs, which would be defined at compile time.
My personal goal is to convert minidlna to kqueue(2) on FreeBSD. This
would later allow for kqueue based directory change notification, which
won't conflict with select(2) like the current patch does.
Other platforms will also benefit from the pluggability of the event
system, Linux can switch to epoll(2) or at least to poll(2).
Detailed list of changes:
* event.h [New]
Our internal API to unify different event dispatch systems.
* select.c [New]
Much simplified version of nginx's ngx_select_module.c.
* minidlna.c
- Split out listen socket event processing into separate function
ProcessListen(), which matches event_process_t type.
- Create and initialize struct event for the monitor socket, SSDP
socket, HTTP socket and beacon socket.
- Simplify and make more precise timeout calculation using
helper timeval functions from utils.c. Treat gettimeofday() error
as a fatal event.
- Rip out all stuff related to select(2). Just call event_module.process().
* upnpevents.c
- Embed struct event into upnp_event_notify.
- Merge upnp_event_create_notify() with upnp_event_notify_connect().
Start connecting immediately after socket creation. Garbage collect
now useless ECreated state.
- Make upnp_event_process_notify() of event_process_t type, and use it
as process callback for upnp_event_notify event.
- Looks like we always create upnp_event_notify with existing subscriber,
and never clear it later. Remove checks for obj->sub and assert that it
is never NULL. Simplifies things.
- When switching obj state, add/del it to event dispatcher accrodingly.
- Garbage collect upnpevents_selectfds().
- Garbage collect select(2) related stuff from upnpevents_processfds().
Rename function to upnpevents_gc(), since the remaining functionality
is garbage collecting, not file descriptor processing.
Actually, this can be simplified even more. We can safely close sockets
and free objects immediately, eliminating need for upnpevents_gc(). But
this change would be beyond scope of this commit.
* upnphttp.c, upnphttp.h
Embed struct event into struct upnphttp. Adjust Process_upnphttp() to match
event_process_t type. Add/del to event dispatcher once creating/closing a
socket.
* minissdp.c, minissdp.h
Make ProcessSSDPRequest() of event_process_t type.
* getifaddr.c, getifaddr.h
Make ProcessMonitorEvent() of event_process_t type.
Fix several issues with the non-destructive rescan functionality.
Most of these issues also affected inotify scanning as well. These
include annoying debug messages, adding album art for files that we
aren't supposed to be scanning anyway, incrementing the UpdateID when no
changes were made to the database, and other smaller issues.
Embedded thumbnails may have an undesirable orientation, so
we should do our own scaling with inline rotation if the
thumbnail image needs to be rotated.
Advertising the DCM10 vendor-specific feature to Samsung Series
C and D (at least) players causes them to always browse ContainerID
1, no matter which section is chosen from their GUI.
Treat TVs and BDPs as separate client types with unique features.