1
0
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:
Rolf Ahrenberg 2010-07-02 18:28:49 +03:00
parent 8a96e5b327
commit 3f88e7a911
6 changed files with 92 additions and 53 deletions

View File

@ -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.

View File

@ -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;

View File

@ -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);

View File

@ -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);

View File

@ -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;
} }

View File

@ -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