|
@@ -1,133 +0,0 @@
|
|
|
-From 51bfbee51fd0376b5a66c944134af3e9972d8592 Mon Sep 17 00:00:00 2001
|
|
|
-From: Fabrice Fontaine <fontaine.fabrice@gmail.com>
|
|
|
-Date: Sun, 6 Sep 2020 11:22:48 +0200
|
|
|
-Subject: [PATCH] upnphttp.c: fix CallStranger a.k.a. CVE-2020-12695
|
|
|
-
|
|
|
-Import CheckCallback function from miniupnpd source code:
|
|
|
-https://github.com/miniupnp/miniupnp/commit/0d9634658860c3c8c209e466cc0ef7002bad3b0a
|
|
|
-
|
|
|
-IPv6 code was kept even if minidlna does not support it currently.
|
|
|
-
|
|
|
-This code is licensed under BSD-3-Clause like minidlna.
|
|
|
-
|
|
|
-Signed-off-by: Fabrice Fontaine <fontaine.fabrice@gmail.com>
|
|
|
-[Upstream status:
|
|
|
-https://sourceforge.net/p/minidlna/support-requests/71]
|
|
|
----
|
|
|
- upnphttp.c | 92 ++++++++++++++++++++++++++++++++++++++++++++++++------
|
|
|
- 1 file changed, 82 insertions(+), 10 deletions(-)
|
|
|
-
|
|
|
-diff --git a/upnphttp.c b/upnphttp.c
|
|
|
-index 974434e..3be793e 100644
|
|
|
---- a/upnphttp.c
|
|
|
-+++ b/upnphttp.c
|
|
|
-@@ -742,6 +742,70 @@ check_event(struct upnphttp *h)
|
|
|
- return type;
|
|
|
- }
|
|
|
-
|
|
|
-+/**
|
|
|
-+ * returns 0 if the callback header value is not valid
|
|
|
-+ * 1 if it is valid.
|
|
|
-+ */
|
|
|
-+static int
|
|
|
-+checkCallbackURL(struct upnphttp * h)
|
|
|
-+{
|
|
|
-+ char addrstr[48];
|
|
|
-+ int ipv6;
|
|
|
-+ const char * p;
|
|
|
-+ int i;
|
|
|
-+
|
|
|
-+ if(!h->req_Callback || h->req_CallbackLen < 8)
|
|
|
-+ return 0;
|
|
|
-+ if(memcmp(h->req_Callback, "http://", 7) != 0)
|
|
|
-+ return 0;
|
|
|
-+ ipv6 = 0;
|
|
|
-+ i = 0;
|
|
|
-+ p = h->req_Callback + 7;
|
|
|
-+ if(*p == '[') {
|
|
|
-+ p++;
|
|
|
-+ ipv6 = 1;
|
|
|
-+ while(*p != ']' && i < (sizeof(addrstr)-1)
|
|
|
-+ && p < (h->req_Callback + h->req_CallbackLen))
|
|
|
-+ addrstr[i++] = *(p++);
|
|
|
-+ } else {
|
|
|
-+ while(*p != '/' && *p != ':' && i < (sizeof(addrstr)-1)
|
|
|
-+ && p < (h->req_Callback + h->req_CallbackLen))
|
|
|
-+ addrstr[i++] = *(p++);
|
|
|
-+ }
|
|
|
-+ addrstr[i] = '\0';
|
|
|
-+ if(ipv6) {
|
|
|
-+ struct in6_addr addr;
|
|
|
-+ if(inet_pton(AF_INET6, addrstr, &addr) <= 0)
|
|
|
-+ return 0;
|
|
|
-+#ifdef ENABLE_IPV6
|
|
|
-+ if(!h->ipv6
|
|
|
-+ || (0!=memcmp(&addr, &(h->clientaddr_v6), sizeof(struct in6_addr))))
|
|
|
-+ return 0;
|
|
|
-+#else
|
|
|
-+ return 0;
|
|
|
-+#endif
|
|
|
-+ } else {
|
|
|
-+ struct in_addr addr;
|
|
|
-+ if(inet_pton(AF_INET, addrstr, &addr) <= 0)
|
|
|
-+ return 0;
|
|
|
-+#ifdef ENABLE_IPV6
|
|
|
-+ if(h->ipv6) {
|
|
|
-+ if(!IN6_IS_ADDR_V4MAPPED(&(h->clientaddr_v6)))
|
|
|
-+ return 0;
|
|
|
-+ if(0!=memcmp(&addr, ((const char *)&(h->clientaddr_v6) + 12), 4))
|
|
|
-+ return 0;
|
|
|
-+ } else {
|
|
|
-+ if(0!=memcmp(&addr, &(h->clientaddr), sizeof(struct in_addr)))
|
|
|
-+ return 0;
|
|
|
-+ }
|
|
|
-+#else
|
|
|
-+ if(0!=memcmp(&addr, &(h->clientaddr), sizeof(struct in_addr)))
|
|
|
-+ return 0;
|
|
|
-+#endif
|
|
|
-+ }
|
|
|
-+ return 1;
|
|
|
-+}
|
|
|
-+
|
|
|
- static void
|
|
|
- ProcessHTTPSubscribe_upnphttp(struct upnphttp * h, const char * path)
|
|
|
- {
|
|
|
-@@ -759,17 +823,25 @@ ProcessHTTPSubscribe_upnphttp(struct upnphttp * h, const char * path)
|
|
|
- * - respond HTTP/x.x 200 OK
|
|
|
- * - Send the initial event message */
|
|
|
- /* Server:, SID:; Timeout: Second-(xx|infinite) */
|
|
|
-- sid = upnpevents_addSubscriber(path, h->req_Callback,
|
|
|
-- h->req_CallbackLen, h->req_Timeout);
|
|
|
-- h->respflags = FLAG_TIMEOUT;
|
|
|
-- if (sid)
|
|
|
-- {
|
|
|
-- DPRINTF(E_DEBUG, L_HTTP, "generated sid=%s\n", sid);
|
|
|
-- h->respflags |= FLAG_SID;
|
|
|
-- h->req_SID = sid;
|
|
|
-- h->req_SIDLen = strlen(sid);
|
|
|
-+ /* Check that the callback URL is on the same IP as
|
|
|
-+ * the request, and not on the internet, nor on ourself (DOS attack ?) */
|
|
|
-+ if(checkCallbackURL(h)) {
|
|
|
-+ sid = upnpevents_addSubscriber(path, h->req_Callback,
|
|
|
-+ h->req_CallbackLen, h->req_Timeout);
|
|
|
-+ h->respflags = FLAG_TIMEOUT;
|
|
|
-+ if (sid)
|
|
|
-+ {
|
|
|
-+ DPRINTF(E_DEBUG, L_HTTP, "generated sid=%s\n", sid);
|
|
|
-+ h->respflags |= FLAG_SID;
|
|
|
-+ h->req_SID = sid;
|
|
|
-+ h->req_SIDLen = strlen(sid);
|
|
|
-+ }
|
|
|
-+ BuildResp_upnphttp(h, 0, 0);
|
|
|
-+ } else {
|
|
|
-+ DPRINTF(E_WARN, L_HTTP, "Invalid Callback in SUBSCRIBE %.*s",
|
|
|
-+ h->req_CallbackLen, h->req_Callback);
|
|
|
-+ BuildResp2_upnphttp(h, 412, "Precondition Failed", 0, 0);
|
|
|
- }
|
|
|
-- BuildResp_upnphttp(h, 0, 0);
|
|
|
- }
|
|
|
- else if (type == E_RENEW)
|
|
|
- {
|
|
|
---
|
|
|
-2.28.0
|
|
|
-
|