diff --git a/upnphttp.c b/upnphttp.c index 974434e..1fbb242 100644 --- a/upnphttp.c +++ b/upnphttp.c @@ -699,7 +699,7 @@ ProcessHTTPPOST_upnphttp(struct upnphttp * h) static int check_event(struct upnphttp *h) { - enum event_type type; + enum event_type type = E_INVALID; if (h->req_Callback) { @@ -707,7 +707,6 @@ check_event(struct upnphttp *h) { BuildResp2_upnphttp(h, 400, "Bad Request", "Bad request", 37); - type = E_INVALID; } else if (strncmp(h->req_Callback, "http://", 7) != 0 || strncmp(h->req_NT, "upnp:event", h->req_NTLen) != 0) @@ -716,10 +715,30 @@ check_event(struct upnphttp *h) * If CALLBACK header is missing or does not contain a valid HTTP URL, * the publisher must respond with HTTP error 412 Precondition Failed*/ BuildResp2_upnphttp(h, 412, "Precondition Failed", 0, 0); - type = E_INVALID; } else - type = E_SUBSCRIBE; + { + /* Make sure callback URL points to the originating IP */ + struct in_addr addr; + char addrstr[16]; + int i = 0; + const char *p = h->req_Callback + 7; + while (!strchr("/:>", *p) && i < sizeof(addrstr) - 1 && + p < (h->req_Callback + h->req_CallbackLen)) + { + addrstr[i++] = *(p++); + } + addrstr[i] = '\0'; + + if (inet_pton(AF_INET, addrstr, &addr) <= 0 || + memcmp(&addr, &h->clientaddr, sizeof(struct in_addr))) + { + DPRINTF(E_ERROR, L_HTTP, "Bad callback IP (%s)\n", addrstr); + BuildResp2_upnphttp(h, 412, "Precondition Failed", 0, 0); + } + else + type = E_SUBSCRIBE; + } } else if (h->req_SID) { @@ -728,7 +747,6 @@ check_event(struct upnphttp *h) { BuildResp2_upnphttp(h, 400, "Bad Request", "Bad request", 37); - type = E_INVALID; } else type = E_RENEW; @@ -736,7 +754,6 @@ check_event(struct upnphttp *h) else { BuildResp2_upnphttp(h, 412, "Precondition Failed", 0, 0); - type = E_INVALID; } return type;