static void ProcessHTTPSubscribe_upnphttp(struct upnphttp * h, const char * path) { const char * sid; syslog(LOG_DEBUG, "ProcessHTTPSubscribe %s", path); syslog(LOG_DEBUG, "Callback '%.*s' Timeout=%d", h->req_CallbackLen, h->req_Callback, h->req_Timeout); syslog(LOG_DEBUG, "SID '%.*s'", h->req_SIDLen, h->req_SID); if(!h->req_Callback && !h->req_SID) { /* Missing or invalid CALLBACK : 412 Precondition Failed. * 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); SendResp_upnphttp(h); CloseSocket_upnphttp(h); } else { /* - add to the subscriber list * - respond HTTP/x.x 200 OK * - Send the initial event message */ /* Server:, SID:; Timeout: Second-(xx|infinite) */ /* Check that the callback URL is on the same IP as * the request, and not on the internet, nor on ourself (DOS attack ?) */ if(h->req_Callback) { if(checkCallbackURL(h)) { sid = upnpevents_addSubscriber(path, h->req_Callback, h->req_CallbackLen, h->req_Timeout); h->respflags = FLAG_TIMEOUT; if(sid) { syslog(LOG_DEBUG, "generated sid=%s", sid); h->respflags |= FLAG_SID; h->req_SID = sid; h->req_SIDLen = strlen(sid); } BuildResp_upnphttp(h, 0, 0); } else { syslog(LOG_WARNING, "Invalid Callback in SUBSCRIBE %.*s", h->req_CallbackLen, h->req_Callback); BuildResp2_upnphttp(h, 412, "Precondition Failed", 0, 0); } } else { /* subscription renew */ /* Invalid SID 412 Precondition Failed. If a SID does not correspond to a known, un-expired subscription, the publisher must respond with HTTP error 412 Precondition Failed. */ if(renewSubscription(h->req_SID, h->req_SIDLen, h->req_Timeout) < 0) { BuildResp2_upnphttp(h, 412, "Precondition Failed", 0, 0); } else { h->respflags = FLAG_TIMEOUT; BuildResp_upnphttp(h, 0, 0); } } SendResp_upnphttp(h); CloseSocket_upnphttp(h); } }
static void ProcessHTTPSubscribe_upnphttp(struct upnphttp * h, const char * path) { const char * sid; syslog(LOG_DEBUG, "ProcessHTTPSubscribe %s", path); syslog(LOG_DEBUG, "Callback '%.*s' Timeout=%d", h->req_CallbackLen, h->req_buf + h->req_CallbackOff, h->req_Timeout); syslog(LOG_DEBUG, "SID '%.*s'", h->req_SIDLen, h->req_buf + h->req_SIDOff); if((h->req_CallbackOff <= 0) && (h->req_SIDOff <= 0)) { /* Missing or invalid CALLBACK : 412 Precondition Failed. * 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); SendRespAndClose_upnphttp(h); } else { /* - add to the subscriber list * - respond HTTP/x.x 200 OK * - Send the initial event message */ /* Server:, SID:; Timeout: Second-(xx|infinite) */ /* Check that the callback URL is on the same IP as * the request, and not on the internet, nor on ourself (DOS attack ?) */ if(h->req_CallbackOff > 0) { #ifdef UPNP_STRICT /* SID: and Callback: are incompatible */ if(h->req_SIDOff > 0) { syslog(LOG_WARNING, "Both Callback: and SID: in SUBSCRIBE"); BuildResp2_upnphttp(h, 400, "Incompatible header fields", 0, 0); /* "NT: upnp:event" header is mandatory */ } else if(h->req_NTOff <= 0 || h->req_NTLen != 10 || 0 != memcmp("upnp:event", h->req_buf + h->req_NTOff, 10)) { syslog(LOG_WARNING, "Invalid NT in SUBSCRIBE %.*s", h->req_NTLen, h->req_buf + h->req_NTOff); BuildResp2_upnphttp(h, 412, "Precondition Failed", 0, 0); } else #endif if(checkCallbackURL(h)) { sid = upnpevents_addSubscriber(path, h->req_buf + h->req_CallbackOff, h->req_CallbackLen, h->req_Timeout); h->respflags = FLAG_TIMEOUT; if(sid) { syslog(LOG_DEBUG, "generated sid=%s", sid); h->respflags |= FLAG_SID; h->res_SID = sid; } BuildResp_upnphttp(h, 0, 0); } else { syslog(LOG_WARNING, "Invalid Callback in SUBSCRIBE %.*s", h->req_CallbackLen, h->req_buf + h->req_CallbackOff); BuildResp2_upnphttp(h, 412, "Precondition Failed", 0, 0); } } else { /* subscription renew */ /* Invalid SID 412 Precondition Failed. If a SID does not correspond to a known, un-expired subscription, the publisher must respond with HTTP error 412 Precondition Failed. */ #ifdef UPNP_STRICT /* SID: and NT: headers are incompatibles */ if(h->req_NTOff > 0) { syslog(LOG_WARNING, "Both NT: and SID: in SUBSCRIBE"); BuildResp2_upnphttp(h, 400, "Incompatible header fields", 0, 0); } else #endif if(renewSubscription(h->req_buf + h->req_SIDOff, h->req_SIDLen, h->req_Timeout) < 0) { BuildResp2_upnphttp(h, 412, "Precondition Failed", 0, 0); } else { h->respflags = FLAG_TIMEOUT; BuildResp_upnphttp(h, 0, 0); } } SendRespAndClose_upnphttp(h); } }
static void ProcessHTTPSubscribe_upnphttp(struct upnphttp * h, const char * path) { const char * sid; syslog(LOG_DEBUG, "ProcessHTTPSubscribe %s", path); syslog(LOG_DEBUG, "Callback '%.*s' Timeout=%d", h->req_CallbackLen, h->req_buf + h->req_CallbackOff, h->req_Timeout); syslog(LOG_DEBUG, "SID '%.*s'", h->req_SIDLen, h->req_buf + h->req_SIDOff); #if defined(UPNP_STRICT) && (UPNP_VERSION_MAJOR > 1) || (UPNP_VERSION_MINOR > 0) /*if(h->req_Timeout < 1800) {*/ if(h->req_Timeout == 0) { /* Second-infinite is forbidden with UDA v1.1 and later : * (UDA 1.1 : 4.1.1 Subscription) * UPnP 1.1 control points MUST NOT subscribe using keyword infinite, * UPnP 1.1 devices MUST NOT set actual subscription durations to * "infinite". The presence of infinite in a request MUST be silently * ignored by a UPnP 1.1 device (the presence of infinite is handled * by the device as if the TIMEOUT header field in a request was not * present) . The keyword infinite MUST NOT be returned by a UPnP 1.1 * device. */ h->req_Timeout = 1800; /* default to 30 minutes */ } #endif /* UPNP_STRICT */ if((h->req_CallbackOff <= 0) && (h->req_SIDOff <= 0)) { /* Missing or invalid CALLBACK : 412 Precondition Failed. * 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); SendRespAndClose_upnphttp(h); } else { /* - add to the subscriber list * - respond HTTP/x.x 200 OK * - Send the initial event message */ /* Server:, SID:; Timeout: Second-(xx|infinite) */ /* Check that the callback URL is on the same IP as * the request, and not on the internet, nor on ourself (DOS attack ?) */ if(h->req_CallbackOff > 0) { #ifdef UPNP_STRICT /* SID: and Callback: are incompatible */ if(h->req_SIDOff > 0) { syslog(LOG_WARNING, "Both Callback: and SID: in SUBSCRIBE"); BuildResp2_upnphttp(h, 400, "Incompatible header fields", 0, 0); /* "NT: upnp:event" header is mandatory */ } else if(h->req_NTOff <= 0 || h->req_NTLen != 10 || 0 != memcmp("upnp:event", h->req_buf + h->req_NTOff, 10)) { syslog(LOG_WARNING, "Invalid NT in SUBSCRIBE %.*s", h->req_NTLen, h->req_buf + h->req_NTOff); BuildResp2_upnphttp(h, 412, "Precondition Failed", 0, 0); } else #endif if(checkCallbackURL(h)) { sid = upnpevents_addSubscriber(path, h->req_buf + h->req_CallbackOff, h->req_CallbackLen, h->req_Timeout); h->respflags = FLAG_TIMEOUT; if(sid) { syslog(LOG_DEBUG, "generated sid=%s", sid); h->respflags |= FLAG_SID; h->res_SID = sid; } BuildResp_upnphttp(h, 0, 0); } else { syslog(LOG_WARNING, "Invalid Callback in SUBSCRIBE %.*s", h->req_CallbackLen, h->req_buf + h->req_CallbackOff); BuildResp2_upnphttp(h, 412, "Precondition Failed", 0, 0); } } else { /* subscription renew */ /* Invalid SID 412 Precondition Failed. If a SID does not correspond to a known, un-expired subscription, the publisher must respond with HTTP error 412 Precondition Failed. */ #ifdef UPNP_STRICT /* SID: and NT: headers are incompatibles */ if(h->req_NTOff > 0) { syslog(LOG_WARNING, "Both NT: and SID: in SUBSCRIBE"); BuildResp2_upnphttp(h, 400, "Incompatible header fields", 0, 0); } else { #endif /* UPNP_STRICT */ sid = upnpevents_renewSubscription(h->req_buf + h->req_SIDOff, h->req_SIDLen, h->req_Timeout); if(!sid) { BuildResp2_upnphttp(h, 412, "Precondition Failed", 0, 0); } else { h->respflags = FLAG_TIMEOUT | FLAG_SID; h->res_SID = sid; BuildResp_upnphttp(h, 0, 0); } #ifdef UPNP_STRICT } #endif /* UPNP_STRICT */ } SendRespAndClose_upnphttp(h); } }