summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbju <bju@maxi.fritz.box>2017-05-04 23:58:02 +0200
committerbju <bju@maxi.fritz.box>2017-05-04 23:58:02 +0200
commit049975cbda6327aae542bac5dd1acd6fe97d18a4 (patch)
tree687b5cf1191b03613d321aadf0438d28c886778b
parent888f87e2ac5fc9ed6e8f40141252dac302ddb688 (diff)
downloadvdr-manager-049975cbda6327aae542bac5dd1acd6fe97d18a4.tar.gz
vdr-manager-049975cbda6327aae542bac5dd1acd6fe97d18a4.tar.bz2
Feature #2496: Support certificate replacement without VDR restart
-rw-r--r--vdr-vdrmanager/clientsock.cpp81
-rw-r--r--vdr-vdrmanager/clientsock.h6
-rw-r--r--vdr-vdrmanager/serversock.cpp107
-rw-r--r--vdr-vdrmanager/serversock.h1
-rw-r--r--vdr-vdrmanager/sock.h2
5 files changed, 117 insertions, 80 deletions
diff --git a/vdr-vdrmanager/clientsock.cpp b/vdr-vdrmanager/clientsock.cpp
index 3f78007..0bce192 100644
--- a/vdr-vdrmanager/clientsock.cpp
+++ b/vdr-vdrmanager/clientsock.cpp
@@ -17,7 +17,7 @@ static int clientno = 0;
/*
* cVdrmonClientSocket
*/
-cVdrmanagerClientSocket::cVdrmanagerClientSocket(const char * password, int compressionMode) {
+cVdrmanagerClientSocket::cVdrmanagerClientSocket(const char * password, int compressionMode, const char * certFile, const char * keyFile) {
readbuf = "";
writebuf = "";
sendbuf = NULL;
@@ -28,6 +28,8 @@ cVdrmanagerClientSocket::cVdrmanagerClientSocket(const char * password, int comp
client = ++clientno;
this->password = password;
this->compressionMode = compressionMode;
+ this->certFile = certFile;
+ this->keyFile = keyFile;
login = false;
compression = false;
initCompression = false;
@@ -43,6 +45,9 @@ cVdrmanagerClientSocket::~cVdrmanagerClientSocket() {
if (ssl) {
SSL_free(ssl);
}
+ if (sslCtx) {
+ SSL_CTX_free(sslCtx);
+ }
#endif
}
@@ -292,6 +297,64 @@ int cVdrmanagerClientSocket::FlushNoSSL() {
#if VDRMANAGER_USE_SSL
+bool cVdrmanagerClientSocket::LoadCerts() {
+
+ if (certFile) {
+ isyslog("[vdrmanager] initialize SSL context");
+
+ SSL_METHOD * method = (SSL_METHOD *)SSLv23_server_method();
+ sslCtx = SSL_CTX_new(method);
+ if (sslCtx == NULL) {
+ long errorCode = ERR_get_error();
+ char * error = ERR_error_string(errorCode, NULL);
+ esyslog("[vdrmanager] Error initializing SSL context: %s", error);
+ SSL_CTX_free(sslCtx);
+ sslCtx = NULL;
+ return false;
+ }
+ SSL_CTX_set_options(sslCtx, SSL_OP_NO_SSLv3);
+
+ /* set the local certificate from CertFile */
+ if (SSL_CTX_use_certificate_chain_file(sslCtx, certFile) != 1) {
+ long errorCode = ERR_get_error();
+ char * error = ERR_error_string(errorCode, NULL);
+ esyslog("[vdrmanager] Error loading cert chain file %s: %s", certFile, error);
+ SSL_CTX_free(sslCtx);
+ sslCtx = NULL;
+ } else {
+ isyslog("[vdrmanager] cert chain file loaded %s", certFile);
+ }
+
+ /* set the private key from KeyFile */
+ if (SSL_CTX_use_PrivateKey_file(sslCtx, keyFile, SSL_FILETYPE_PEM) != 1) {
+ long errorCode = ERR_get_error();
+ char * error = ERR_error_string(errorCode, NULL);
+ esyslog("[vdrmanager] Error loading key file %s: %s", keyFile, error);
+ SSL_CTX_free(sslCtx);
+ sslCtx = NULL;
+ return false;
+ } else {
+ isyslog("[vdrmanager] key file loaded %s", keyFile);
+ }
+
+ /* verify private key */
+ if (!SSL_CTX_check_private_key(sslCtx)) {
+ long errorCode = ERR_get_error();
+ char * error = ERR_error_string(errorCode, NULL);
+ esyslog("[vdrmanager] Error checking SSL keys: %s", error);
+ SSL_CTX_free(sslCtx);
+ sslCtx = NULL;
+ return false;
+ }
+
+ SSL_CTX_set_mode(sslCtx, SSL_MODE_ENABLE_PARTIAL_WRITE);
+
+ return true;
+ }
+
+ return true;
+}
+
int cVdrmanagerClientSocket::FlushSSL() {
sslReadWrite = SSL_NO_RETRY;
@@ -325,20 +388,22 @@ int cVdrmanagerClientSocket::FlushSSL() {
#endif
-bool cVdrmanagerClientSocket::Attach(int fd, SSL_CTX * sslCtx) {
+bool cVdrmanagerClientSocket::Attach(int fd) {
sock = fd;
if (!MakeDontBlock()) {
return false;
}
#if VDRMANAGER_USE_SSL
- if (sslCtx) {
- ssl = SSL_new(sslCtx);
- SSL_set_accept_state(ssl);
- BIO *bio = BIO_new_socket(sock, BIO_NOCLOSE);
- SSL_set_bio(ssl, bio, bio);
- BIO_set_nbio(bio, 1);
+
+ if (!LoadCerts()) {
+ return false;
}
+ ssl = SSL_new(sslCtx);
+ SSL_set_accept_state(ssl);
+ BIO *bio = BIO_new_socket(sock, BIO_NOCLOSE);
+ SSL_set_bio(ssl, bio, bio);
+ BIO_set_nbio(bio, 1);
#endif
return true;
diff --git a/vdr-vdrmanager/clientsock.h b/vdr-vdrmanager/clientsock.h
index 6c3fba3..c2062e6 100644
--- a/vdr-vdrmanager/clientsock.h
+++ b/vdr-vdrmanager/clientsock.h
@@ -37,14 +37,15 @@ private:
bool initCompression;
int compressionMode;
#if VDRMANAGER_USE_SSL
+ SSL_CTX * sslCtx;
SSL * ssl;
int sslReadWrite;
int sslWantsSelect;
#endif
public:
- cVdrmanagerClientSocket(const char * password, int compressionMode);
+ cVdrmanagerClientSocket(const char * password, int compressionMode, const char * certFile, const char * keyFile);
virtual ~cVdrmanagerClientSocket();
- bool Attach(int fd, SSL_CTX * sslCtx);
+ bool Attach(int fd);
bool IsLineComplete();
bool GetLine(string& line);
void Write(string line);
@@ -58,6 +59,7 @@ public:
int GetSslReadWrite();
int GetSslWantsSelect();
bool IsSSL();
+ bool LoadCerts();
#endif
bool Disconnected();
void Disconnect();
diff --git a/vdr-vdrmanager/serversock.cpp b/vdr-vdrmanager/serversock.cpp
index 0cd9f1f..0c44a45 100644
--- a/vdr-vdrmanager/serversock.cpp
+++ b/vdr-vdrmanager/serversock.cpp
@@ -19,14 +19,9 @@ static int clientno = 0;
*/
cVdrmanagerServerSocket::cVdrmanagerServerSocket() : cVdrmanagerSocket() {
port = -1;
- sslCtx = NULL;
}
cVdrmanagerServerSocket::~cVdrmanagerServerSocket() {
-#if VDRMANAGER_USE_SSL
- if (sslCtx)
- SSL_CTX_free(sslCtx);
-#endif
}
bool cVdrmanagerServerSocket::Create(int port, const char * password, bool forceCheckSvrp, int compressionMode,
@@ -34,8 +29,10 @@ bool cVdrmanagerServerSocket::Create(int port, const char * password, bool force
this->port = port;
this->password = password;
- this->forceCheckSvdrp = forceCheckSvrp;
- this->compressionMode = compressionMode;
+ this->forceCheckSvdrp = forceCheckSvrp;
+ this->compressionMode = compressionMode;
+ this->certFile = certFile;
+ this->keyFile = keyFile;
// create socket
sock = socket(PF_INET, SOCK_STREAM, 0);
@@ -75,8 +72,7 @@ bool cVdrmanagerServerSocket::Create(int port, const char * password, bool force
}
#if VDRMANAGER_USE_SSL
-
- if (certFile) {
+ if (certFile) {
isyslog("[vdrmanager] initialize SSL");
OpenSSL_add_all_algorithms();
@@ -86,71 +82,44 @@ bool cVdrmanagerServerSocket::Create(int port, const char * password, bool force
SSL_load_error_strings();
SSL_library_init();
-
- SSL_METHOD * method = (SSL_METHOD *)SSLv23_server_method();
- sslCtx = SSL_CTX_new(method);
- if (sslCtx == NULL) {
- long errorCode = ERR_get_error();
- char * error = ERR_error_string(errorCode, NULL);
- esyslog("[vdrmanager] Error initializing SSL context: %s", error);
- Close();
- return false;
- }
- SSL_CTX_set_options(sslCtx, SSL_OP_NO_SSLv3);
-
- /* set the local certificate from CertFile */
- SSL_CTX_use_certificate_file(sslCtx, certFile, SSL_FILETYPE_PEM);
- /* set the private key from KeyFile */
- SSL_CTX_use_PrivateKey_file(sslCtx, keyFile, SSL_FILETYPE_PEM);
- /* verify private key */
- if (!SSL_CTX_check_private_key(sslCtx)) {
- long errorCode = ERR_get_error();
- char * error = ERR_error_string(errorCode, NULL);
- esyslog("[vdrmanager] Error checking SSL keys: %s", error);
- Close();
- return false;
- }
-
- SSL_CTX_set_mode(sslCtx, SSL_MODE_ENABLE_PARTIAL_WRITE);
- }
+ }
#endif
-
return true;
}
cVdrmanagerClientSocket * cVdrmanagerServerSocket::Accept() {
- cVdrmanagerClientSocket * newsocket = NULL;
-
- isyslog("[vdrmanager] new %sclient on port %d", sslCtx ? "SSL " : "", port);
-
- // 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, sslCtx)) {
- delete newsocket;
- return NULL;
- }
-
- if (!IsPasswordSet() || forceCheckSvdrp == true) {
- bool accepted = SVDRPhosts.Acceptable(clientname.sin_addr.s_addr);
- if (!accepted) {
- newsocket->Write(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;
+ cVdrmanagerClientSocket * newsocket = NULL;
+
+ isyslog("[vdrmanager] new client on port %d", port);
+
+ // 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, certFile, keyFile);
+ if (!newsocket->Attach(newsock)) {
+ delete newsocket;
+ return NULL;
+ }
+
+ if (!IsPasswordSet() || forceCheckSvdrp == true) {
+ bool accepted = SVDRPhosts.Acceptable(clientname.sin_addr.s_addr);
+ if (!accepted) {
+ newsocket->Write(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;
}
int cVdrmanagerServerSocket::GetPort() {
diff --git a/vdr-vdrmanager/serversock.h b/vdr-vdrmanager/serversock.h
index e8c939e..6269574 100644
--- a/vdr-vdrmanager/serversock.h
+++ b/vdr-vdrmanager/serversock.h
@@ -24,7 +24,6 @@ class cVdrmanagerServerSocket : public cVdrmanagerSocket
{
private:
int port;
- SSL_CTX * sslCtx;
public:
cVdrmanagerServerSocket();
virtual ~cVdrmanagerServerSocket();
diff --git a/vdr-vdrmanager/sock.h b/vdr-vdrmanager/sock.h
index bc19d6d..4cc550f 100644
--- a/vdr-vdrmanager/sock.h
+++ b/vdr-vdrmanager/sock.h
@@ -25,6 +25,8 @@ protected:
const char * password;
bool forceCheckSvdrp;
int compressionMode;
+ const char * certFile;
+ const char * keyFile;
protected:
cVdrmanagerSocket();
bool IsPasswordSet();