예제 #1
0
파일: upnphttp.c 프로젝트: yeonsh/miniupnp
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);
	}
}
예제 #2
0
/* ProcessHTTPPOST_upnphttp()
 * executes the SOAP query if it is possible */
static void
ProcessHTTPPOST_upnphttp(struct upnphttp * h)
{
	if((h->req_buflen - h->req_contentoff) >= h->req_contentlen)
	{
		if(h->req_soapAction)
		{
			/* we can process the request */
			syslog(LOG_INFO, "SOAPAction: %.*s",
		    	   h->req_soapActionLen, h->req_soapAction);
			ExecuteSoapAction(h, 
				h->req_soapAction,
				h->req_soapActionLen);
		}
		else
		{
			static const char err400str[] =
				"<html><body>Bad request</body></html>";
			syslog(LOG_INFO, "No SOAPAction in HTTP headers");
			h->respflags = FLAG_HTML;
			BuildResp2_upnphttp(h, 400, "Bad Request",
			                    err400str, sizeof(err400str) - 1);
			SendResp_upnphttp(h);
			CloseSocket_upnphttp(h);
		}
	}
	else
	{
		/* waiting for remaining data */
		h->state = 1;
	}
}
예제 #3
0
/* very minimalistic 501 error message */
static void
Send501(struct upnphttp * h)
{
/*
	static const char error501[] = "HTTP/1.1 501 Not Implemented\r\n"
		"Connection: close\r\n"
		"Content-type: text/html\r\n"
		"\r\n"
		"<HTML><HEAD><TITLE>501 Not Implemented</TITLE></HEAD>"
		"<BODY><H1>Not Implemented</H1>The HTTP Method "
		"is not implemented by this server.</BODY></HTML>\r\n";
	int n;
	n = send(h->socket, error501, sizeof(error501) - 1, 0);
	if(n < 0)
	{
		syslog(LOG_ERR, "Send501: send(http): %m");
	}
*/
	static const char body501[] = 
		"<HTML><HEAD><TITLE>501 Not Implemented</TITLE></HEAD>"
		"<BODY><H1>Not Implemented</H1>The HTTP Method "
		"is not implemented by this server.</BODY></HTML>\r\n";
	h->respflags = FLAG_HTML;
	BuildResp2_upnphttp(h, 501, "Not Implemented",
	                    body501, sizeof(body501) - 1);
	SendResp_upnphttp(h);
	CloseSocket_upnphttp(h);
}
예제 #4
0
/* very minimalistic 404 error message */
static void
Send404(struct upnphttp * h)
{
/*
	static const char error404[] = "HTTP/1.1 404 Not found\r\n"
		"Connection: close\r\n"
		"Content-type: text/html\r\n"
		"\r\n"
		"<HTML><HEAD><TITLE>404 Not Found</TITLE></HEAD>"
		"<BODY><H1>Not Found</H1>The requested URL was not found"
		" on this server.</BODY></HTML>\r\n";
	int n;
	n = send(h->socket, error404, sizeof(error404) - 1, 0);
	if(n < 0)
	{
		syslog(LOG_ERR, "Send404: send(http): %m");
	}*/
	static const char body404[] =
		"<HTML><HEAD><TITLE>404 Not Found</TITLE></HEAD>"
		"<BODY><H1>Not Found</H1>The requested URL was not found"
		" on this server.</BODY></HTML>\r\n";
	h->respflags = FLAG_HTML;
	BuildResp2_upnphttp(h, 404, "Not Found",
	                    body404, sizeof(body404) - 1);
	SendResp_upnphttp(h);
	CloseSocket_upnphttp(h);
}
예제 #5
0
static void
ProcessHTTPUnSubscribe_upnphttp(struct upnphttp * h, const char * path)
{
	syslog(LOG_DEBUG, "ProcessHTTPUnSubscribe %s", path);
	syslog(LOG_DEBUG, "SID '%.*s'", h->req_SIDLen, h->req_buf + h->req_SIDOff);
	/* Remove from the list */
#ifdef UPNP_STRICT
	if(h->req_SIDOff <= 0 || h->req_SIDLen == 0) {
		/* SID: header missing or empty */
		BuildResp2_upnphttp(h, 412, "Precondition Failed", 0, 0);
	} else if(h->req_CallbackOff > 0 || h->req_NTOff > 0) {
		/* no NT: or Callback: header must be present */
		BuildResp2_upnphttp(h, 400, "Incompatible header fields", 0, 0);
	} else
#endif
	if(upnpevents_removeSubscriber(h->req_buf + h->req_SIDOff, h->req_SIDLen) < 0) {
		BuildResp2_upnphttp(h, 412, "Precondition Failed", 0, 0);
	} else {
		BuildResp_upnphttp(h, 0, 0);
	}
	SendRespAndClose_upnphttp(h);
}
예제 #6
0
/* very minimalistic 501 error message */
static void
Send501(struct upnphttp * h)
{
	static const char body501[] =
		"<HTML><HEAD><TITLE>501 Not Implemented</TITLE></HEAD>"
		"<BODY><H1>Not Implemented</H1>The HTTP Method "
		"is not implemented by this server.</BODY></HTML>\r\n";

	h->respflags = FLAG_HTML;
	BuildResp2_upnphttp(h, 501, "Not Implemented",
	                    body501, sizeof(body501) - 1);
	SendRespAndClose_upnphttp(h);
}
예제 #7
0
static void
Send405(struct upnphttp * h)
{
	static const char body405[] =
		"<HTML><HEAD><TITLE>405 Method Not Allowed</TITLE></HEAD>"
		"<BODY><H1>Method Not Allowed</H1>The HTTP Method "
		"is not allowed on this resource.</BODY></HTML>\r\n";

	h->respflags |= FLAG_HTML;
	BuildResp2_upnphttp(h, 405, "Method Not Allowed",
	                    body405, sizeof(body405) - 1);
	SendRespAndClose_upnphttp(h);
}
예제 #8
0
/* very minimalistic 404 error message */
static void
Send404(struct upnphttp * h)
{
	static const char body404[] =
		"<HTML><HEAD><TITLE>404 Not Found</TITLE></HEAD>"
		"<BODY><H1>Not Found</H1>The requested URL was not found"
		" on this server.</BODY></HTML>\r\n";

	h->respflags = FLAG_HTML;
	BuildResp2_upnphttp(h, 404, "Not Found",
	                    body404, sizeof(body404) - 1);
	SendRespAndClose_upnphttp(h);
}
예제 #9
0
파일: upnphttp.c 프로젝트: yeonsh/miniupnp
static void
ProcessHTTPUnSubscribe_upnphttp(struct upnphttp * h, const char * path)
{
	syslog(LOG_DEBUG, "ProcessHTTPUnSubscribe %s", path);
	syslog(LOG_DEBUG, "SID '%.*s'", h->req_SIDLen, h->req_SID);
	/* Remove from the list */
	if(upnpevents_removeSubscriber(h->req_SID, h->req_SIDLen) < 0) {
		BuildResp2_upnphttp(h, 412, "Precondition Failed", 0, 0);
	} else {
		BuildResp_upnphttp(h, 0, 0);
	}
	SendResp_upnphttp(h);
	CloseSocket_upnphttp(h);
}
예제 #10
0
/* ProcessHTTPPOST_upnphttp()
 * executes the SOAP query if it is possible */
