]> git.ipfire.org Git - thirdparty/squid.git/blobdiff - src/ssl/ssl_crtd.cc
SourceFormat Enforcement
[thirdparty/squid.git] / src / ssl / ssl_crtd.cc
index 5ec4d0c1f2d3a7b92925cd1b0494b6ffbaa15478..f0181fa42173f2971b2f106f7f8b5bba5eefbf5e 100644 (file)
@@ -1,28 +1,21 @@
 /*
- * $Id$
+ * Copyright (C) 1996-2015 The Squid Software Foundation and contributors
+ *
+ * Squid software is distributed under GPLv2+ license and includes
+ * contributions from numerous individuals and organizations.
+ * Please see the COPYING and CONTRIBUTORS files for details.
  */
 
 #include "squid.h"
 #include "helpers/defines.h"
-#include "ssl/gadgets.h"
-#include "ssl/crtd_message.h"
 #include "ssl/certificate_db.h"
+#include "ssl/crtd_message.h"
 
-#if HAVE_CSTRING
 #include <cstring>
-#endif
-#if HAVE_SSTREAM
-#include <sstream>
-#endif
-#if HAVE_IOSTREAM
 #include <iostream>
-#endif
-#if HAVE_STDEXCEPT
+#include <sstream>
 #include <stdexcept>
-#endif
-#if HAVE_STRING
 #include <string>
-#endif
 #if HAVE_GETOPT_H
 #include <getopt.h>
 #endif
@@ -72,14 +65,9 @@ usage: ssl_crtd -hv -s ssl_storage_path -M storage_max_size
         Create new private key and certificate request for "host.dom".
         Sign new request by received certificate and private key.
 
-usage: ssl_crtd -c -s ssl_store_path\n -n new_serial_number
+usage: ssl_crtd -c -s ssl_store_path\n
     -c                   Init ssl db directories and exit.
-    -n new_serial_number HEX serial number to use when initializing db.
-                         The default value of serial number is
-                         the number of seconds since Epoch minus 1200000000
 
-usage: ssl_crtd -g -s ssl_store_path
-    -g                   Show current serial number and exit.
  \endverbatim
  */
 
@@ -195,13 +183,8 @@ static void usage()
         "-----END RSA PRIVATE KEY-----\n"
         "\tCreate new private key and certificate request for \"host.dom\"\n"
         "\tSign new request by received certificate and private key.\n"
-        "usage: ssl_crtd -c -s ssl_store_path -n new_serial_number\n"
-        "\t-c                   Init ssl db directories and exit.\n"
-        "\t-n new_serial_number HEX serial number to use when initializing db.\n"
-        "\t                     The default value of serial number is\n"
-        "\t                     the number of seconds since Epoch minus 1200000000\n"
-        "usage: ssl_crtd -g -s ssl_store_path\n"
-        "\t-g                   Show current serial number and exit.";
+        "usage: ssl_crtd -c -s ssl_store_path\n"
+        "\t-c                   Init ssl db directories and exit.\n";
     std::cerr << help_string << std::endl;
 }
 
@@ -209,33 +192,36 @@ static void usage()
  \ingroup ssl_crtd
  * Proccess new request message.
  */
