mirror of
https://github.com/rofafor/vdr-plugin-iptv.git
synced 2023-10-10 13:37:03 +02:00
Added validation for source addresses of socket data.
This commit is contained in:
parent
8a96e5b327
commit
3f88e7a911
1
HISTORY
1
HISTORY
@ -146,3 +146,4 @@ VDR Plugin 'iptv' Revision History
|
|||||||
|
|
||||||
- Renamed Sid scanner to section id scanner and added
|
- Renamed Sid scanner to section id scanner and added
|
||||||
experimental Tid/Nid support into it.
|
experimental Tid/Nid support into it.
|
||||||
|
- Added validation for source addresses of socket data.
|
||||||
|
@ -109,7 +109,7 @@ bool cIptvProtocolExt::Open(void)
|
|||||||
if (!strlen(*scriptFile))
|
if (!strlen(*scriptFile))
|
||||||
return false;
|
return false;
|
||||||
// Create the listening socket
|
// Create the listening socket
|
||||||
OpenSocket(socketPort);
|
OpenSocket(INADDR_LOOPBACK, socketPort);
|
||||||
// Execute the external script
|
// Execute the external script
|
||||||
ExecuteScript();
|
ExecuteScript();
|
||||||
isActive = true;
|
isActive = true;
|
||||||
|
@ -40,9 +40,6 @@ bool cIptvProtocolHttp::Connect(void)
|
|||||||
debug("cIptvProtocolHttp::Connect()\n");
|
debug("cIptvProtocolHttp::Connect()\n");
|
||||||
// Check that stream address is valid
|
// Check that stream address is valid
|
||||||
if (!isActive && !isempty(streamAddr) && !isempty(streamPath)) {
|
if (!isActive && !isempty(streamAddr) && !isempty(streamPath)) {
|
||||||
// Ensure that socket is valid
|
|
||||||
OpenSocket(socketPort);
|
|
||||||
|
|
||||||
// First try only the IP address
|
// First try only the IP address
|
||||||
sockAddr.sin_addr.s_addr = inet_addr(streamAddr);
|
sockAddr.sin_addr.s_addr = inet_addr(streamAddr);
|
||||||
|
|
||||||
@ -61,6 +58,9 @@ bool cIptvProtocolHttp::Connect(void)
|
|||||||
sockAddr.sin_addr.s_addr = inet_addr(*host->h_addr_list);
|
sockAddr.sin_addr.s_addr = inet_addr(*host->h_addr_list);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Ensure that socket is valid
|
||||||
|
OpenSocket(sockAddr.sin_addr.s_addr, socketPort);
|
||||||
|
|
||||||
int err = connect(socketDesc, (struct sockaddr *)&sockAddr, sizeof(sockAddr));
|
int err = connect(socketDesc, (struct sockaddr *)&sockAddr, sizeof(sockAddr));
|
||||||
// Non-blocking sockets always report in-progress error when connected
|
// Non-blocking sockets always report in-progress error when connected
|
||||||
ERROR_IF_FUNC(err < 0 && errno != EINPROGRESS, "connect()", CloseSocket(), return false);
|
ERROR_IF_FUNC(err < 0 && errno != EINPROGRESS, "connect()", CloseSocket(), return false);
|
||||||
|
@ -39,7 +39,7 @@ bool cIptvProtocolUdp::JoinMulticast(void)
|
|||||||
// Check that stream address is valid
|
// Check that stream address is valid
|
||||||
if (!isActive && !isempty(streamAddr)) {
|
if (!isActive && !isempty(streamAddr)) {
|
||||||
// Ensure that socket is valid
|
// Ensure that socket is valid
|
||||||
OpenSocket(socketPort);
|
OpenSocket(inet_addr(streamAddr), socketPort);
|
||||||
// Join a new multicast group
|
// Join a new multicast group
|
||||||
struct ip_mreq mreq;
|
struct ip_mreq mreq;
|
||||||
mreq.imr_multiaddr.s_addr = inet_addr(streamAddr);
|
mreq.imr_multiaddr.s_addr = inet_addr(streamAddr);
|
||||||
@ -59,7 +59,7 @@ bool cIptvProtocolUdp::DropMulticast(void)
|
|||||||
// Check that stream address is valid
|
// Check that stream address is valid
|
||||||
if (isActive && !isempty(streamAddr)) {
|
if (isActive && !isempty(streamAddr)) {
|
||||||
// Ensure that socket is valid
|
// Ensure that socket is valid
|
||||||
OpenSocket(socketPort);
|
OpenSocket(inet_addr(streamAddr), socketPort);
|
||||||
// Drop the multicast group
|
// Drop the multicast group
|
||||||
struct ip_mreq mreq;
|
struct ip_mreq mreq;
|
||||||
mreq.imr_multiaddr.s_addr = inet_addr(streamAddr);
|
mreq.imr_multiaddr.s_addr = inet_addr(streamAddr);
|
||||||
|
65
socket.c
65
socket.c
@ -18,11 +18,13 @@
|
|||||||
#include "socket.h"
|
#include "socket.h"
|
||||||
|
|
||||||
cIptvSocket::cIptvSocket()
|
cIptvSocket::cIptvSocket()
|
||||||
: socketPort(0),
|
: socketDesc(-1),
|
||||||
socketDesc(-1),
|
socketPort(0),
|
||||||
|
inetAddr(INADDR_NONE),
|
||||||
isActive(false)
|
isActive(false)
|
||||||
{
|
{
|
||||||
debug("cIptvSocket::cIptvSocket()\n");
|
debug("cIptvSocket::cIptvSocket()\n");
|
||||||
|
memset(&sockAddr, 0, sizeof(sockAddr));
|
||||||
}
|
}
|
||||||
|
|
||||||
cIptvSocket::~cIptvSocket()
|
cIptvSocket::~cIptvSocket()
|
||||||
@ -32,9 +34,11 @@ cIptvSocket::~cIptvSocket()
|
|||||||
CloseSocket();
|
CloseSocket();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool cIptvSocket::OpenSocket(const int Port, const bool isUdp)
|
bool cIptvSocket::OpenSocket(const in_addr_t InetAddr, const int Port, const bool isUdp)
|
||||||
{
|
{
|
||||||
debug("cIptvSocket::OpenSocket()\n");
|
debug("cIptvSocket::OpenSocket()\n");
|
||||||
|
if (inetAddr != InetAddr)
|
||||||
|
inetAddr = InetAddr;
|
||||||
// If socket is there already and it is bound to a different port, it must
|
// If socket is there already and it is bound to a different port, it must
|
||||||
// be closed first
|
// be closed first
|
||||||
if (Port != socketPort) {
|
if (Port != socketPort) {
|
||||||
@ -57,7 +61,7 @@ bool cIptvSocket::OpenSocket(const int Port, const bool isUdp)
|
|||||||
ERROR_IF_FUNC(setsockopt(socketDesc, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) < 0, "setsockopt()",
|
ERROR_IF_FUNC(setsockopt(socketDesc, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) < 0, "setsockopt()",
|
||||||
CloseSocket(), return false);
|
CloseSocket(), return false);
|
||||||
// Bind socket
|
// Bind socket
|
||||||
memset(&sockAddr, '\0', sizeof(sockAddr));
|
memset(&sockAddr, 0, sizeof(sockAddr));
|
||||||
sockAddr.sin_family = AF_INET;
|
sockAddr.sin_family = AF_INET;
|
||||||
sockAddr.sin_port = htons((uint16_t)(Port & 0xFFFF));
|
sockAddr.sin_port = htons((uint16_t)(Port & 0xFFFF));
|
||||||
sockAddr.sin_addr.s_addr = htonl(INADDR_ANY);
|
sockAddr.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||||
@ -78,6 +82,9 @@ void cIptvSocket::CloseSocket(void)
|
|||||||
if (socketDesc >= 0) {
|
if (socketDesc >= 0) {
|
||||||
close(socketDesc);
|
close(socketDesc);
|
||||||
socketDesc = -1;
|
socketDesc = -1;
|
||||||
|
socketPort = 0;
|
||||||
|
inetAddr = INADDR_NONE;
|
||||||
|
memset(&sockAddr, 0, sizeof(sockAddr));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -92,10 +99,10 @@ cIptvUdpSocket::~cIptvUdpSocket()
|
|||||||
debug("cIptvUdpSocket::~cIptvUdpSocket()\n");
|
debug("cIptvUdpSocket::~cIptvUdpSocket()\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
bool cIptvUdpSocket::OpenSocket(const int Port)
|
bool cIptvUdpSocket::OpenSocket(const in_addr_t InetAddr, const int Port)
|
||||||
{
|
{
|
||||||
debug("cIptvUdpSocket::OpenSocket()\n");
|
debug("cIptvUdpSocket::OpenSocket()\n");
|
||||||
return cIptvSocket::OpenSocket(Port, true);
|
return cIptvSocket::OpenSocket(InetAddr, Port, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
int cIptvUdpSocket::Read(unsigned char* BufferAddr, unsigned int BufferLen)
|
int cIptvUdpSocket::Read(unsigned char* BufferAddr, unsigned int BufferLen)
|
||||||
@ -108,13 +115,35 @@ int cIptvUdpSocket::Read(unsigned char* BufferAddr, unsigned int BufferLen)
|
|||||||
}
|
}
|
||||||
socklen_t addrlen = sizeof(sockAddr);
|
socklen_t addrlen = sizeof(sockAddr);
|
||||||
int len = 0;
|
int len = 0;
|
||||||
|
struct msghdr msgh;
|
||||||
|
struct cmsghdr *cmsg;
|
||||||
|
struct iovec iov;
|
||||||
|
char cbuf[256];
|
||||||
|
// Initialize iov and msgh structures
|
||||||
|
memset(&msgh, 0, sizeof(struct msghdr));
|
||||||
|
iov.iov_base = BufferAddr;
|
||||||
|
iov.iov_len = BufferLen;
|
||||||
|
msgh.msg_control = cbuf;
|
||||||
|
msgh.msg_controllen = sizeof(cbuf);
|
||||||
|
msgh.msg_name = &sockAddr;
|
||||||
|
msgh.msg_namelen = addrlen;
|
||||||
|
msgh.msg_iov = &iov;
|
||||||
|
msgh.msg_iovlen = 1;
|
||||||
|
msgh.msg_flags = 0;
|
||||||
// Read data from socket
|
// Read data from socket
|
||||||
if (isActive && socketDesc && BufferAddr && (BufferLen > 0))
|
if (isActive && socketDesc && BufferAddr && (BufferLen > 0))
|
||||||
len = (int)recvfrom(socketDesc, BufferAddr, BufferLen, MSG_DONTWAIT,
|
len = (int)recvmsg(socketDesc, &msgh, MSG_DONTWAIT);
|
||||||
(struct sockaddr *)&sockAddr, &addrlen);
|
if (len < 0)
|
||||||
if ((len > 0) && (BufferAddr[0] == TS_SYNC_BYTE)) {
|
return -1;
|
||||||
|
else if (len > 0) {
|
||||||
|
// Process auxiliary received data
|
||||||
|
for (cmsg = CMSG_FIRSTHDR(&msgh); cmsg != NULL; cmsg = CMSG_NXTHDR(&msgh, cmsg)) {
|
||||||
|
if ((cmsg->cmsg_level == SOL_IP) && (cmsg->cmsg_type == IP_PKTINFO)) {
|
||||||
|
struct in_pktinfo *i = (struct in_pktinfo *)CMSG_DATA(cmsg);
|
||||||
|
// Validate source address
|
||||||
|
if (i->ipi_addr.s_addr == inetAddr) {
|
||||||
|
if (BufferAddr[0] == TS_SYNC_BYTE)
|
||||||
return len;
|
return len;
|
||||||
}
|
|
||||||
else if (len > 3) {
|
else if (len > 3) {
|
||||||
// http://www.networksorcery.com/enp/rfc/rfc2250.txt
|
// http://www.networksorcery.com/enp/rfc/rfc2250.txt
|
||||||
// version
|
// version
|
||||||
@ -144,6 +173,11 @@ int cIptvUdpSocket::Read(unsigned char* BufferAddr, unsigned int BufferLen)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TCP socket class
|
// TCP socket class
|
||||||
@ -157,10 +191,10 @@ cIptvTcpSocket::~cIptvTcpSocket()
|
|||||||
debug("cIptvTcpSocket::~cIptvTcpSocket()\n");
|
debug("cIptvTcpSocket::~cIptvTcpSocket()\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
bool cIptvTcpSocket::OpenSocket(const int Port)
|
bool cIptvTcpSocket::OpenSocket(const in_addr_t InetAddr, const int Port)
|
||||||
{
|
{
|
||||||
debug("cIptvTcpSocket::OpenSocket()\n");
|
debug("cIptvTcpSocket::OpenSocket()\n");
|
||||||
return cIptvSocket::OpenSocket(Port, false);
|
return cIptvSocket::OpenSocket(InetAddr, Port, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
int cIptvTcpSocket::Read(unsigned char* BufferAddr, unsigned int BufferLen)
|
int cIptvTcpSocket::Read(unsigned char* BufferAddr, unsigned int BufferLen)
|
||||||
@ -171,10 +205,13 @@ int cIptvTcpSocket::Read(unsigned char* BufferAddr, unsigned int BufferLen)
|
|||||||
error("Invalid socket in %s\n", __FUNCTION__);
|
error("Invalid socket in %s\n", __FUNCTION__);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
int len = 0;
|
||||||
socklen_t addrlen = sizeof(sockAddr);
|
socklen_t addrlen = sizeof(sockAddr);
|
||||||
// Read data from socket
|
// Read data from socket
|
||||||
if (isActive && socketDesc && BufferAddr && (BufferLen > 0))
|
if (isActive && socketDesc && BufferAddr && (BufferLen > 0))
|
||||||
return (int)recvfrom(socketDesc, BufferAddr, BufferLen, MSG_DONTWAIT,
|
len = recvfrom(socketDesc, BufferAddr, BufferLen, MSG_DONTWAIT,
|
||||||
(struct sockaddr *)&sockAddr, &addrlen);
|
(struct sockaddr *)&sockAddr, &addrlen);
|
||||||
return 0;
|
//if (inetAddr != sockAddr.sin_addr.s_addr)
|
||||||
|
// return -1;
|
||||||
|
return len;
|
||||||
}
|
}
|
||||||
|
9
socket.h
9
socket.h
@ -12,13 +12,14 @@
|
|||||||
|
|
||||||
class cIptvSocket {
|
class cIptvSocket {
|
||||||
protected:
|
protected:
|
||||||
int socketPort;
|
|
||||||
int socketDesc;
|
int socketDesc;
|
||||||
|
int socketPort;
|
||||||
|
in_addr_t inetAddr;
|
||||||
struct sockaddr_in sockAddr;
|
struct sockaddr_in sockAddr;
|
||||||
bool isActive;
|
bool isActive;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool OpenSocket(const int Port, const bool isUdp);
|
bool OpenSocket(const in_addr_t InetAddr, const int Port, const bool isUdp);
|
||||||
void CloseSocket(void);
|
void CloseSocket(void);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -31,7 +32,7 @@ public:
|
|||||||
cIptvUdpSocket();
|
cIptvUdpSocket();
|
||||||
virtual ~cIptvUdpSocket();
|
virtual ~cIptvUdpSocket();
|
||||||
virtual int Read(unsigned char* BufferAddr, unsigned int BufferLen);
|
virtual int Read(unsigned char* BufferAddr, unsigned int BufferLen);
|
||||||
bool OpenSocket(const int Port);
|
bool OpenSocket(const in_addr_t InetAddr, const int Port);
|
||||||
};
|
};
|
||||||
|
|
||||||
class cIptvTcpSocket : public cIptvSocket {
|
class cIptvTcpSocket : public cIptvSocket {
|
||||||
@ -39,7 +40,7 @@ public:
|
|||||||
cIptvTcpSocket();
|
cIptvTcpSocket();
|
||||||
virtual ~cIptvTcpSocket();
|
virtual ~cIptvTcpSocket();
|
||||||
virtual int Read(unsigned char* BufferAddr, unsigned int BufferLen);
|
virtual int Read(unsigned char* BufferAddr, unsigned int BufferLen);
|
||||||
bool OpenSocket(const int Port);
|
bool OpenSocket(const in_addr_t InetAddr, const int Port);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // __IPTV_SOCKET_H
|
#endif // __IPTV_SOCKET_H
|
||||||
|
Loading…
Reference in New Issue
Block a user