From e644f219fa5c4409fa97dacc72032cef9588ceb1 Mon Sep 17 00:00:00 2001
From: Thomas Bernard <miniupnp@free.fr>
Date: Sat, 13 Dec 2014 19:10:39 +0100
Subject: [PATCH] miniupnpc-libevent: check SID and other headers in event
 NOTIFY

---
 miniupnpc-libevent/miniupnpc-libevent.c | 34 ++++++++++++++++++++-----
 miniupnpc-libevent/miniupnpc-libevent.h |  3 +++
 2 files changed, 30 insertions(+), 7 deletions(-)

diff --git a/miniupnpc-libevent/miniupnpc-libevent.c b/miniupnpc-libevent/miniupnpc-libevent.c
index 12ff33b..4239b29 100644
--- a/miniupnpc-libevent/miniupnpc-libevent.c
+++ b/miniupnpc-libevent/miniupnpc-libevent.c
@@ -431,6 +431,11 @@ static void upnpc_subscribe_response(struct evhttp_request * req, void * pvoid)
 		struct evkeyvalq * headers = evhttp_request_get_input_headers(req);
 		sid = evhttp_find_header(headers, "sid");
 		debug_printf("SID=%s\n", sid);
+		if(sid) {
+			if(d->event_conn_sid)
+				free(d->event_conn_sid);
+			d->event_conn_sid = strdup(sid);
+		}
 	}
 }
 #endif /* ENABLE_UPNP_EVENTS */
@@ -639,28 +644,39 @@ void upnpc_event_conn_req(struct evhttp_request * req, void * data)
 	struct evkeyvalq * headers;
 	const char * sid;
 	const char * nts;
+	const char * nt;
 	const char * seq;
 	struct NameValueParserData parsed_data;
 	struct NameValue * nv;
 	upnpc_device_t * d = (upnpc_device_t *)data;
 
 	debug_printf("%s(%p, %p)\n", __func__, req, d);
+	headers = evhttp_request_get_input_headers(req);
 	input_buffer = evhttp_request_get_input_buffer(req);
 	len = evbuffer_get_length(input_buffer);
-	if(len == 0) {
-		evhttp_send_reply(req, 406, "Not Acceptable", NULL);
-		return;
-	}
-	xml_data = (char *)evbuffer_pullup(input_buffer, len);
-	headers = evhttp_request_get_input_headers(req);
 	sid = evhttp_find_header(headers, "sid");
 	nts = evhttp_find_header(headers, "nts");
+	nt = evhttp_find_header(headers, "nt");
 	seq = evhttp_find_header(headers, "seq");
+	if(len == 0 || nts == NULL || nt == NULL) {
+		/* 400 Bad request :
+		 * The NT or NTS header field is missing
+		 * or the request is malformed. */
+		evhttp_send_reply(req, 400, "Bad Request", NULL);
+		return;
+	}
 	debug_printf("SID=%s NTS=%s SEQ=%s\n", sid, nts, seq);
-	if(sid == NULL || nts == NULL || seq == NULL) {
+	if(sid == NULL || 0 != strcmp(sid, d->event_conn_sid)
+	   || 0 != strcmp(nt, "upnp:event") || 0 != strcmp(nts, "upnp:propchange")) {
+		/* 412 Precondition Failed :
+		 *  An SID does not correspond to a known, un-expired subscription
+		 *  or the NT header field does not equal upnp:event
+		 *  or the NTS header field does not equal upnp:propchange
+		 *  or the SID header field is missing or empty.  */
 		evhttp_send_reply(req, 412, "Precondition Failed", NULL);
 		return;
 	}
+	xml_data = (char *)evbuffer_pullup(input_buffer, len);
 	/*debug_printf("%.*s\n", len, xml_data);*/
 	ParseNameValue(xml_data, len, &parsed_data);
 	for(nv = parsed_data.l_head; nv != NULL; nv = nv->l_next) {
@@ -798,6 +814,10 @@ static void upnpc_device_finalize(upnpc_device_t * d)
 		d->soap_conn = NULL;
 	}
 	ClearNameValueList(&d->soap_response_data);
+#ifdef ENABLE_UPNP_EVENTS
+	free(d->event_conn_sid);
+	d->event_conn_sid = NULL;
+#endif /* ENABLE_UPNP_EVENTS */
 }
 
 int upnpc_finalize(upnpc_t * p)
diff --git a/miniupnpc-libevent/miniupnpc-libevent.h b/miniupnpc-libevent/miniupnpc-libevent.h
index 0c97588..c7fca09 100644
--- a/miniupnpc-libevent/miniupnpc-libevent.h
+++ b/miniupnpc-libevent/miniupnpc-libevent.h
@@ -67,6 +67,9 @@ struct upnpc_device {
 	struct evhttp_connection * soap_conn;
 	struct NameValueParserData soap_response_data;
 	unsigned int state;
+#ifdef ENABLE_UPNP_EVENTS
+	char * event_conn_sid;
+#endif /* ENABLE_UPNP_EVENTS */
 };
 
 struct upnpc {