-static bool proccessNewRequest(Ssl::CrtdMessage const & request_message, std::string const & db_path, size_t max_db_size, size_t fs_block_size)
+static bool proccessNewRequest(Ssl::CrtdMessage & request_message, std::string const & db_path, size_t max_db_size, size_t fs_block_size)
 {
-    Ssl::CrtdMessage::BodyParams map;
-    std::string body_part;
-    request_message.parseBody(map, body_part);
-
-    Ssl::CrtdMessage::BodyParams::iterator i = map.find(Ssl::CrtdMessage::param_host);
-    if (i == map.end())
-        throw std::runtime_error("Cannot find \"" + Ssl::CrtdMessage::param_host + "\" parameter in request message.");
-    std::string host = i->second;
+    Ssl::CertificateProperties certProperties;
+    std::string error;
+    if (!request_message.parseRequest(certProperties, error))
+        throw std::runtime_error("Error while parsing the crtd request: " + error);
 
     Ssl::CertificateDb db(db_path, max_db_size, fs_block_size);
 
     Ssl::X509_Pointer cert;
     Ssl::EVP_PKEY_Pointer pkey;
-    db.find("/CN=" + host, cert, pkey);
+    std::string &cert_subject = certProperties.dbKey();
 
-    if (!cert || !pkey) {
-        Ssl::X509_Pointer certToSign;
-        Ssl::EVP_PKEY_Pointer pkeyToSign;
-        Ssl::readCertAndPrivateKeyFromMemory(certToSign, pkeyToSign, body_part.c_str());
+    db.find(cert_subject, cert, pkey);
 
-        Ssl::BIGNUM_Pointer serial(db.getCurrentSerialNumber());
+    if (cert.get()) {
+        if (!Ssl::certificateMatchesProperties(cert.get(), certProperties)) {
+            // The certificate changed (renewed or other reason).
+            // Generete a new one with the updated fields.
+            cert.reset(NULL);
+            pkey.reset(NULL);
+            db.purgeCert(cert_subject);
+        }
+    }
 
-        if (!Ssl::generateSslCertificateAndPrivateKey(host.c_str(), certToSign, pkeyToSign, cert, pkey, serial.get()))
+    if (!cert || !pkey) {
+        if (!Ssl::generateSslCertificate(cert, pkey, certProperties))
             throw std::runtime_error("Cannot create ssl certificate or private key.");
-        if (!db.addCertAndPrivateKey(cert, pkey) && db.IsEnabledDiskStore())
+
+        if (!db.addCertAndPrivateKey(cert, pkey, cert_subject) && db.IsEnabledDiskStore())
             throw std::runtime_error("Cannot add certificate to db.");
     }
 
@@ -243,7 +229,7 @@ static bool proccessNewRequest(Ssl::CrtdMessage const & request_message, std::st
     if (!Ssl::writeCertAndPrivateKeyToMemory(cert, pkey, bufferToWrite))
         throw std::runtime_error("Cannot write ssl certificate or/and private key to memory.");
 
-    Ssl::CrtdMessage response_message;
+    Ssl::CrtdMessage response_message(Ssl::CrtdMessage::REPLY);
     response_message.setCode("OK");
     response_message.setBody(bufferToWrite);
 
@@ -260,12 +246,10 @@ static bool proccessNewRequest(Ssl::CrtdMessage const & request_message, std::st
 int main(int argc, char *argv[])
 {
     try {
-        int serial = (getCurrentTime() -  1200000000);
         size_t max_db_size = 0;
         size_t fs_block_size = 2048;
-        char c;
+        int8_t c;
         bool create_new_db = false;
-        bool show_sn = false;
         std::string db_path;
         // proccess options.
         while ((c = getopt(argc, argv, "dcghvs:M:b:n:")) != -1) {
@@ -281,11 +265,6 @@ int main(int argc, char *argv[])
             case 's':
                 db_path = optarg;
                 break;
-            case 'n': {
-                std::stringstream sn_stream(optarg);
-                sn_stream >> std::hex >> serial;
-                break;
-            }
             case 'M':
                 if (!parseBytesOptionValue(&max_db_size, optarg)) {
                     throw std::runtime_error("Error when parsing -M options value");
@@ -298,9 +277,6 @@ int main(int argc, char *argv[])
             case 'c':
                 create_new_db = true;
                 break;
-            case 'g':
-                show_sn = true;
-                break;
             case 'h':
                 usage();
                 exit(0);
@@ -311,23 +287,21 @@ int main(int argc, char *argv[])
 
         if (create_new_db) {
             std::cout << "Initialization SSL db..." << std::endl;
-            Ssl::CertificateDb::create(db_path, serial);
+            Ssl::CertificateDb::create(db_path);
             std::cout << "Done" << std::endl;
             exit(0);
         }
 
-        if (show_sn) {
-            Ssl::CertificateDb db(db_path, 4096, 0);
-            std::cout << db.getSNString() << std::endl;
-            exit(0);
-        }
         {
-            Ssl::CertificateDb::check(db_path, max_db_size);
+            Ssl::CertificateDb::check(db_path, max_db_size, fs_block_size);
         }
+        // Initialize SSL subsystem
+        SSL_load_error_strings();
+        SSLeay_add_ssl_algorithms();
         // proccess request.
         for (;;) {
             char request[HELPER_INPUT_BUFFER];
-            Ssl::CrtdMessage request_message;
+            Ssl::CrtdMessage request_message(Ssl::CrtdMessage::REQUEST);
             Ssl::CrtdMessage::ParseResult parse_result = Ssl::CrtdMessage::INCOMPLETE;
 
             while (parse_result == Ssl::CrtdMessage::INCOMPLETE) {
@@ -352,3 +326,4 @@ int main(int argc, char *argv[])
     }
     return 0;
 }
+