diff options
-rw-r--r-- | vdr-vdrmanager/sock.cpp | 104 | ||||
-rw-r--r-- | vdr-vdrmanager/sock.h | 10 | ||||
-rw-r--r-- | vdr-vdrmanager/vdrmanager.cpp | 12 | ||||
-rw-r--r-- | vdr-vdrmanager/vdrmanagerthread.cpp | 29 | ||||
-rw-r--r-- | vdr-vdrmanager/vdrmanagerthread.h | 5 |
5 files changed, 142 insertions, 18 deletions
diff --git a/vdr-vdrmanager/sock.cpp b/vdr-vdrmanager/sock.cpp index 1d17ee2..e2d4d36 100644 --- a/vdr-vdrmanager/sock.cpp +++ b/vdr-vdrmanager/sock.cpp @@ -3,6 +3,8 @@ */ #include <unistd.h> #include <vdr/plugin.h> +#include <openssl/ssl.h> +#include <openssl/err.h> #include "sock.h" #include "helpers.h" @@ -13,6 +15,9 @@ static int clientno = 0; */ cVdrmanagerSocket::cVdrmanagerSocket() { sock = -1; + useSSL = false; + password = ""; + forceCheckSvdrp = false; } cVdrmanagerSocket::~cVdrmanagerSocket() { @@ -50,20 +55,37 @@ const char * cVdrmanagerSocket::GetPassword() { return password; } +void cVdrmanagerSocket::LogSSLError() { + + char * error = ERR_error_string(ERR_get_error(), NULL); + + esyslog("SSL error: %s", error); + +} + /* * cVdrmonServerSocket */ -cVdrmanagerServerSocket::cVdrmanagerServerSocket() : - cVdrmanagerSocket() { +cVdrmanagerServerSocket::cVdrmanagerServerSocket() : cVdrmanagerSocket() { + + sslContext = NULL; } cVdrmanagerServerSocket::~cVdrmanagerServerSocket() { } -bool cVdrmanagerServerSocket::Create(int port, const char * password, bool forceCheckSvrp) { - // save password +bool cVdrmanagerServerSocket::Create(int port, const char * password, bool forceCheckSvrp, + bool useSSL, const char * pemFile) { + this->password = password; this->forceCheckSvdrp = forceCheckSvrp; + this->useSSL = useSSL; + + // create SSL context + if (useSSL && !InitSSL(pemFile)) { + return false; + } + // create socket sock = socket(PF_INET, SOCK_STREAM, 0); if (sock < 0) { @@ -117,6 +139,12 @@ cVdrmanagerClientSocket * cVdrmanagerServerSocket::Accept() { return NULL; } + // Attach client SSL + if (!newsocket->InitSSL(sslContext)) { + delete newsocket; + return NULL; + } + if (!IsPasswordSet() || forceCheckSvdrp == true) { bool accepted = SVDRPhosts.Acceptable(clientname.sin_addr.s_addr); if (!accepted) { @@ -127,14 +155,35 @@ cVdrmanagerClientSocket * cVdrmanagerServerSocket::Accept() { } 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 - ) + } else if (errno != EINTR && errno != EAGAIN) { LOG_ERROR; + } return newsocket; } +bool cVdrmanagerServerSocket::InitSSL(const char * pemFile) { + + sslContext = SSL_CTX_new(SSLv3_server_method()); + if (sslContext == NULL) { + LogSSLError(); + return false; + } + + if (SSL_CTX_use_certificate_file(sslContext, pemFile, SSL_FILETYPE_PEM) != 1) { + LogSSLError(); + return false; + } + + if (SSL_CTX_use_PrivateKey_file(sslContext, pemFile, SSL_FILETYPE_PEM) != 1) { + LogSSLError(); + return false; + } + + return true; +} /* * cVdrmonClientSocket */ @@ -147,6 +196,10 @@ cVdrmanagerClientSocket::cVdrmanagerClientSocket(const char * password) { } cVdrmanagerClientSocket::~cVdrmanagerClientSocket() { + + if (sslContext) { + SSL_free(sslContext); + } } bool cVdrmanagerClientSocket::IsLineComplete() { @@ -184,13 +237,24 @@ bool cVdrmanagerClientSocket::GetLine(string& line) { } bool cVdrmanagerClientSocket::Read() { + if (Disconnected()) return false; int rc; bool len = 0; char buf[2001]; - while ((rc = read(sock, buf, sizeof(buf) - 1)) > 0) { + + for(;;) { + if (useSSL) { + rc = read(sock, buf, sizeof(buf)-1); + } else { + rc = SSL_read(sslContext, buf, sizeof(buf)-1); + } + + if (rc <= 0) + break; + buf[rc] = 0; readbuf += buf; len += rc; @@ -229,8 +293,12 @@ bool cVdrmanagerClientSocket::PutLine(string line) { // data present? if (writebuf.length() > 0) { - // write so many bytes as possible - int rc = write(sock, writebuf.c_str(), writebuf.length()); + int rc; + if (useSSL) { + rc = SSL_write(sslContext, writebuf.c_str(), writebuf.length()); + } else { + rc = write(sock, writebuf.c_str(), writebuf.length()); + } if (rc < 0 && errno != EAGAIN) { LOG_ERROR; @@ -270,3 +338,21 @@ bool cVdrmanagerClientSocket::IsLoggedIn() { void cVdrmanagerClientSocket::SetLoggedIn() { login = true; } + +bool::cVdrmanagerClientSocket::InitSSL(SSL_CTX * sslContext) { + + // create a new SSL context + this->sslContext = SSL_new(sslContext); + if (this->sslContext == NULL) { + LOG_ERROR_STR("Error creating new SSL context"); + return false; + } + + // connect context to the socket + if (SSL_set_fd(this->sslContext, sock) != 1) { + SSL_free(this->sslContext); + this->sslContext = NULL; + LOG_ERROR_STR("Error connecting SSL and socket"); + return false; + } +} diff --git a/vdr-vdrmanager/sock.h b/vdr-vdrmanager/sock.h index 0234afc..94da4b2 100644 --- a/vdr-vdrmanager/sock.h +++ b/vdr-vdrmanager/sock.h @@ -8,6 +8,7 @@ #include <sys/types.h> #include <sys/socket.h> #include <string> +#include <openssl/ssl.h> using namespace std; @@ -17,6 +18,7 @@ protected: int sock; const char * password; bool forceCheckSvdrp; + bool useSSL; protected: cVdrmanagerSocket(); bool IsPasswordSet(); @@ -26,6 +28,7 @@ public: int GetSocket(); bool MakeDontBlock(); const char * GetPassword(); + void LogSSLError(); }; class cVdrmanagerClientSocket : public cVdrmanagerSocket @@ -36,6 +39,7 @@ private: bool disconnected; int client; bool login; + SSL * sslContext; public: cVdrmanagerClientSocket(const char * password); virtual ~cVdrmanagerClientSocket(); @@ -51,15 +55,19 @@ public: bool WritePending(); bool IsLoggedIn(); void SetLoggedIn(); + bool InitSSL(SSL_CTX * sslContext); }; class cVdrmanagerServerSocket : public cVdrmanagerSocket { +private: + SSL_CTX * sslContext; public: cVdrmanagerServerSocket(); virtual ~cVdrmanagerServerSocket(); - bool Create(int port, const char * password, bool forceCheckSvdrp); + bool Create(int port, const char * password, bool forceCheckSvdrp, bool useSSL, const char * pemFile); cVdrmanagerClientSocket * Accept(); + bool InitSSL(const char * pemFile); }; #endif diff --git a/vdr-vdrmanager/vdrmanager.cpp b/vdr-vdrmanager/vdrmanager.cpp index 2b81464..96c5f6f 100644 --- a/vdr-vdrmanager/vdrmanager.cpp +++ b/vdr-vdrmanager/vdrmanager.cpp @@ -25,6 +25,8 @@ private: int port; const char * password; bool forceCheckSvdrp; + bool useSSL; + const char * pemFile; bool forceDelete; protected: public: @@ -58,6 +60,8 @@ cVdrManager::cVdrManager(void) { password = ""; forceCheckSvdrp = false; forceDelete = false; + useSSL = false; + pemFile = NULL; } cVdrManager::~cVdrManager() { @@ -78,8 +82,12 @@ const char * cVdrManager::CommandLineHelp(void) { bool cVdrManager::ProcessArgs(int argc, char *argv[]) { int c; - while ((c = getopt(argc, argv, "p:P:s:f")) != -1) + while ((c = getopt(argc, argv, "c:p:P:s:f")) != -1) switch (c) { + case 'c': + pemFile = optarg; + useSSL = true; + break; case 'p': port = atoi(optarg); break; @@ -115,7 +123,7 @@ 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); + Thread = new cVdrManagerThread(port, password, forceCheckSvdrp, useSSL, pemFile); return Thread != NULL; } diff --git a/vdr-vdrmanager/vdrmanagerthread.cpp b/vdr-vdrmanager/vdrmanagerthread.cpp index 2a4ca64..977f3d1 100644 --- a/vdr-vdrmanager/vdrmanagerthread.cpp +++ b/vdr-vdrmanager/vdrmanagerthread.cpp @@ -4,16 +4,21 @@ #include <string.h> #include <vdr/plugin.h> #include <vdr/thread.h> +#include <openssl/ssl.h> + #include "vdrmanagerthread.h" #include "select.h" #include "helpers.h" -cVdrManagerThread::cVdrManagerThread(int port, const char * password, bool forceCheckSvdrp) +cVdrManagerThread::cVdrManagerThread(int port, const char * password, bool forceCheckSvdrp, + bool useSSL, const char * pemFile) { select = NULL; - this -> port = port; - this -> password = password; - this -> forceCheckSvdrp = forceCheckSvdrp; + this->port = port; + this->password = password; + this->forceCheckSvdrp = forceCheckSvdrp; + this->useSSL = useSSL; + this->pemFile = pemFile; } cVdrManagerThread::~cVdrManagerThread() @@ -23,6 +28,11 @@ cVdrManagerThread::~cVdrManagerThread() void cVdrManagerThread::Action(void) { + // initialize SSL + if (useSSL) { + InitSSL(); + } + // create listener socket if (!Init()) return; @@ -43,7 +53,7 @@ bool cVdrManagerThread::Init() // create server socket cVdrmanagerServerSocket * sock = new cVdrmanagerServerSocket(); - if (sock == NULL || !sock->Create(port, password, forceCheckSvdrp)) + if (sock == NULL || !sock->Create(port, password, forceCheckSvdrp, useSSL, pemFile)) return false; // register server socket @@ -61,3 +71,12 @@ void cVdrManagerThread::Cleanup() void cVdrManagerThread::Shutdown() { } + +bool cVdrManagerThread::InitSSL() { + + SSL_library_init(); + SSL_load_error_strings(); + ERR_load_BIO_strings(); + ERR_load_SSL_strings(); + +} diff --git a/vdr-vdrmanager/vdrmanagerthread.h b/vdr-vdrmanager/vdrmanagerthread.h index 83f5f31..ac3551b 100644 --- a/vdr-vdrmanager/vdrmanagerthread.h +++ b/vdr-vdrmanager/vdrmanagerthread.h @@ -22,14 +22,17 @@ private: int port; const char * password; bool forceCheckSvdrp; + bool useSSL; + const char * pemFile; public: - cVdrManagerThread(int port, const char * password, bool forceCheckSvdrp); + cVdrManagerThread(int port, const char * password, bool forceCheckSvdrp, bool useSSL, const char * pemFile); virtual void Action(void); void Shutdown(); private: virtual ~cVdrManagerThread(); void Cleanup(); bool Init(); + bool InitSSL(); }; #endif |