diff --git a/src/TLSClient.cpp b/src/TLSClient.cpp index 27a31b0bd..0ee60c201 100644 --- a/src/TLSClient.cpp +++ b/src/TLSClient.cpp @@ -54,6 +54,39 @@ static void gnutls_log_function (int level, const char* message) std::cout << "c: " << level << " " << message; } +//////////////////////////////////////////////////////////////////////////////// +static int verify_certificate_callback (gnutls_session_t session) +{ + if (trust_override) + return 0; + + // Get the hostname from the session. + const char* hostname = (const char*) gnutls_session_get_ptr (session); + + // This verification function uses the trusted CAs in the credentials + // structure. So you must have installed one or more CA certificates. + unsigned int status; + int ret = gnutls_certificate_verify_peers3 (session, hostname, &status); + if (ret < 0) + return GNUTLS_E_CERTIFICATE_ERROR; + + gnutls_certificate_type_t type = gnutls_certificate_type_get (session); + gnutls_datum_t out; + ret = gnutls_certificate_verification_status_print (status, type, &out, 0); + if (ret < 0) + return GNUTLS_E_CERTIFICATE_ERROR; + + std::cout << "c: INFO " << out.data << "\n"; + + gnutls_free (out.data); + + if (status != 0) + return GNUTLS_E_CERTIFICATE_ERROR; + + // Continue handshake. + return 0; +} + //////////////////////////////////////////////////////////////////////////////// TLSClient::TLSClient () : _ca ("") @@ -109,16 +142,26 @@ void TLSClient::trust (bool value) } //////////////////////////////////////////////////////////////////////////////// -void TLSClient::init (const std::string& ca) +void TLSClient::init ( + const std::string& cert, + const std::string& key) { - _ca = ca; - File ca_file (_ca); - if (!ca_file.exists ()) - throw std::string (STRING_CMD_SYNC_NO_CA); + _cert = cert; + _key = key; gnutls_global_init (); gnutls_certificate_allocate_credentials (&_credentials); - gnutls_certificate_set_x509_trust_file (_credentials, _ca.c_str (), GNUTLS_X509_FMT_PEM); + + if (_cert != "" && + gnutls_certificate_set_x509_trust_file (_credentials, _cert.c_str (), GNUTLS_X509_FMT_PEM) < 0) + throw std::string ("Missing CA file."); + + if (_cert != "" && + _key != "" && + gnutls_certificate_set_x509_key_file (_credentials, _cert.c_str (), _key.c_str (), GNUTLS_X509_FMT_PEM) < 0) + throw std::string ("Missing CERT file."); + + gnutls_certificate_set_verify_function (_credentials, verify_certificate_callback); gnutls_init (&_session, GNUTLS_CLIENT); // Use default priorities. diff --git a/src/TLSClient.h b/src/TLSClient.h index 668a04992..d7462fbee 100644 --- a/src/TLSClient.h +++ b/src/TLSClient.h @@ -40,7 +40,7 @@ public: void limit (int); void debug (int); void trust (bool); - void init (const std::string&); + void init (const std::string&, const std::string&); void connect (const std::string&, const std::string&); void bye (); @@ -49,6 +49,8 @@ public: private: std::string _ca; + std::string _cert; + std::string _key; gnutls_certificate_credentials_t _credentials; gnutls_session_t _session; int _socket; diff --git a/src/commands/CmdSync.cpp b/src/commands/CmdSync.cpp index fe557142a..4d7daae20 100644 --- a/src/commands/CmdSync.cpp +++ b/src/commands/CmdSync.cpp @@ -88,10 +88,21 @@ int CmdSync::execute (std::string& output) if (credentials.size () != 3) throw std::string (STRING_CMD_SYNC_BAD_CRED); + bool trust = context.config.getBoolean ("taskd.trust"); +/* + File ca (context.config.get ("taskd.ca")); + if (ca._data != "" && ! ca.exists ()) + throw std::string (STRING_CMD_SYNC_BAD_CA); +*/ + File certificate (context.config.get ("taskd.certificate")); if (! certificate.exists ()) throw std::string (STRING_CMD_SYNC_BAD_CERT); + File key (context.config.get ("taskd.key")); + if (! key.exists ()) + throw std::string (STRING_CMD_SYNC_BAD_KEY); + // If this is a first-time initialization, send pending.data, not // backlog.data. std::string payload = ""; @@ -146,7 +157,7 @@ int CmdSync::execute (std::string& output) signal (SIGUSR2, SIG_IGN); Msg response; - if (send (connection, certificate._data, request, response)) + if (send (connection, certificate._data, key._data, trust, request, response)) { std::string code = response.get ("code"); if (code == "200") @@ -304,6 +315,8 @@ int CmdSync::execute (std::string& output) bool CmdSync::send ( const std::string& to, const std::string& certificate, + const std::string& key, + bool trust, const Msg& request, Msg& response) { @@ -315,14 +328,13 @@ bool CmdSync::send ( std::string server = to.substr (0, colon); std::string port = to.substr (colon + 1); - File cert (certificate); - try { // A very basic TLS client, with X.509 authentication. TLSClient client; client.debug (context.config.getInteger ("debug.tls")); - client.init (cert); + client.trust (trust); + client.init (certificate, key); client.connect (server, port); client.send (request.serialize () + "\n"); diff --git a/src/commands/CmdSync.h b/src/commands/CmdSync.h index 6bae60f49..d4cee496a 100644 --- a/src/commands/CmdSync.h +++ b/src/commands/CmdSync.h @@ -39,7 +39,7 @@ public: int execute (std::string&); private: - bool send (const std::string&, const std::string&, const Msg&, Msg&); + bool send (const std::string&, const std::string&, const std::string&, bool, const Msg&, Msg&); }; #endif