summaryrefslogtreecommitdiff
path: root/vdr-vdrmanager
diff options
context:
space:
mode:
authorbju <bju@maxi.fritz.box>2014-01-22 02:28:34 +0100
committerbju <bju@maxi.fritz.box>2014-01-22 02:28:34 +0100
commit321bebe669a5aafc2c4ff0e9f59e60de2fa79bac (patch)
treef8b81b463027a60481f8f41939eaa5a18824ce19 /vdr-vdrmanager
parentbc2c9e64787d4682bd9f3a3340f8b46497f63bb3 (diff)
downloadvdr-manager-321bebe669a5aafc2c4ff0e9f59e60de2fa79bac.tar.gz
vdr-manager-321bebe669a5aafc2c4ff0e9f59e60de2fa79bac.tar.bz2
http://projects.vdr-developer.org/issues/1267:
- some fixes on client side certificate validation - added SSL server side support to the plugin
Diffstat (limited to 'vdr-vdrmanager')
-rw-r--r--vdr-vdrmanager/Makefile4
-rw-r--r--vdr-vdrmanager/clientsock.cpp2
-rw-r--r--vdr-vdrmanager/compressor.cpp8
-rw-r--r--vdr-vdrmanager/handler.cpp177
-rw-r--r--vdr-vdrmanager/select.cpp90
-rw-r--r--vdr-vdrmanager/select.h8
-rw-r--r--vdr-vdrmanager/sock.cpp302
-rw-r--r--vdr-vdrmanager/sock.h48
-rw-r--r--vdr-vdrmanager/vdrmanager.cpp47
-rw-r--r--vdr-vdrmanager/vdrmanagerthread.cpp42
-rw-r--r--vdr-vdrmanager/vdrmanagerthread.h6
11 files changed, 250 insertions, 484 deletions
diff --git a/vdr-vdrmanager/Makefile b/vdr-vdrmanager/Makefile
index e63dc13..a5119ce 100644
--- a/vdr-vdrmanager/Makefile
+++ b/vdr-vdrmanager/Makefile
@@ -47,7 +47,7 @@ SOFILE = libvdr-$(PLUGIN).so
### The object files (add further files here):
-OBJS = $(PLUGIN).o sock.o vdrmanagerthread.o select.o handler.o helpers.o compressor.o
+OBJS = $(PLUGIN).o sock.o serversock.o clientsock.o vdrmanagerthread.o select.o handler.o helpers.o compressor.o
### The main target:
@@ -96,7 +96,7 @@ install-i18n: $(I18Nmsgs)
### Targets:
$(SOFILE): $(OBJS)
- $(CXX) $(CXXFLAGS) $(LDFLAGS) -shared $(OBJS) -o $@ -lz
+ $(CXX) $(CXXFLAGS) $(LDFLAGS) -shared $(OBJS) -o $@ -lz -lssl
install-lib: $(SOFILE)
install -D $^ $(LIBDIR)/$^.$(APIVERSION)
diff --git a/vdr-vdrmanager/clientsock.cpp b/vdr-vdrmanager/clientsock.cpp
index 82b12f4..91e6704 100644
--- a/vdr-vdrmanager/clientsock.cpp
+++ b/vdr-vdrmanager/clientsock.cpp
@@ -376,7 +376,7 @@ void cVdrmanagerClientSocket::Compress() {
sendsize = compressor.getDataSize();
double ratio = 1.0 * writebuf.length() / sendsize;
- isyslog("Compression stats: raw %ld, compressed %ld, ratio %f:1", writebuf.length(), sendsize, ratio);
+ dsyslog("[vdrmanager] Compression stats: raw %ld, compressed %ld, ratio %f:1", writebuf.length(), sendsize, ratio);
}
int cVdrmanagerClientSocket::GetSslReadWrite() {
diff --git a/vdr-vdrmanager/compressor.cpp b/vdr-vdrmanager/compressor.cpp
index 6a479f3..c8322b8 100644
--- a/vdr-vdrmanager/compressor.cpp
+++ b/vdr-vdrmanager/compressor.cpp
@@ -56,7 +56,13 @@ bool cCompressor::CompressGzip(string text) {
close(in_fd[0]);
close(out_fd[1]);
- write(in_fd[1], text.c_str(), text.length());
+ if (write(in_fd[1], text.c_str(), text.length()) != text.length())
+ {
+ close(in_fd[1]);
+ close(out_fd[0]);
+ return false;
+ }
+
close(in_fd[1]);
char buf[32*1024];
diff --git a/vdr-vdrmanager/handler.cpp b/vdr-vdrmanager/handler.cpp
index ea15296..4a787c7 100644
--- a/vdr-vdrmanager/handler.cpp
+++ b/vdr-vdrmanager/handler.cpp
@@ -17,104 +17,97 @@ bool cHandler::HandleNewClient(cVdrmanagerClientSocket * sock)
bool cHandler::HandleClientRequest(cVdrmanagerClientSocket * sock)
{
- bool closeSocket = true;
+ while (!sock->IsLineComplete() && sock->Read())
+ ;
- while(sock->Read())
- {
- // get lines
- while (sock->IsLineComplete())
- {
- string line;
- sock->GetLine(line);
+ if (sock->IsLineComplete()) {
- // parse request
- size_t space = line.find(' ');
- string cmd;
- string args;
- if (space != string::npos) {
- cmd = cHelpers::ToUpper(line.substr(0, space));
- args = cHelpers::Trim(line.substr(space+1));
- } else {
- cmd = cHelpers::ToUpper(line);
- args = "";
- }
+ string line;
+ sock->GetLine(line);
- if (!sock->IsLoggedIn() && cmd != "PASSWD") {
- sock->PutLine("!ERROR\r\n");
- }
- else if (cmd == "PASSWD")
- {
- if (args != sock->GetPassword()) {
- sock->PutLine("!ERROR\r\n");
- } else {
- sock->SetLoggedIn();
- sock->PutLine("!OK\r\n");
- }
- closeSocket = false;
- }
- else if (cmd == "COMPRESS")
- {
- sock->ActivateCompression();
- closeSocket = false;
- }
- else if (cmd == "TIMERS")
- {
- string text = cHelpers::GetTimers(args);
- sock->PutLine(text);
- }
- else if (cmd == "CHANNELS")
- {
- string text = cHelpers::GetChannels(args);
- sock->PutLine(text);
- }
- else if (cmd == "TEVENTS")
- {
- string text = cHelpers::GetTimeEvents(args);
- sock->PutLine(text);
- }
- else if (cmd == "CEVENTS")
- {
- string text = cHelpers::GetChannelEvents(args);
- sock->PutLine(text);
- }
- else if (cmd == "TIMER")
- {
- string text = cHelpers::SetTimer(args);
- sock->PutLine(text);
- }
- else if (cmd == "SEARCH")
- {
- string text = cHelpers::SearchEvents(args);
- sock->PutLine(text);
- }
- else if(cmd == "RECORDINGS")
- {
- string text = cHelpers::GetRecordings(args);
- sock->PutLine(text);
- }
- else if(cmd == "DRECORDING")
- {
- string text = cHelpers::DelRecording(args);
- sock->PutLine(text);
- }
- else if (cmd == "SETCHANNEL")
- {
- string text = cHelpers::SetChannel(args);
- sock->PutLine(text);
- }
- else if (cmd == "QUIT")
- {
- // close socket
- sock->PutLine(string("Good bye! :-)\r\n"));
- sock->Disconnect();
- }
+ isyslog("[vdrmanager] got %s", line.c_str());
- if (closeSocket) {
- sock->Disconnect();
- }
+ // parse request
+ size_t space = line.find(' ');
+ string cmd;
+ string args;
+ if (space != string::npos) {
+ cmd = cHelpers::ToUpper(line.substr(0, space));
+ args = cHelpers::Trim(line.substr(space+1));
+ } else {
+ cmd = cHelpers::ToUpper(line);
+ args = "";
+ }
- sock->Flush();
+ if (!sock->IsLoggedIn() && cmd != "PASSWD") {
+ sock->Write("!ERROR\r\n");
}
+ else if (cmd == "PASSWD")
+ {
+ if (args != sock->GetPassword()) {
+ sock->Write("!ERROR\r\n");
+ } else {
+ sock->SetLoggedIn();
+ sock->Write("!OK\r\n");
+ }
+ }
+ else if (cmd == "COMPRESS")
+ {
+ sock->ActivateCompression();
+ }
+ else if (cmd == "TIMERS")
+ {
+ string text = cHelpers::GetTimers(args);
+ sock->Write(text);
+ }
+ else if (cmd == "CHANNELS")
+ {
+ string text = cHelpers::GetChannels(args);
+ sock->Write(text);
+ }
+ else if (cmd == "TEVENTS")
+ {
+ string text = cHelpers::GetTimeEvents(args);
+ sock->Write(text);
+ }
+ else if (cmd == "CEVENTS")
+ {
+ string text = cHelpers::GetChannelEvents(args);
+ sock->Write(text);
+ }
+ else if (cmd == "TIMER")
+ {
+ string text = cHelpers::SetTimer(args);
+ sock->Write(text);
+ }
+ else if (cmd == "SEARCH")
+ {
+ string text = cHelpers::SearchEvents(args);
+ sock->Write(text);
+ }
+ else if(cmd == "RECORDINGS")
+ {
+ string text = cHelpers::GetRecordings(args);
+ sock->Write(text);
+ }
+ else if(cmd == "DRECORDING")
+ {
+ string text = cHelpers::DelRecording(args);
+ sock->Write(text);
+ }
+ else if (cmd == "SETCHANNEL")
+ {
+ string text = cHelpers::SetChannel(args);
+ sock->Write(text);
+ }
+ else if (cmd == "QUIT")
+ {
+ // close socket
+ sock->Write(string("Good bye! :-)\r\n"));
+ sock->Disconnect();
+ }
+
+ sock->Flush();
}
return true;
diff --git a/vdr-vdrmanager/select.cpp b/vdr-vdrmanager/select.cpp
index c569f42..2080ad0 100644
--- a/vdr-vdrmanager/select.cpp
+++ b/vdr-vdrmanager/select.cpp
@@ -17,6 +17,7 @@ struct node {
cSelect::cSelect() {
serversocket = NULL;
+ sslServersocket = NULL;
clientsockets = NULL;
clientsocketcount = 0;
handler = new cHandler;
@@ -29,6 +30,8 @@ cSelect::cSelect() {
cSelect::~cSelect() {
if (serversocket)
delete serversocket;
+ if (sslServersocket)
+ delete sslServersocket;
while (clientsockets) {
node * next = clientsockets->next;
@@ -44,8 +47,9 @@ cSelect::~cSelect() {
delete pollfds;
}
-void cSelect::SetServerSocket(cVdrmanagerServerSocket * sock) {
+void cSelect::SetServerSockets(cVdrmanagerServerSocket * sock, cVdrmanagerServerSocket * sslSock) {
serversocket = sock;
+ sslServersocket = sslSock;
}
void cSelect::AddClientSocket(cVdrmanagerClientSocket * sock) {
@@ -107,31 +111,58 @@ bool cSelect::Action() {
return true;
}
-void cSelect::CreatePollfds() {
+int cSelect::CreatePollfds() {
+
+ int i = 0;
+
+ int count = clientsocketcount + (sslServersocket ? 2 : 1);
// we poll for the server socket and for each client socket
- pollfds = new struct pollfd[clientsocketcount + 1];
- pollfds[0].fd = serversocket->GetSocket();
- pollfds[0].events = POLLIN;
+ pollfds = new struct pollfd[count];
+
+ pollfds[i].fd = serversocket->GetSocket();
+ pollfds[i].revents = 0;
+ pollfds[i++].events = POLLIN;
+
+ if (sslServersocket) {
+ pollfds[i].fd = sslServersocket->GetSocket();
+ pollfds[i].revents = 0;
+ pollfds[i++].events = POLLIN;
+ }
node * curnode = clientsockets;
- int i = 1;
while (curnode) {
- pollfds[i].fd = curnode->socket->GetSocket();
- pollfds[i].events = POLLIN | POLLHUP;
- if (curnode->socket->WritePending()) {
- pollfds[i].events |= POLLOUT;
+ cVdrmanagerClientSocket * sock = curnode->socket;
+ pollfds[i].fd = sock->GetSocket();
+ if (sock->IsSSL()) {
+ if (sock->GetSslWantsSelect() == SSL_ERROR_WANT_READ) {
+ pollfds[i].events = POLLIN | POLLHUP;
+ } else if (sock->GetSslWantsSelect() == SSL_ERROR_WANT_WRITE) {
+ pollfds[i].events = POLLOUT;
+ } else {
+ pollfds[i].events = POLLIN | POLLHUP;
+ if (sock->WritePending())
+ pollfds[i].events |= POLLOUT;
+ }
+ } else {
+ pollfds[i].events = POLLIN | POLLHUP;
+ if (curnode->socket->WritePending())
+ pollfds[i].events |= POLLOUT;
}
pollfds[i++].revents = 0;
curnode = curnode->next;
}
+
+ return count;
}
bool cSelect::Poll() {
+
// poll for events
- CreatePollfds();
+ int count = CreatePollfds();
+
int rc = 0;
- while ((rc = poll(pollfds, clientsocketcount + 1, -1)) < 0) {
+ while ((rc = poll(pollfds, count, -1)) < 0) {
if (errno != EINTR)
break;
}
@@ -146,10 +177,16 @@ bool cSelect::Poll() {
return true;
// client requests or outstanding writes
- for (int i = 1; i < clientsocketcount + 1; i++) {
+ for (int i = (sslServersocket ? 2 : 1); i < count; i++) {
cVdrmanagerClientSocket * sock = GetClientSocket(pollfds[i].fd);
if (sock) {
- if (pollfds[i].revents & POLLOUT) {
+ if ((pollfds[i].revents & (POLLIN|POLLOUT)) && sock->GetSslReadWrite() != SSL_NO_RETRY) {
+ if (sock->GetSslReadWrite() == SSL_RETRY_READ) {
+ handler->HandleClientRequest(sock);
+ } else {
+ sock->Flush();
+ }
+ } else if (pollfds[i].revents & POLLOUT) {
// possibly outstanding writes
sock->Flush();
} else if (pollfds[i].revents & (POLLIN | POLLHUP)) {
@@ -165,15 +202,22 @@ bool cSelect::Poll() {
}
// new client?
- if (pollfds[0].revents & POLLIN) {
- // get client socket
- cVdrmanagerClientSocket * sock = serversocket->Accept();
- if (sock) {
- // Add client socket
- AddClientSocket(sock);
- // Send current data
- handler->HandleNewClient(sock);
- }
+ for(int i = 0; i < (sslServersocket ? 2 : 1); i++) {
+ if (pollfds[i].revents & POLLIN) {
+ // get client socket
+ cVdrmanagerClientSocket * sock;
+ if (i == 0)
+ sock = serversocket->Accept();
+ else
+ sock = sslServersocket->Accept();
+
+ if (sock) {
+ // Add client socket
+ AddClientSocket(sock);
+ // Send current data
+ handler->HandleNewClient(sock);
+ }
+ }
}
delete pollfds;
diff --git a/vdr-vdrmanager/select.h b/vdr-vdrmanager/select.h
index fbdeb02..2a7f5ba 100644
--- a/vdr-vdrmanager/select.h
+++ b/vdr-vdrmanager/select.h
@@ -7,7 +7,8 @@
#include <string>
#include <sys/select.h>
-#include "sock.h"
+#include "clientsock.h"
+#include "serversock.h"
#include "handler.h"
struct node;
@@ -17,6 +18,7 @@ private:
node * clientsockets;
int clientsocketcount;
cVdrmanagerServerSocket * serversocket;
+ cVdrmanagerServerSocket * sslServersocket;
cHandler * handler;
struct pollfd * pollfds;
bool stopped;
@@ -26,13 +28,13 @@ public:
cSelect();
virtual ~cSelect();
void DispatchVdrEvent(string event);
- void SetServerSocket(cVdrmanagerServerSocket * sock);
+ void SetServerSockets(cVdrmanagerServerSocket * sock, cVdrmanagerServerSocket * sslSock);
void AddClientSocket(cVdrmanagerClientSocket * sock);
void RemoveClientSocket(cVdrmanagerClientSocket * sock);
bool Action();
bool Stop();
private:
- void CreatePollfds();
+ int CreatePollfds();
cVdrmanagerClientSocket * GetClientSocket(int fd);
bool Poll();
void NotifyClients(string event);
diff --git a/vdr-vdrmanager/sock.cpp b/vdr-vdrmanager/sock.cpp
index 1d1d907..7e7da70 100644
--- a/vdr-vdrmanager/sock.cpp
+++ b/vdr-vdrmanager/sock.cpp
@@ -3,12 +3,11 @@
*/
#include <unistd.h>
#include <vdr/plugin.h>
+#include <openssl/err.h>
#include "sock.h"
#include "helpers.h"
#include "compressor.h"
-static int clientno = 0;
-
/*
* cVdrmonSocket
*/
@@ -51,304 +50,7 @@ const char * cVdrmanagerSocket::GetPassword() {
return password;
}
-/*
- * cVdrmonServerSocket
- */
-cVdrmanagerServerSocket::cVdrmanagerServerSocket() :
- cVdrmanagerSocket() {
-}
-
-cVdrmanagerServerSocket::~cVdrmanagerServerSocket() {
-}
-
-bool cVdrmanagerServerSocket::Create(int port, const char * password, bool forceCheckSvrp, int compressionMode) {
-
- this->password = password;
- this->forceCheckSvdrp = forceCheckSvrp;
- this->compressionMode = compressionMode;
-
- // create socket
- sock = socket(PF_INET, SOCK_STREAM, 0);
- if (sock < 0) {
- LOG_ERROR;
- return false;
- }
-
- // allow it to always reuse the same port:
- int ReUseAddr = 1;
- setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &ReUseAddr, sizeof(ReUseAddr));
-
- // bind to address
- struct sockaddr_in name;
- name.sin_family = AF_INET;
- name.sin_port = htons(port);
- name.sin_addr.s_addr = htonl(INADDR_ANY);
- if (bind(sock, (struct sockaddr *) &name, sizeof(name)) < 0) {
- LOG_ERROR;
- Close();
- return false;
- }
-
- // make it non-blocking:
- if (!MakeDontBlock()) {
- Close();
- return false;
- }
-
- // listen to the socket:
- if (listen(sock, 100) < 0) {
- LOG_ERROR;
- Close();
- return false;
- }
-
- return true;
-}
-
-cVdrmanagerClientSocket * cVdrmanagerServerSocket::Accept() {
- cVdrmanagerClientSocket * newsocket = NULL;
-
- // accept the connection
- struct sockaddr_in clientname;
- uint size = sizeof(clientname);
- int newsock = accept(sock, (struct sockaddr *) &clientname, &size);
- if (newsock > 0) {
- // create client socket
- newsocket = new cVdrmanagerClientSocket(password, compressionMode);
- if (!newsocket->Attach(newsock)) {
- delete newsocket;
- return NULL;
- }
-
- if (!IsPasswordSet() || forceCheckSvdrp == true) {
- bool accepted = SVDRPhosts.Acceptable(clientname.sin_addr.s_addr);
- if (!accepted) {
- newsocket->PutLine(string("NACC Access denied.\n"));
- newsocket->Flush();
- delete newsocket;
- newsocket = NULL;
- }
- dsyslog(
- "[vdrmanager] connect from %s, port %hd - %s", inet_ntoa(clientname.sin_addr), ntohs(clientname.sin_port), accepted ? "accepted" : "DENIED");
- }
- } else if (errno != EINTR && errno != EAGAIN
- )
- LOG_ERROR;
-
- return newsocket;
-}
-
-/*
- * cVdrmonClientSocket
- */
-cVdrmanagerClientSocket::cVdrmanagerClientSocket(const char * password, int compressionMode) {
- readbuf = "";
- writebuf = "";
- sendbuf = NULL;
- sendsize = 0;
- sendoffset = 0;
- disconnected = false;
- initDisconnect = false;
- client = ++clientno;
- this->password = password;
- this->compressionMode = compressionMode;
- login = false;
- compression = false;
- initCompression = false;
-}
-
-cVdrmanagerClientSocket::~cVdrmanagerClientSocket() {
-}
-
-bool cVdrmanagerClientSocket::IsLineComplete() {
- // check a for complete line
- string::size_type pos = readbuf.find("\r", 0);
- if (pos == string::npos)
- pos = readbuf.find("\n");
- return pos != string::npos;
-}
-
bool cVdrmanagerSocket::IsPasswordSet(){
- return strcmp(password, "");
-}
-
-bool cVdrmanagerClientSocket::GetLine(string& line) {
- // check the line
- string::size_type pos = readbuf.find("\r", 0);
- if (pos == string::npos)
- pos = readbuf.find("\n", 0);
- if (pos == string::npos)
- return false;
-
- // extract the line ...
- line = readbuf.substr(0, pos);
-
- // handle \r\n
- if (readbuf[pos] == '\r' && readbuf.length() > pos
- && readbuf[pos + 1] == '\n')
- pos++;
-
- // ... and move the remainder
- readbuf = readbuf.substr(pos + 1);
-
- return true;
+ return strcmp(password, "");
}
-bool cVdrmanagerClientSocket::Read() {
- if (Disconnected())
- return false;
-
- int rc;
- bool len = 0;
- char buf[2001];
- while ((rc = read(sock, buf, sizeof(buf) - 1)) > 0) {
- buf[rc] = 0;
- readbuf += buf;
- len += rc;
- }
-
- if (rc < 0 && errno != EAGAIN)
- {
- LOG_ERROR;
- return false;
- } else if (rc == 0) {
- disconnected = true;
- }
-
- return len > 0;
-}
-
-bool cVdrmanagerClientSocket::Disconnected() {
- return disconnected;
-}
-
-void cVdrmanagerClientSocket::Disconnect() {
- initDisconnect = true;
-}
-
-bool cVdrmanagerClientSocket::PutLine(string line) {
-
- // fill writebuf
- if (line.length() > 0) {
- writebuf += line;
- return true;
- }
-
- // initialize sendbuf if needed
- if (sendbuf == NULL) {
- if (!compression) {
- sendbuf = (char *)malloc(writebuf.length()+1);
- strcpy(sendbuf, writebuf.c_str());
- sendsize = writebuf.length();
- } else {
- Compress();
- }
- sendoffset = 0;
- writebuf.clear();
- }
-
- // send data
- if (sendsize > 0) {
-
- // write so many bytes as possible
- int rc = write(sock, sendbuf + sendoffset, sendsize);
- if (rc < 0 && errno != EAGAIN)
- {
- LOG_ERROR;
-
- if (sendbuf != NULL) {
- free(sendbuf);
- sendbuf = NULL;
- }
-
- return false;
- }
- sendsize -= rc;
- sendoffset += rc;
- }
-
- if (sendsize == 0) {
-
- if (sendbuf != NULL) {
- free(sendbuf);
- sendbuf = NULL;
- }
-
- if (initCompression) {
- isyslog("Compression is activated now");
- initCompression = false;
- compression = true;
- }
-
- if (initDisconnect) {
- initDisconnect = false;
- disconnected = true;
- }
- }
-
- return true;
-}
-
-bool cVdrmanagerClientSocket::Flush() {
- return PutLine("");
-}
-
-bool cVdrmanagerClientSocket::Attach(int fd) {
- sock = fd;
- return MakeDontBlock();
-}
-
-int cVdrmanagerClientSocket::GetClientId() {
- return client;
-}
-
-bool cVdrmanagerClientSocket::WritePending() {
- return sendsize > 0;
-}
-
-bool cVdrmanagerClientSocket::IsLoggedIn() {
- return login || !password || !*password;
-}
-
-void cVdrmanagerClientSocket::SetLoggedIn() {
- login = true;
-}
-
-void cVdrmanagerClientSocket::ActivateCompression() {
-
- string mode = "NONE";
- switch (compressionMode) {
- case COMPRESSION_GZIP:
- mode = "GZIP";
- initCompression = true;
- break;
- case COMPRESSION_ZLIB:
- mode = "ZLIB";
- initCompression = true;
- break;
- default:
- mode = "NONE";
- break;
- }
-
- PutLine("!OK " + mode + "\r\n");
-}
-
-void cVdrmanagerClientSocket::Compress() {
- cCompressor compressor = cCompressor();
-
- switch (compressionMode) {
- case COMPRESSION_GZIP:
- compressor.CompressGzip(writebuf);
- break;
- case COMPRESSION_ZLIB:
- compressor.CompressZlib(writebuf);
- break;
- }
-
- sendbuf = compressor.GetData();
- sendsize = compressor.getDataSize();
-
- double ratio = 1.0 * writebuf.length() / sendsize;
- dsyslog("[vdrmanager] Compression stats: raw %ld, compressed %ld, ratio %f:1", writebuf.length(), sendsize, ratio);
-}
diff --git a/vdr-vdrmanager/sock.h b/vdr-vdrmanager/sock.h
index 25a7b83..f9e3ebf 100644
--- a/vdr-vdrmanager/sock.h
+++ b/vdr-vdrmanager/sock.h
@@ -8,8 +8,13 @@
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
+#include <openssl/ssl.h>
#include <string>
+#define SSL_NO_RETRY 0
+#define SSL_RETRY_READ 1
+#define SSL_RETRY_WRITE 2
+
using namespace std;
class cVdrmanagerSocket
@@ -30,47 +35,4 @@ public:
const char * GetPassword();
};
-class cVdrmanagerClientSocket : public cVdrmanagerSocket
-{
-private:
- string readbuf;
- string writebuf;
- char * sendbuf;
- size_t sendsize;
- size_t sendoffset;
- bool disconnected;
- bool initDisconnect;
- int client;
- bool login;
- bool compression;
- bool initCompression;
- int compressionMode;
-public:
- cVdrmanagerClientSocket(const char * password, int compressionMode);
- virtual ~cVdrmanagerClientSocket();
- bool Attach(int fd);
- bool IsLineComplete();
- bool GetLine(string& line);
- bool PutLine(string line);
- bool Read();
- bool Disconnected();
- void Disconnect();
- bool Flush();
- int GetClientId();
- bool WritePending();
- bool IsLoggedIn();
- void SetLoggedIn();
- void ActivateCompression();
- void Compress();
-};
-
-class cVdrmanagerServerSocket : public cVdrmanagerSocket
-{
-public:
- cVdrmanagerServerSocket();
- virtual ~cVdrmanagerServerSocket();
- bool Create(int port, const char * password, bool forceCheckSvdrp, int compressionMode);
- cVdrmanagerClientSocket * Accept();
-};
-
#endif
diff --git a/vdr-vdrmanager/vdrmanager.cpp b/vdr-vdrmanager/vdrmanager.cpp
index 57393a3..4feb5f5 100644
--- a/vdr-vdrmanager/vdrmanager.cpp
+++ b/vdr-vdrmanager/vdrmanager.cpp
@@ -14,7 +14,10 @@
#include "vdrmanagerthread.h"
#include "compressor.h"
-#define VDRMANAGER_PORT 6420
+#define VDRMANAGER_PORT 6420
+#define VDRMANAGER_SSL_PORT 6421
+#define VDRMANAGER_CRT_FILE "/etc/vdr/plugins/vdrmanager/vdrmanager.pem"
+#define VDRMANAGER_KEY_FILE "/etc/vdr/plugins/vdrmanager/vdrmanager.pem"
static const char *VERSION = "0.11";
static const char *DESCRIPTION = "VDR-Manager support plugin";
@@ -24,9 +27,12 @@ private:
// Add any member variables or functions you may need here.
cVdrManagerThread * Thread;
int port;
+ int sslport;
const char * password;
bool forceCheckSvdrp;
int compressionMode;
+ const char * certFile;
+ const char * keyFile;
protected:
public:
cVdrManager(void);
@@ -56,9 +62,12 @@ cVdrManager::cVdrManager(void) {
// VDR OBJECTS TO EXIST OR PRODUCE ANY OUTPUT!
Thread = NULL;
port = VDRMANAGER_PORT;
+ sslport = VDRMANAGER_SSL_PORT;
password = "";
forceCheckSvdrp = false;
compressionMode = COMPRESSION_NONE;
+ certFile = VDRMANAGER_CRT_FILE;
+ keyFile = VDRMANAGER_KEY_FILE;
}
cVdrManager::~cVdrManager() {
@@ -74,18 +83,27 @@ cMenuSetupPage * cVdrManager::SetupMenu(void) {
}
const char * cVdrManager::CommandLineHelp(void) {
- return " -p port port number to listen to\n"
- " -P password password (none if not given). No password forces check against svdrphosts.conf.\n"
- " -s force check against svdrphosts.conf, even if a password was given\n"
- " -c compression selects the compression mode to use (zlib or gzip). Default is zlib";
+ return
+ " -p port[,sslport] port number to listen to (sslport = port+1 if not given\n"
+ " -P password password (none if not given). No password forces check against svdrphosts.conf.\n"
+ " -s force check against svdrphosts.conf, even if a password was given\n"
+ " -c compression selects the compression mode to use (zlib or gzip). Default is zlib\n"
+ " -k certfile[,keyfile] cert and key file for SSL (or one file for both)";
}
bool cVdrManager::ProcessArgs(int argc, char *argv[]) {
int c;
- while ((c = getopt(argc, argv, "c::p:P:s")) != -1)
+ while ((c = getopt(argc, argv, "c::p:P:st:k:")) != -1)
switch (c) {
case 'p':
port = atoi(optarg);
+ {
+ const char * sep = strchr(optarg, ',');
+ if (sep)
+ sslport = atoi(sep+1);
+ else
+ sslport = port+1;
+ }
break;
case 'P':
password = optarg;
@@ -104,6 +122,17 @@ bool cVdrManager::ProcessArgs(int argc, char *argv[]) {
return false;
}
break;
+ case 'k':
+ {
+ const char * sep = strchr(optarg, ',');
+ if (sep == NULL) {
+ certFile = keyFile = optarg;
+ } else {
+ certFile = strndup(optarg, sep-optarg);
+ keyFile = sep;
+ }
+ }
+ break;
case '?':
return false;
default:
@@ -113,6 +142,8 @@ bool cVdrManager::ProcessArgs(int argc, char *argv[]) {
// default port
if (port <= 0)
port = VDRMANAGER_PORT;
+ if (sslport <= 0)
+ sslport = port+1;
return true;
}
@@ -121,8 +152,8 @@ bool cVdrManager::Initialize(void) {
// Initialize any background activities the plugin shall perform.
// Start any background activities the plugin shall perform.
- Thread = new cVdrManagerThread(port, password, forceCheckSvdrp,
- compressionMode);
+ Thread = new cVdrManagerThread(port, sslport, password, forceCheckSvdrp,
+ compressionMode, certFile, keyFile);
return Thread != NULL;
}
diff --git a/vdr-vdrmanager/vdrmanagerthread.cpp b/vdr-vdrmanager/vdrmanagerthread.cpp
index 51301e5..55a3c90 100644
--- a/vdr-vdrmanager/vdrmanagerthread.cpp
+++ b/vdr-vdrmanager/vdrmanagerthread.cpp
@@ -8,13 +8,17 @@
#include "select.h"
#include "helpers.h"
-cVdrManagerThread::cVdrManagerThread(int port, const char * password, bool forceCheckSvdrp, int compressionMode)
+cVdrManagerThread::cVdrManagerThread(int port, int sslPort, const char * password, bool forceCheckSvdrp, int compressionMode,
+ const char * certFile, const char * keyFile)
{
select = NULL;
- this -> port = port;
- this -> password = password;
- this -> forceCheckSvdrp = forceCheckSvdrp;
- this -> compressionMode = compressionMode;
+ this->port = port;
+ this->sslPort = sslPort;
+ this->password = password;
+ this->forceCheckSvdrp = forceCheckSvdrp;
+ this->compressionMode = compressionMode;
+ this->certFile = certFile;
+ this->keyFile = keyFile;
}
cVdrManagerThread::~cVdrManagerThread()
@@ -25,8 +29,10 @@ cVdrManagerThread::~cVdrManagerThread()
void cVdrManagerThread::Action(void)
{
// create listener socket
- if (!Init())
+ if (!Init()) {
+ Cleanup();
return;
+ }
// do processing
select->Action();
@@ -44,19 +50,35 @@ bool cVdrManagerThread::Init()
// create server socket
cVdrmanagerServerSocket * sock = new cVdrmanagerServerSocket();
- if (sock == NULL || !sock->Create(port, password, forceCheckSvdrp, compressionMode))
+ if (sock == NULL || !sock->Create(port, password, forceCheckSvdrp, compressionMode, NULL, NULL))
return false;
- // register server socket
- select->SetServerSocket(sock);
+ // register server sockets
+ select->SetServerSockets(sock, NULL);
+
+ cVdrmanagerServerSocket * sslSock;
+ if (!access(certFile, R_OK) && !access(keyFile, R_OK)) {
+ sslSock = new cVdrmanagerServerSocket();
+ if (sslSock == NULL || !sslSock->Create(sslPort, password, forceCheckSvdrp, compressionMode, certFile, keyFile)) {
+ return false;
+ }
+ } else {
+ sslSock = NULL;
+ isyslog("[vdrmanager] SSL key files %s and %s can't be read. SSL disabled.", certFile, keyFile);
+ }
+
+ // register server sockets
+ select->SetServerSockets(sock, sslSock);
return true;
}
void cVdrManagerThread::Cleanup()
{
- if (select)
+ if (select) {
delete select;
+ select = NULL;
+ }
}
void cVdrManagerThread::Shutdown()
diff --git a/vdr-vdrmanager/vdrmanagerthread.h b/vdr-vdrmanager/vdrmanagerthread.h
index 0dd3646..57e129b 100644
--- a/vdr-vdrmanager/vdrmanagerthread.h
+++ b/vdr-vdrmanager/vdrmanagerthread.h
@@ -20,11 +20,15 @@ class cVdrManagerThread : public cThread {
private:
cSelect * select;
int port;
+ int sslPort;
const char * password;
bool forceCheckSvdrp;
int compressionMode;
+ const char * certFile;
+ const char * keyFile;
public:
- cVdrManagerThread(int port, const char * password, bool forceCheckSvdrp, int compressionMode);
+ cVdrManagerThread(int port, int sslPort, const char * password, bool forceCheckSvdrp, int compressionMode,
+ const char * certFile, const char * keyFile);
virtual void Action(void);
void Shutdown();
private: