]> git.ipfire.org Git - thirdparty/squid.git/blobdiff - src/ssl/ssl_crtd.cc
SourceFormat Enforcement
[thirdparty/squid.git] / src / ssl / ssl_crtd.cc
index 6ba0194448c9cfd335daac8fadf57e78cfe64884..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 "config.h"
+#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,18 +65,12 @@ 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
  */
 
-#define CERT_BEGIN_STR "-----BEGIN CERTIFICATE"
 static const char *const B_KBYTES_STR = "KB";
 static const char *const B_MBYTES_STR = "MB";
 static const char *const B_GBYTES_STR = "GB";
@@ -140,7 +127,7 @@ static bool parseBytesOptionValue(size_t * bptr, char const * value)
     char const * number_end = value;
 
     while ((*number_end >= '0' && *number_end <= '9')) {
-        number_end++;
+        ++number_end;
     }
 
     std::string number(number_begin, number_end - number_begin);
@@ -196,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;
 }
 
@@ -210,77 +192,34 @@ 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;
-    Ssl::X509_Pointer certToMimic;
-    
-    const char *s;
-    std::string cert_subject;
-    if ((s = strstr(body_part.c_str(), CERT_BEGIN_STR))) {
-        s += strlen(CERT_BEGIN_STR);
-        if ((s = strstr(s, CERT_BEGIN_STR))) {
-            Ssl::readCertFromMemory(certToMimic, s);
-            if (certToMimic.get()) {
-                char buf[1024];
-                cert_subject = X509_NAME_oneline(X509_get_subject_name(certToMimic.get()), buf, sizeof(buf));
-            }
-        }
-    }
-
-    if (cert_subject.empty())
-        cert_subject = "/CN=" + host;
-
-    i = map.find(Ssl::CrtdMessage::param_SetValidAfter);
-    if (i != map.end() && strcasecmp(i->second.c_str(), "on") == 0)
-        cert_subject.append("+SetValidAfter=on");
-    
-    i = map.find(Ssl::CrtdMessage::param_SetValidBefore);
-    if (i != map.end() && strcasecmp(i->second.c_str(), "on") == 0)
-        cert_subject.append("+SetValidBefore=on");
-
-    i = map.find(Ssl::CrtdMessage::param_SetCommonName);
-    if (i != map.end()) {
-        cert_subject.append("+SetCommonName=");
-        cert_subject.append(i->second);
-    }
+    std::string &cert_subject = certProperties.dbKey();
 
     db.find(cert_subject, cert, pkey);
 
-    if (cert.get() && certToMimic.get()) {
-        if (!Ssl::ssl_match_certificates(cert.get(), certToMimic.get())) {
+    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 (!cert || !pkey) {
-        Ssl::X509_Pointer certToSign;
-        Ssl::EVP_PKEY_Pointer pkeyToSign;
-        Ssl::readCertAndPrivateKeyFromMemory(certToSign, pkeyToSign, body_part.c_str());
-
-        Ssl::BIGNUM_Pointer serial(db.getCurrentSerialNumber());
-
-        if (certToMimic.get()) {
-            Ssl::generateSslCertificate(certToMimic, certToSign, pkeyToSign, cert, pkey, serial.get(), map);
-        }
-        else 
-            if (!Ssl::generateSslCertificateAndPrivateKey(host.c_str(), certToSign, pkeyToSign, cert, pkey, serial.get()))
-                throw std::runtime_error("Cannot create ssl certificate or private key.");
+        if (!Ssl::generateSslCertificate(cert, pkey, certProperties))
+            throw std::runtime_error("Cannot create ssl certificate or private key.");
 
         if (!db.addCertAndPrivateKey(cert, pkey, cert_subject) && db.IsEnabledDiskStore())
             throw std::runtime_error("Cannot add certificate to db.");
@@ -290,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);
 
@@ -307,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) {
@@ -328,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");
@@ -345,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);
@@ -358,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) {
@@ -399,3 +326,4 @@ int main(int argc, char *argv[])
     }
     return 0;
 }
+