Commit message: GetOutboundPinholeTimeout: check args
CVE: CVE-2019-12109
CWE: CWE-476
Vulnerability description: A Denial Of Service vulnerability in MiniUPnP MiniUPnPd through 2.1 exists due to a NULL pointer dereference in GetOutboundPinholeTimeout in upnpsoap.c for rem_port.

Project: miniupnp
File: upnpsoap.c

BuildSendAndCloseSoapResp(struct upnphttp * h,
                          const char * body, int bodylen)
{
	static const char beforebody[] =
		"<?xml version=\"1.0\"?>\r\n"
		"<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" "
		"s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">"
		"<s:Body>";

	static const char afterbody[] =
		"</s:Body>"
		"</s:Envelope>\r\n";

	int r = BuildHeader_upnphttp(h, 200, "OK",  sizeof(beforebody) - 1
	                             + sizeof(afterbody) - 1 + bodylen );

	if(r >= 0) {
		memcpy(h->res_buf + h->res_buflen, beforebody, sizeof(beforebody) - 1);
		h->res_buflen += sizeof(beforebody) - 1;

		memcpy(h->res_buf + h->res_buflen, body, bodylen);
		h->res_buflen += bodylen;

		memcpy(h->res_buf + h->res_buflen, afterbody, sizeof(afterbody) - 1);
		h->res_buflen += sizeof(afterbody) - 1;
	} else {
		BuildResp2_upnphttp(h, 500, "Internal Server Error", NULL, 0);
	}

	SendRespAndClose_upnphttp(h);
}

Project: miniupnp
File: upnpsoap.c

ExecuteSoapAction(struct upnphttp * h, const char * action, int n)
{
	char * p;
	char * p2;
	int i, len, methodlen;
	char namespace[256];

	/* SoapAction example :
	 * urn:schemas-upnp-org:service:WANIPConnection:1#GetStatusInfo */
	p = strchr(action, '#');
	if(p && (p - action) < n) {
		for(i = 0; i < ((int)sizeof(namespace) - 1) && (action + i) < p; i++)
			namespace[i] = action[i];
		namespace[i] = '\0';
		p++;
		p2 = strchr(p, '"');
		if(p2 && (p2 - action) <= n)
			methodlen = p2 - p;
		else
			methodlen = n - (p - action);
		/*syslog(LOG_DEBUG, "SoapMethod: %.*s %d %d %p %p %d",
		       methodlen, p, methodlen, n, action, p, (int)(p - action));*/
		for(i = 0; soapMethods[i].methodName; i++) {
			len = strlen(soapMethods[i].methodName);
			if((len == methodlen) && memcmp(p, soapMethods[i].methodName, len) == 0) {
#ifdef DEBUG
				syslog(LOG_DEBUG, "Remote Call of SoapMethod '%s' %s",
				       soapMethods[i].methodName, namespace);
#endif /* DEBUG */
				soapMethods[i].methodImpl(h, soapMethods[i].methodName, namespace);
				return;
			}
		}
		syslog(LOG_NOTICE, "SoapMethod: Unknown: %.*s %s", methodlen, p, namespace);
	} else {
		syslog(LOG_NOTICE, "cannot parse SoapAction");
	}

	SoapError(h, 401, "Invalid Action");
}

Project: miniupnp
File: upnpsoap.c

GetFirewallStatus(struct upnphttp * h, const char * action, const char * ns)
{
	static const char resp[] =
		"<u:%sResponse "
		"xmlns:u=\"%s\">"
		"<FirewallEnabled>%d</FirewallEnabled>"
		"<InboundPinholeAllowed>%d</InboundPinholeAllowed>"
		"</u:%sResponse>";

	char body[512];
	int bodylen;

	bodylen = snprintf(body, sizeof(body), resp,
		action, ns, /*"urn:schemas-upnp-org:service:WANIPv6FirewallControl:1",*/
	    GETFLAG(IPV6FCFWDISABLEDMASK) ? 0 : 1,
	    GETFLAG(IPV6FCINBOUNDDISALLOWEDMASK) ? 0 : 1,
	    action);
	BuildSendAndCloseSoapResp(h, body, bodylen);
}

Project: miniupnp
File: upnpsoap.c

GetStatusInfo(struct upnphttp * h, const char * action, const char * ns)
{
	static const char resp[] =
		"<u:%sResponse "
		"xmlns:u=\"%s\">"
		"<NewConnectionStatus>%s</NewConnectionStatus>"
		"<NewLastConnectionError>ERROR_NONE</NewLastConnectionError>"
		"<NewUptime>%ld</NewUptime>"
		"</u:%sResponse>";

	char body[512];
	int bodylen;
	time_t uptime;
	const char * status;
	/* ConnectionStatus possible values :
	 * Unconfigured, Connecting, Connected, PendingDisconnect,
	 * Disconnecting, Disconnected */

	status = get_wan_connection_status_str(ext_if_name);
	uptime = upnp_get_uptime();
	bodylen = snprintf(body, sizeof(body), resp,
		action, ns, /*SERVICE_TYPE_WANIPC,*/
		status, (long)uptime, action);
	BuildSendAndCloseSoapResp(h, body, bodylen);
}

Project: miniupnp
File: upnpsoap.c

GetTotalBytesSent(struct upnphttp * h, const char * action, const char * ns)
{
	int r;

	static const char resp[] =
		"<u:%sResponse "
		"xmlns:u=\"%s\">"
		"<NewTotalBytesSent>%lu</NewTotalBytesSent>"
		"</u:%sResponse>";

	char body[512];
	int bodylen;
	struct ifdata data;

	r = getifstats(ext_if_name, &data);
	bodylen = snprintf(body, sizeof(body), resp,
	         action, ns, /* was "urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1" */
#ifdef UPNP_STRICT
             r<0?0:(data.obytes & UPNP_UI4_MAX), action);
#else /* UPNP_STRICT */
             r<0?0:data.obytes, action);
#endif /* UPNP_STRICT */
	BuildSendAndCloseSoapResp(h, body, bodylen);
}