static void
ProcessHTTPPOST_upnphttp(struct upnphttp * h)
{
	if((h->req_buflen - h->req_contentoff) >= h->req_contentlen)
	{
		/* the request body is received */
		if(h->req_soapActionOff > 0)
		{
			/* we can process the request */
			syslog(LOG_INFO, "SOAPAction: %.*s",
			       h->req_soapActionLen, h->req_buf + h->req_soapActionOff);
			ExecuteSoapAction(h,
				h->req_buf + h->req_soapActionOff,
				h->req_soapActionLen);
		}
		else
		{
			static const char err400str[] =
				"<html><body>Bad request</body></html>";
			syslog(LOG_INFO, "No SOAPAction in HTTP headers");
			h->respflags = FLAG_HTML;
			BuildResp2_upnphttp(h, 400, "Bad Request",
			                    err400str, sizeof(err400str) - 1);
			SendRespAndClose_upnphttp(h);
		}
	}
	else if(h->respflags & FLAG_CONTINUE)
	{
		/* Sending the 100 Continue response */
		if(!h->res_buf) {
			h->res_buf = malloc(256);
			h->res_buf_alloclen = 256;
		}
		h->res_buflen = snprintf(h->res_buf, h->res_buf_alloclen,
		                         "%s 100 Continue\r\n\r\n", h->HttpVer);
		h->res_sent = 0;
		h->state = ESendingContinue;
		if(SendResp_upnphttp(h))
			h->state = EWaitingForHttpContent;
	}
	else
	{
		/* waiting for remaining data */
		h->state = EWaitingForHttpContent;
	}
}
예제 #11
0
/* Sends the description generated by the parameter */
static void
sendXMLdesc(struct upnphttp * h, char * (f)(int *))
{
	char * desc;
	int len;
	desc = f(&len);
	if(!desc)
	{
		static const char error500[] = "<HTML><HEAD><TITLE>Error 500</TITLE>"
		   "</HEAD><BODY>Internal Server Error</BODY></HTML>\r\n";
		syslog(LOG_ERR, "Failed to generate XML description");
		h->respflags = FLAG_HTML;
		BuildResp2_upnphttp(h, 500, "Internal Server Error",
		                    error500, sizeof(error500)-1);
	}
	else
	{
		BuildResp_upnphttp(h, desc, len);
	}
	SendRespAndClose_upnphttp(h);
	free(desc);
}
예제 #12
0
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);
	}
}
예제 #13
0
/* responding 200 OK ! */
void
BuildResp_upnphttp(struct upnphttp * h,
                        const char * body, int bodylen)
{
	BuildResp2_upnphttp(h, 200, "OK", body, bodylen);
}
예제 #14
0
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);
    }
}